Comparer une chaine vide en C

Résolu
valgoku Messages postés 187 Date d'inscription   Statut Membre Dernière intervention   -  
mamiemando Messages postés 33772 Date d'inscription   Statut Modérateur Dernière intervention   -
Bonjour,

J'ai un probleme lors de ma comparaison de chaine de caractere.

J'aimerai que la comparaison compare un élément de mon tableau pour savoir s'il il est vide ou pas .

Le probleme c'est que je n'arrive pas à trouver comment faire.

Car "\o" -> yen a chaque fin de chaine
"\n" -> ca marche pas

Je ne sais que faire .

Je vous mets un bout de code pour m'éclairer, car ce probleme est tres crucial dans mon exercice.

#include <stdio.h>
#include <stdlib.h>
#include <string>

struct mots{
char mot[5];
};

struct mots MOT[5];

int main(){
int i=0;
char moto[5];

for(i=0;i<4;i++){ // ici 4 est fait exprès pour ne pas écrire dans la dernière case
printf("Mot ??? \n");
gets(moto);
strcpy(MOT[i].mot,moto);
}
for(i=0;i<4;i++){ // affichage de ce que je viens d'écrire
printf("MOT : %s \n", MOT[i].mot);
}
fflush(stdin);
for(i=0;i<5;i++){ // et la je commence la comparaison
if(( strcmp(MOT[i].mot,"\o")!=0){ <----- PROBLEME A RESOUDRE
printf("pas possible car déjà utilisé\n");
system("pause");
}
else{
printf("MOT ???\n");
fflush(stdin);
gets(moto);
strcpy(MOT[i].mot,moto);
}
}
for(i=0;i<5;i++){ //affichage de nouveau mais avec les 5 cases du tableau
printf("MOT : %s \n", MOT[i].mot);
}
system("pause");
return 0;
}

Merci beaucoup de m'aider, et si possible sans pointeur, car en cours on en est pas encore là.

5 réponses

mamiemando Messages postés 33772 Date d'inscription   Statut Modérateur Dernière intervention   7 882
 
Il faut très clairement choisir la deuxième solution si tu veux écrire ton programme "sérieusement". Une chaîne de caractère classique est un tableau (un bloc mémoire).

Chaque "case" fait la taille d'un octet, interprété comme un char (d'où la notation char[] ou char *). Par convention, on considère que le caractère '\0' arrête la fin de cette chaîne. Dans ton code tu écris '\o' ce qui n'a rien à voir avec '\0' (backslash 0). '\0' (qui en fait est un octet dont tous les bits sont nuls) désigne le caractère de fin de chaîne. C'est notamment lui qui permet aux fonctions printf, strlen etc... de savoir quand s'arrêter de lire des octets en mémoire (sans ce caractère, ces fonctions dépasseraient la chaîne et atteindrait une zone mémoire qui déclencherait une erreur de segmentation).

Note que quand tu écris :

char *string = "plop";


... en réalité tu manipules un bloc mémoire de 5 chars :

- string[0] == 'p'
- string[1] == 'l'
- string[2] == 'o'
- string[3] == 'p'
- string[4] == '\0'

Ainsi on pourrait écrire :

if(chaine[0] == '\0') {
  printf("La chaîne est vide\n");
} else {
  printf("La chaîne est non vide et contient [%s]\n",chaine);
}


En fait, ce qu'il faut bien voir c'est que 'p', 'l', ... sont autant de constantes codées sur un octet et qui associent chaque caractère et son code ascii
http://www.manpagez.com/man/7/ascii/

C'est la raison pour laquelle par exemple 'p' == 112 (cf lien précédent). Pour s'en convaincre :

#include <stdio.h>

int main(){
  char c;
  c = 112;
  printf("%c\n",c);
  c = 'p';
  printf("%c\n",c);
  return 0;
}


En particulier le caractère fin de chaîne, noté '\0', vaut en réalité 0.

D'autre part, si tu révises ton cours sur les pointeurs tu verras que chaine[i] équivaut à *(chaine+i). En particulier chaine[0] == *(chaine + 0) = *chaine. Comme en C un if est vrai si la valeur passée entre parenthèse du if est non nulle, on peut donc directement écrire :

if(*chaine) { // *chaine <=> chaine[0] et '\0' <=> 0
  printf("La chaîne est vide\n");
} else {
  printf("La chaîne est non vide et contient [%s]\n",chaine);
}


... ou en encore plus compressé, avec l'autre syntaxe du if ... else ... du C :

*chaine ?
  printf("La chaîne est vide\n") :
  printf("La chaîne est non vide et contient [%s]\n",chaine);


Alors maintenant, revenons à la version avec strlen :

if(strlen(chaine)){ // si la longueur est non nulle, ce test est vrai
  printf("La chaîne est non vide\n");
}else{
  printf("La chaîne est vide\n");
}


C'est très mauvais pour la raison suivante : imagine que ta chaîne fasse 100000 chars. La fonction strlen va devoir parcourir toute la chaîne, ce qui va l'occuper un petit moment avant de renvoyer 100000 (+1). C'est bien dommage, car en fait la seule chose qu'on a besoin de savoir, c'est si le premier caractère vaut '\0' ou non, ce qui est immédiat au lieu d'avoir un coût proportionnel à la longueur de la chaîne. Alors certes la version avec strlen est "plus lisible" quand on débute en C. Mais il faut l'oublier le plus vite possible !

Bonne chance
3
fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention   1 846
 
Salut,

Car "\o" -> yen a chaque fin de chaine
Je reformulerais plutôt en disant, qu'il faut en mettre en fin de chaîne. Car il y a des fois où ça n'est pas le cas, ce qui engendre des bugs. De plus attention il s'agit de '\0' (dont le code ascii est 0) et non '\o'.

#include <string>
En C, c'est string.h et non string.

gets(moto);
Il ne faut pas utiliser gets. Utilise plutôt fgets. Par exemple, fgets(moto, sizeof moto, stdin);

strcpy(MOT[i].mot,moto);
Autant mettre directement fgets(MOT[i].mot,sizeof MOT[i].mot,stdin);

fflush(stdin);
Cette instruction provoque un comportement indéfini et ne doit donc pas être utilisé. Pour vider le cache, il faut le faire manuellement (vider jusqu'à l'obtention d'un '\n'). De plus, il faut le faire que si on est sûr qu'il y a des informations dans le cache sinon on aura une boucle infinie.

system("pause");
Utilise plutôt getchar(); car system("pause") est non portable.

if(( strcmp(MOT[i].mot,"\o")!=0){
Pour comparer une chaîne s1 et s2, il suffit de mettre : strcmp(s1,s2); Cela renvoie 0 lorsque les deux chaînes sont égales. Il faut faire attention au \n éventuellement stocké dans les chaînes.

Pour vérifier qu'une chaîne est nulle, tu peux faire :
if(strcmp(MOT[i].mot,"")==0); mais attention à avoir enlevé le '\n' de ta chaîne auparavant.
Ou sinon, les deux solutions apportées par loupius.

Cdlt,
1
loupius Messages postés 697 Date d'inscription   Statut Membre Dernière intervention   148
 
Pour savoir si une chaîne est vide, tu peux faire:
- un 'strlen(chaine)' qui vaut 0 si la chaîne est vide,
- un test 'chaine[0]' qui vaut 0 si la chaîne est vide.
Nota, la deuxième solution est plus rapide mais peut-être moins lisible.
Bonne continuation.
0
valgoku Messages postés 187 Date d'inscription   Statut Membre Dernière intervention   47
 
Probleme résolu !

Merci :)

Et surtout merci pour les explications ;)
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
mamiemando Messages postés 33772 Date d'inscription   Statut Modérateur Dernière intervention   7 882
 
Pas de soucis, à bientôt ;-)
0