Lecture chaîne de char avec espace

Résolu
mdao032 -  
fiddy Messages postés 441 Date d'inscription   Statut Contributeur Dernière intervention   -
Bonjour,

Vu que je n'ai pas un très bon niveau en c, j'ai écrit mon code et je demande votre aide pour me signaler si vous constater d'éventuelle incohérences.

Voici mon problème de départ :
Ecrire un programme qui affiche une invite et lit une chaîne de caractère contenant des espaces. Le programme ne doit pas être sujet à buffer overflow.

Mon programme :
char * lire_chaine(char * message){
printf("%s", message);
int MIN_BUFFER = 7;
size_t taillbuff = MIN_BUFFER;
char *buffer = malloc(taillbuff);
if (buffer == NULL) return NULL; // échec de malloc()
char *p;
for(p=buffer ; (*p=getchar()) != '\n' && *p!=EOF ; ++p)
if (p - buffer == taillbuff - 1) { // buffer plein,
p = realloc(buffer, taillbuff *= 2); //on le double
if (p == NULL) { // échec de realloc()
free(buffer);
return NULL;
}
else buffer = p; //bloc réalloué != buffer
p += taillbuff/2 - 1; // p reprend sa place dans
} // la nouvelle zone
  • p = 0; p = realloc(buffer, p - buffer + 1); //réajustement if (p == NULL) { // échec de realloc free(buffer); return NULL; } else return p;}int main (int argc, char *argv[]){ char chaine[100]; printf("entrez votre chaine de char : \n"); scanf("%[^\n]%*c", chaine); printf("la chaine de char lue est : \n"); lire_chaine(chaine); return 0;}


Le programme compile bien et lit les chaînes que je met en entrée

Je vous remercie d'avance.

3 réponses

  1. nocram18 Messages postés 531 Statut Membre 26
     
    Yo,

    C'est du C++ ?

    Je commence aussi donc je pourrais pas d'aider la mais ce que je te conseille déjà c'est d'apprendre à un indenter c'estg plus beau et lisible surtout quand tu partage apres tes problemes :D.
    0
    1. mdao032
       
      Bonjour Nocram,
      Non en fait c'est du C et non C++ ;)
      Merci pour ta proposition concernant l'indentation :)
      0
    2. nocram18 Messages postés 531 Statut Membre 26
       
      Ah oki donc les commentaires c'est

      c=

      /* Ceci est un commentaire C */

      et c++=

      action quelconque // Ceci est un commentaire C++
      action suivante

      Petit conseil ^^ bonne chance dans ta quête
      0
    3. fiddy Messages postés 441 Date d'inscription   Statut Contributeur Dernière intervention   1 847
       
      Cela dépend de la norme.
      Vrai en C89/90. Plus en C99.

      Note : en C++. /**/ est également autorisé :-).
      0
    4. nocram18 Messages postés 531 Statut Membre 26 > fiddy Messages postés 441 Date d'inscription   Statut Contributeur Dernière intervention  
       
      Dac :pouce:
      Merci je vais retenir, toujours bon dans la culture geek :D
      0
    5. mdao032
       
      merci Nocram18 ;),
      Bon courage à toi aussi surtout
      Cdt.
      0
  2. fiddy Messages postés 441 Date d'inscription   Statut Contributeur Dernière intervention   1 847
     
    Bonjour,

    Je n'ai pas tout lu.
    Mais déjà : scanf("%[^\n]%*c", chaine
    Risque de buffer overflow. Utilise plutôt : scanf("%99[^\n]", chaine);

    Note :pourquoi ne pas utiliser fgets ?
    0
    1. mdao032
       
      Bonjour Fiddy,
      Sans le savoir plus précisément, je pensais justement éviter le buffer overflow quand je mettais scanf("%[^\n]%*c", chaine). Merci d'avoir corrigé la partie,... je change tout de suite.

      Aussi concernant le fgets, j'avais lu des trucs là dessus, mais j'avais pas trop compris son implémentation :( . La compilation me retournait des erreurs.
      0
    2. mdao032
       
      re fiddy,
      je te remercie pour l'aide apportée.
      Tes interventions me font vraiment progresser dans mon apprentissage.
      Le "fgets", je réfléchie là dessus un moment, je reviendrai par suite.
      0
  3. fiddy Messages postés 441 Date d'inscription   Statut Contributeur Dernière intervention   1 847
     
    Bonsoir,

    Un retour plus complet que tout à l'heure :
    Attention, à ne pas trop mélanger les déclarations de variables et les instructions.
    Par exemple :
    {
         printf("Salut ");
         int a=5;
         [...]
    }
    

    N'est pas terrible. En C, il vaut mieux (d'ailleurs dans l'ancienne norme, c'est une obligation) mettre les déclarations de variable en début de frame puis après le code.
    Ce qui donne :
    <code c>
    {
    int a=5;
    printf("Salut ");
    [...]
    }

    Dans le main() :
    scanf("%[^\n]%*c", chaine);
    Comme dit dans mon post précédent, c'est sujet au buffer overflow.
    Utilise plutôt fgets(). scanf() est très dangereux lorsque mal utilisé.

    for(p=buffer ; (*p=getchar()) != '\n' && *p!=EOF ; ++p)
    Aucun contrôle de taille. Donc, si l'utilisateur tape une longue chaîne, cela fera planter le programme. Fais intervenir taillbuff dans ta condition de fin.

    buffer = p; //bloc réalloué != buffer
    Inutile. Ton realloc a déjà fait le job.

    p = 0;
    Que souhaites-tu faire ? Plutôt *p=0; (ou *p='\0'); afin de mettre le \0 en fin de chaîne, non ?

    Cdlt,
    0
    1. mdao032
       
      rebonjour fiddy,
      merci pour le point sur l'ordre des des déclarations et des instructions.
      En réalité, d'habitude j'ordonne afin de retrouver facilement si j'ai déjà déclaré une variable ou pas.

      La partie sur scanf est je pense assez claire maintenant après cette explication :)

      Bien vu pour le "p = 0;"
      En fait dans mon code, c'est exactment *p= 0 (comme dans première proposition).
      C'est collant mon code, que mon étoile a été remplacé par le "point noir" que tu peux constater juste avant le p.

      Passez une très bonne journée fiddy :)
      0
    2. fiddy Messages postés 441 Date d'inscription   Statut Contributeur Dernière intervention   1 847
       
      Pas de problème. N'hésite pas si tu as des questions :-).
      Bonne journée à toi.
      0