Comparer une chaine vide en C

[Résolu/Fermé]
Signaler
Messages postés
187
Date d'inscription
lundi 17 avril 2006
Statut
Membre
Dernière intervention
22 janvier 2013
-
Messages postés
30102
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
17 septembre 2021
-
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

Messages postés
30102
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
17 septembre 2021
7 172
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
2
Merci

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

CCM 42674 internautes nous ont dit merci ce mois-ci

Messages postés
11066
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
18 octobre 2016
1 776
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,
Messages postés
697
Date d'inscription
dimanche 1 novembre 2009
Statut
Membre
Dernière intervention
31 décembre 2017
143
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.
Messages postés
187
Date d'inscription
lundi 17 avril 2006
Statut
Membre
Dernière intervention
22 janvier 2013
47
Probleme résolu !

Merci :)

Et surtout merci pour les explications ;)
Messages postés
30102
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
17 septembre 2021
7 172
Pas de soucis, à bientôt ;-)