Bonjour tout le monde,
Tout � coup j'ai eu une subite envie de faire une petite fonction permettant de lire une cha�nes de caract�res de taille variable sur stdin (et plus g�n�ralement, sur un FILE *).
Le comportement de la fonction est le suivant :
- La fonction prend un param�tre, le flux (FILE *) sur lequel la cha�ne de caract�res sera lue
- La fonction retournera un char *, l'adresse du premier caract�re lu ou NULL si une erreur survient
- Si une erreur survient, le flux sera consomm� (= lecture des caract�res juqu'� ce qu'on tombe sur \n ou EOF)
La signature de la fonction sera donc la suivante : char * get_line(FILE *);
N'ayant pas trouv� grand chose sur la lecture de cha�nes de caract�res de taille variable, j'ai du faire chauffer mes m�ninges et trouver un algorithme, esp�rons qu'il soit potable.
Ne sachant pas trop comment �crire cela en pseudo-code, je vais le faire avec de bonnes vieilles phrases.
Premi�re question, est-ce que cet algorithme semble correct, potable ?
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9 /* D'abord on va allouer un espace mémoire de taille arbitraire (32 octets) pouvant stocker des char. Si l'allocation a réussie, on va pouvoir lire le flux caractère par caractère. Tant qu'on ne rencontre pas \n ou EOF : Si l'espace alloué n'est pas suffisant, on va augmenter la taille de l'espace précédemment alloué (+ 32 octets). Si l'allocation a échouée, on va libérer l'espace précédemment alloué, consommer le flux et sortir de la boucle. S'il n'y a pas eu d'erreur d'allocation, on rajoute le \0 à la chaîne de caractères. On retourne un pointeur sur le premier élément de l'espace alloué ou NULL s'il y a eu une erreur d'allocation. */
Pour la r�allocation, j'ai vu certains codes qui doublaient la taille de l'espace allou� au lieu de l'agrandir d'un nombre fixe d'octets. Y a-t-il une m�thode pr�f�rable � l'autre, ou est-ce d�pendant de la situation ? Et si c'est d�pendant de la situation, quelle m�thode r�pondrait le mieux � la probl�matique actuelle ?
Passons maintenant � l'impl�mentation en C :
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11
12 /* /Document/C/str/mstr.h */ #ifndef MSTR_H_INCLUDED #define MSTR_H_INCLUDED #include <stdlib.h> #include <stdio.h> #define MSTR_ALLOC_BLOCK_SIZE 32 char * get_line(FILE *); #endif /* MSTR_H_INCLUDED */Qu'en pensez-vous ?
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 /* /Document/C/str/mstr.c */ #include "mstr.h" char * get_line(FILE * stream) { /* Allocation du bloc de depart */ size_t size = MSTR_ALLOC_BLOCK_SIZE; char * s = malloc(size); /* Si l'allocation a reussie */ if(s != NULL) { size_t i; int c; /* On lit tous les caractères jusqu'a \n ou EOF */ for(i = 0; (c = fgetc(stream)) != '\n' && c != EOF; i++) { /* Si l'espace alloue n'est plus suffisant on essaie de l'agrandir */ if(i >= size) { char * tmp = realloc(s, size += MSTR_ALLOC_BLOCK_SIZE); /* Si l'allocation a reussie, on recupere le pointeur Sinon on libere l'espace precedemment alloue, on vide le buffer du flux et on sort du while */ if(tmp != NULL) { s = tmp; } else { free(s); s = NULL; while((c = fgetc(stream)) != '\n' && c != EOF) { } break; } } s[i] = (char)c; } /* On ajoute le \0 terminal a la chaine recuperee */ if(s != NULL) { s[i] = '\0'; } } return s; }
Le code semble fonctionner. Semble car j'avoue avoir un peu de mal pour les tests unitaires.. Est-il possible de faire �chouer volontairement un malloc/realloc ?
Derni�re petite chose, j'ai eu beau lutter, un warning persiste � la compilation.. J'utilise code::block avec les options de compilations suivantes (GNU/CSS compiler) : -Wall -Wextra -ansi -O -Wwrite-strings -Wstrict-prototypes -Wuninitialized -Wunreachable-code
Et voici le warning en question :
J'ai demand� � une connaissance de compiler, il a utilis� le m�me compilateur (mais je ne sais pas si c'est la m�me version par contre) avec les m�mes options, et point de warning chez lui.
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5 /* \Documents\C\str\mstr.c||In function `get_line':| \Documents\C\str\mstr.c|10|warning: will never be executed| ||=== Build finished: 0 errors, 1 warnings ===| */
Merci d'avoir pris le temps de me lire et merci d'avance pour vos futures r�ponses. =)
Cordialement, Krystal_.
Partager