Lecture chaîne de char avec espace
Résolu
mdao032
-
fiddy Messages postés 11069 Date d'inscription Statut Contributeur Dernière intervention -
fiddy Messages postés 11069 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 :
Le programme compile bien et lit les chaînes que je met en entrée
Je vous remercie d'avance.
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.
A voir également:
- Lecture chaîne de char avec espace
- Espace insécable - Guide
- Espace de stockage gmail plein - Guide
- Chaine tnt gratuite sur mobile - Guide
- Espace de stockage google - Guide
- Confirmation de lecture whatsapp - Guide
3 réponses
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.
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.
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 ?
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 ?
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.
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.
Son implémentation est très simple :
fgets(chaine, sizeof chaine, stdin);
Après, il faut vérifier s'il y a un '\n' dans le buffer. Si oui, il faut le supprimer sinon, il faut vider le buffer clavier.
Un petit article : http://fiddy.free.fr/blog/index.php?post/2008/11/22/Le-C%2C-pas-si-facile-que-%C3%A7a
fgets(chaine, sizeof chaine, stdin);
Après, il faut vérifier s'il y a un '\n' dans le buffer. Si oui, il faut le supprimer sinon, il faut vider le buffer clavier.
Un petit article : http://fiddy.free.fr/blog/index.php?post/2008/11/22/Le-C%2C-pas-si-facile-que-%C3%A7a
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 :
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,
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,
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 :)
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 :)
Non en fait c'est du C et non C++ ;)
Merci pour ta proposition concernant l'indentation :)
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
Vrai en C89/90. Plus en C99.
Note : en C++. /**/ est également autorisé :-).
Merci je vais retenir, toujours bon dans la culture geek :D
Bon courage à toi aussi surtout
Cdt.