Lecture chaîne de char avec espace

Résolu/Fermé
mdao032 - Modifié par mdao032 le 11/05/2016 à 14:09
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 - 12 mai 2016 à 16:13
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.

A voir également:

3 réponses

nocram18 Messages postés 471 Date d'inscription vendredi 26 avril 2013 Statut Membre Dernière intervention 16 juillet 2017 25
11 mai 2016 à 13:52
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
Bonjour Nocram,
Non en fait c'est du C et non C++ ;)
Merci pour ta proposition concernant l'indentation :)
0
nocram18 Messages postés 471 Date d'inscription vendredi 26 avril 2013 Statut Membre Dernière intervention 16 juillet 2017 25
11 mai 2016 à 14:05
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
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
Modifié par fiddy le 11/05/2016 à 14:36
Cela dépend de la norme.
Vrai en C89/90. Plus en C99.

Note : en C++. /**/ est également autorisé :-).
0
nocram18 Messages postés 471 Date d'inscription vendredi 26 avril 2013 Statut Membre Dernière intervention 16 juillet 2017 25 > fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022
11 mai 2016 à 14:47
Dac :pouce:
Merci je vais retenir, toujours bon dans la culture geek :D
0
merci Nocram18 ;),
Bon courage à toi aussi surtout
Cdt.
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
11 mai 2016 à 13:54
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
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
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
11 mai 2016 à 14:36
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
0
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
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
11 mai 2016 à 22:57
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
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
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
12 mai 2016 à 16:13
Pas de problème. N'hésite pas si tu as des questions :-).
Bonne journée à toi.
0