Lecture chaîne de char avec espace

Résolu
mdao032 -  
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 :
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   Statut Membre Dernière intervention   25
 
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
mdao032
 
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   Statut Membre Dernière intervention   25
 
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   Statut Contributeur Dernière intervention   1 846
 
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   Statut Membre Dernière intervention   25 > fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention  
 
Dac :pouce:
Merci je vais retenir, toujours bon dans la culture geek :D
0
mdao032
 
merci Nocram18 ;),
Bon courage à toi aussi surtout
Cdt.
0
fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention   1 846
 
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
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
fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention   1 846
 
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
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
fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention   1 846
 
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
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
fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention   1 846
 
Pas de problème. N'hésite pas si tu as des questions :-).
Bonne journée à toi.
0