Lire une chaîne de caractères de taille variable sur stdin

Voir le sujet précédent Voir le sujet suivant Aller en bas

Lire une chaîne de caractères de taille variable sur stdin

Message  Krystal le Mar 23 Sep 2008 - 0:55

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.
Code:
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.

Première question, est-ce que cet algorithme semble correct, potable ?
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:
/* /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 */

Code:
/* /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;
}

Qu'en pensez-vous ?
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 :
Code:
\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 ===|

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.

Merci d'avoir pris le temps de me lire et merci d'avance pour vos futures réponses. :)

Cordialement, Krystal.

Krystal

Messages : 2
Date d'inscription : 23/09/2008

Voir le profil de l'utilisateur

Revenir en haut Aller en bas

Re: Lire une chaîne de caractères de taille variable sur stdin

Message  -ed- le Mar 23 Sep 2008 - 21:08

Bonjour,

Je t'ai répondu sur DVP.

A+
Emmanuel

-ed-
Admin
Admin

Messages : 289
Date d'inscription : 26/05/2008
Age : 60
Localisation : Paris 6eme arrondissement (75, France)

Voir le profil de l'utilisateur http://bien-programmer.fr

Revenir en haut Aller en bas

Re: Lire une chaîne de caractères de taille variable sur stdin

Message  Krystal le Mar 23 Sep 2008 - 21:40

Merci beaucoup.

Voici le lien du fil sur developpez pour ceux qui seraient intéressés : http://www.developpez.net/forums/d617984/c-cpp/c/lire-chaine-caracteres-taille-variable-stdin/

Bonne soirée.

Krystal

Messages : 2
Date d'inscription : 23/09/2008

Voir le profil de l'utilisateur

Revenir en haut Aller en bas

Re: Lire une chaîne de caractères de taille variable sur stdin

Message  -ed- le Mer 24 Sep 2008 - 12:12

Krystal a écrit:Voici le lien du fil sur developpez pour ceux qui seraient intéressés : http://www.developpez.net/forums/d617984/c-cpp/c/lire-chaine-caracteres-taille-variable-stdin/
Oui, il suffisait de clicker sur ma réponse !

-ed-
Admin
Admin

Messages : 289
Date d'inscription : 26/05/2008
Age : 60
Localisation : Paris 6eme arrondissement (75, France)

Voir le profil de l'utilisateur http://bien-programmer.fr

Revenir en haut Aller en bas

Re: Lire une chaîne de caractères de taille variable sur stdin

Message  Contenu sponsorisé Aujourd'hui à 21:18


Contenu sponsorisé


Revenir en haut Aller en bas

Voir le sujet précédent Voir le sujet suivant Revenir en haut

- Sujets similaires

 
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum