Comparer une chaine vide en C

Résolu/Fermé
valgoku Messages postés 187 Date d'inscription lundi 17 avril 2006 Statut Membre Dernière intervention 22 janvier 2013 - 12 janv. 2010 à 22:02
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 - 20 janv. 2010 à 16:52
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 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
13 janv. 2010 à 00:26
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