comment je fais pour récupérer toute la ligne alors ? Je me servais de \n comme séparateur.
fgets() est fait pour lire une ligne entière.
http://emmanuel-delahaye.developpez....tes.htm#saisie
http://emmanuel-delahaye.developpez....s.htm#fichiers
cette fonction ne marche pas :
buf1 contient après le fgets() :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76 double **lecture_csv(const char *fichier, int nbl, int nbc, char separateur, int *ligne_tableau) { FILE *f; char *buf1,c; int ligne, i, nb_char, nb_sep; long pos; double **sortie; if ( !(sortie=(double **)malloc(sizeof(double *)*nbl)) ) erreur_memoire(); f=fopen(fichier,"r"); if (f) { /* On initialise la ligne courante du tableau */ ligne=0; for(i=0;i<=nbl;i++) { pos=ftell(f); /* On calcule le nombre de caractères de la ligne */ c=fgetc(f); nb_char=1; if (c!=separateur) nb_sep=0; else nb_sep=1; while(c!='\n' && c!=EOF) { if (c==separateur) nb_sep++; c=fgetc(f); nb_char++; } /* on écrit la ligne contenue dans le buffer dans le tableau de sortie. Si la ligne est vide on n'imcrémente pas ligne donc on réécrira dessus au prochain tour de boucle */ if ( nb_sep==(nbc-1) ) { fseek(f,pos,SEEK_SET); if ( !(buf1=(char *)malloc(sizeof(char)*(nb_char))) ) erreur_memoire(); //fscanf(f,"%s\n",buf1); /* on récupére dans le buffer la ligne courante */ fgets(buf1,sizeof(buf1),f);printf("%s\n",buf1); buf1=bouche_trous(buf1,separateur,'0'); if ( !(sortie[ligne]=(double *)malloc(sizeof(double)*(nbc+1))) ) erreur_memoire(); enregistre_ligne(sortie,buf1,ligne,separateur); free(buf1); ligne++; } } fclose(f); } else { fichier_non_trouve(); if (ligne_tableau) *ligne_tableau=0; return NULL; } if ( !(sortie=(double **)realloc(sortie,sizeof(double *)*ligne)) ) erreur_memoire(); if (ligne_tableau) *ligne_tableau=ligne; return sortie; }
1,3
,5,
2,4
,6,
3,5
,7,
4,6
,8,
5,7
,9,
6,8
,10
7,9
,11
apperemment c'est un problèmle dans la taille que j'alloue.
edit : au niveau du prototype de fgets, ne deuxième paramètre est le nombre de caractère à lire ou la taille ? En gros je mets sizeof(char)*n ou n ? (dans les exemple des liens c'est avec sizeof mais le prototype propose un int et non un size_t)
le problème est-il de mettre les différents éléments de ceci :
dans des tableaux ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 1,"nom1",5,"colonne4.1" 2,"nom22",7,"colonne4.2" 2,"nonpl",7,"reine" 7,"nom7",17,"col4.7" 8,"nom8765432101234567890",19,"colonne4.8" 9,"nom9",21,"colonne4.9" ,"",," " 11,"nom11",25,"colonne4.11" 12,"nom12",27,"col4.12" 14,"nom14",31,"colonne4.14" 15,"nom15",33,"colonne4.15"
Comme je l'écris dans d'autres discussions, je préfère toujours la solution de la lecture in extenso du fichier dans un tampon temporaire, puis son analyse caractère à caractère au moyen d'un UCHAR*.
C'est un peu trivial mais plus rapide et beaucoup plus simple à déboguer et à maintenir.
Dans ce cas où les chaînes sont majoritaires dans le fichier je suggère de garder le tampon provisoire et de ne mettre que des pointeurs sur celui-ci dans les tableaux.
ok pour fgets (c'est que j'avais vu un exemple sur le net avec un nombre de caractère et non un sizeof...).
@Stabia : je ne comprend pas trop la solution : Le but est de stocké un ensemble de nombres contenu dans un csv dans un tableau (alloué dynamiquement). Au début je voulais prendre en compte les chaine de caractères mais ça m'est apparu compliqué que se soit au niveau de l'allocation ou de l'utilisation après.
j'ai écris cela en 20 minutes, je n'ai rien testé.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99 struct CHAMPS { char* ptNom; int val; char* ptPlus; }; fichier = fopen(nomFichier, "r"); if(!fichier) goto erreur; lg = fseek(fichier, 0, SEEK_END); if(!lg) goto erreur; fseek(fichier, 0, SEEK_SET); tp = new unsiqned char[lg+1]; if(!tp) goto erreur; val = fread(tp, 1, lg, fichier); if(val != lg) goto erreur; fclose(fichier); tp[lg] = 0; nbSeparateur = 0; dansChaine = 0; for(int b = 0 ; b < lg ; b++) { car = tp[b]; if(car == ',') // ATTENTION séparateur en dur ! { if(!dansChaine) nbSeparateur++; } else if (car == '"') { dansChaine ^= 1; } // on pourrait ici calculer la longueur totale des chaînes pour // éventuellement faire une recopie dans un autre tampon, mais les quelques // 'séparateurs' et entiers ne prennent pas trop de place. } if(dansChaine) goto erreur; nbIndice = nbSeparateur / nbChamps; // if faudrait vérifier avec modulo tabChamps = new CHAMPS[nbChamps]; if(!ptChamps) goto erreur; decompteur = nbChamps; ptLect = tp; ptChamp = ptLect; typeChamp = -1; // pour savoir ou l'on en est dans la structure champCourant = 0; do { ptFinChamp = strpbrk(ptLect, ",\""); if(!ptFinChamp) goto erreur; ptLect = ptFinChamp + 1; // lire la suite switch(*ptFinChamp) { case ',': if(dansChaine) continue; // une ou plusieurs virgules dans les chaînes // fin d'un champ typeChamp++; switch(typeChamp) { // à adapter selon le nombre et le type de champs case 0: tabChamps[champCourant].ptNom = ptChamp; break; case 1: if(!scanf(ptChamp, "%d", &tabChamps[champCourant].val)) goto erreur; break; case 2; tabChamps[champCourant].ptNom = ptPlus; typeChamp = -1; champCourant++; } break; case '\"": if(dansChaine) { // on sort d'une chaîne *ptFinChamp = 0; } // sinon on entre dans une chaîne et 'ptChamp' va être positioné aprés dansChaine ^= 1; } ptChamp = ptLect; decompteur--; }while(decompteur); return NbChamp; erreur: return -1;
Quelle importance ?
Contrairement à vous je suppose de la part de nos lecteurs un minimum d'intelligence; et je les crédite du désir de comprendre.
Vous feriez mieux de proposer quelque chose, ou de critiquer mon code, ce serait plus constructif et vous éviterait le ridicule de vos agressions incessantes.
1 - Ici, c'est le forum C. Le forum C++, c'est à-coté.
2 - Il y a des débutants qui ont du mal à ne pas confondre ces langages, donc, on s'efforce de réduire la confusion. Et je parle d'expérience, car j'ai commencé mes activités de soutien sur les forums C fin 1998, soit près de 10 ans (après 2 ou 3 ans de remise à niveau, car moi aussi, fort de mon expérience professionnelle d'une dizaine d'années, je croyais tout savoir... Grave erreur, moments difficiles, j'ai survécu !).
3 - Je n'agresse personne, je me contente de relever les inexactitudes, ce qui est le minimum que l'on attend d'un forum sérieux et technique comme celui-ci.
4 - Je ne suis pas responsable du fait que tu ne supportes pas la moindre remarque.
5 - Je ne me permets pas d'attaques personnelles (à part une pointe d'humour sur un certain ratio, mais je sais que l'humour est valeur la moins partagée au monde. Je ne le ferais plus).
6 - Quand aux critiques de codes et aux solutions, les forums C de Developpez en sont remplies (-ed-) ... Et je ne parle pas des forums Usenet c.l.c et f.c.l.c. que j'ai abandonné depuis quelques années...
7 - Ton code étant incomplet et écrit dans un langage qui n'est pas le C, je ne l'ai pas soumis à mon compilateur...
@Stabia : ton code est vraiment plus simple que le mien ? Je pense que c'est une question d'algo, on ne pense pas pareil...et puis les goto...
est-ce que quelqu'un pourrait tester la dernière version de mon code svp (sous windows) ?
http://www.rniamo-developping.prog.fr/C_CSV.zip
soit tout compiler en gtk+ (sources dans 0_src/, include dans 1_inc/) soit juste csv.c et écrire un petit main avec la dernière fonction et un des fichiers du dossier Fichiers_de_tests/.
Oui "Rniamo" je crois que mon code est plus simple que le votre, c'était le but recherché, mais en plus je programme comme cela.
Monsieur Emanuel D.
C / C++ dans le simple cas d'un "new" c'est transparent, qu'est-ce que c'est que cette querelle de chapelle ? le fond du problème c'était de mettre le demandeur sur la voie d'une analyse d'une suite de caractère, c'est tout, c'est vous qui ne cessez de dévier et de m'agresser, je répond, voilà tout, vous en remettez une couche, moi-aussi.
Autoportrait parfait.Je ne suis pas responsable du fait que tu ne supportes pas la moindre remarque
vous voulez que je liste ? avant que vous ne les retiriez !Je n'agresse personne
Tout lecteur ayant une bonne connaissance des subtilités du Français comprend parfaitement qu'il s'agissait d'une agression méprisante.à part une pointe d'humour sur un certain ratio
C'est parce que je l'ai ressenti comme tel, que je vous ai répondu sur le même mode.
Pour élever un peu le débat et cesser cette joute qui doit lasser les lecteurs, peut être faudrait-il ouvrir un forum sur des cas précis d'applications développées, et en parallèle sur la réalité du langage utilisé.
A tord, -et j'ai déjà exprimé que j'avais sans doute beaucoup de mauvaises habitudes- je programme dans un mélange des deux (donc en compilant avec un compilateur C++) ; dans certains cas je pourrais décrire pourquoi, dans d'autre pas.
C'est comme le choix du niveau d'interface (je travaille sous Windows) parfois les M.F.C. parfois non (en fait je préfère).
Mais néanmoins mon expérience peut être utile aux débutants -quitte à leur montrer que ce n'est pas normé- ce que je revendique.
En ce moment je clos un ensemble d'applications pour une Chambre de Commerce (HTLM, C/C++, Java, RealBasic (PC et MAC)), j'ajoute quelques fonctions pour un ensemble d'applications (C/C++) réalisant des calculs de déperditions thermiques, et je commence l'écriture d'un programme d'automates qui commanderont des installations urbaines et doivent communiquer ensemble par GPRS.
Je veux dire par cette énumération de mes programme en cours qu'il y a plusieurs façons de programmer, privilégier le style "scolaire" en production n'est pas forcement la meilleure chose qui soit.
Bien sur, il me serait impossible -déjà par caractère- de travailler avec mes méthodes dans une grosse équipe mais ce n'est pas une raison pour me pas accepter que ces méthodes -archaïques, impures, simplistes, naïves- sont aussi capable de produire des logiciels efficaces et fonctionnels ... et bien souvent 3 fois moins chers !
Mais arrêtez s'il vous plaît vous tuez le langage !
Vous voulez donnez un exemple de goto manque de bol il est mauvais, il montre bien même qu'il n'est pas à la portée des débutants.
Regardez ce que vous écrivez, un problème de lecture ->goto erreur ok. On va voir ce qui est fais dans le label->return -1. Du coup plus de fermeture de fichier à moins que finalement se soit aussi le but recherché...
Je me suis arrêté à cette ligne le reste j'ose à peine l'aborder...
Vous avez raison il eu fallu mettre deux sorties dont l'une fermait le fichier, j'ai écris 80 lignes de code à la volée pour essayer de montrer une solution, je n'ai pas écris le code pour le demandeur, et j'ai clairement indiqué que je n'avais rien testé (ni relu).
ça c'est typiquement les mots de trop qui encombrent et tendent les discussions.Je me suis arrêté à cette ligne le reste j'ose à peine l'aborder.
A quoi cela sert-il ce "nian-nian-nian j'ai trouvé un truc qui marche pas, c'est pourri !" nous savons tous comment se passe l'écriture d'un programme et son débogage, alors inutile de jeter des pierres à celui qui cherche à aider.
ça sert à rien de s'énerver...
même si j'aimerais que quelqu'un teste mon code sous windows, j'ai relu le code de Stabia, et si je comprend bien, tu mets tout en char ? Je ne vois pas l'intérêt de ta structure (qui est le point centrale de ton code malheureusement pour moi). Je ne suis pas sûr que l'on puisse en C (C89 ou C99, pas C++) allouer un tableau avec des cases mémoires de type différent....et puis je me satisfait de nombres (%lf plutôt que %d).
Dans mon exemple je mets dans la structure soit des pointeurs sur une chaîne, soit des entiers, donc chaque éliment de la structure à une taille fixe (dans mon exemple 12 octets), comme j'ai compté le nombre de structures il est facile d'allouer la taille qui convient surtout pas avec 'new' enfin parait-il comme dirait le vieil oncle de Kirikou.Ces colonnes comportent soit des nombres (scannés comme doubles) soit des chaînes de caractères entre " ".
J'ai pris comme base que le fichier était formé de n. fois {"chaîne", entier en représentation alphanumérique, "chaîne"} si ce n'est pas cela c'est très facile à adapter.
Ce code n'est pas complet puisqu'il ne comporte pas la fonction principale ni même l'en-tête de la fonction exemple. Mais je vous assure que c'est un code efficace, maintenant s'il s'agit d'un exercice je ne suis pas sur que votre professeur apprécie la méthode, mais enfin il ne sont pas forcement tous aussi formatés que les codes des manuels.
Bon courage.
ok, j'y suis, merci. En effet ça m'a l'air efficace, je n'ai pas pour l'instant le temps de compléter le codage mais je m'y pencherais. Encore merci.
Partager