Problème de comparaison de chaine de caractères
CrazyGeekMan
Messages postés
971
Statut
Membre
-
[Dal] Messages postés 6122 Date d'inscription Statut Contributeur Dernière intervention -
[Dal] Messages postés 6122 Date d'inscription Statut Contributeur Dernière intervention -
Bonjour,
Voici mon tout petit code :
J'ai lu quelques topics et j'ai cru comprendre qu'il faudrait mettre plutôt
Mais même voir ce changement le Bonjour ne s'affiche pas.
Que faire s'il vous plaît?
Merci :)
Voici mon tout petit code :
#include <stdio.h>
void main()
{
char mot[3]="non";
if (mot=="non")
printf("Bonjour");
}
J'ai lu quelques topics et j'ai cru comprendre qu'il faudrait mettre plutôt
mot[4]="non\0"pour montrer la fin de la suite de caractères.
Mais même voir ce changement le Bonjour ne s'affiche pas.
Que faire s'il vous plaît?
Merci :)
2 réponses
-
google, "c comparaison chaine", premier lien :
https://fr.wikibooks.org/wiki/Programmation_C/Cha%C3%AEnes_de_caract%C3%A8resint strcmp(const char * chaine1, const char * chaine2);
Compare les chaînes chaine1 et chaine2 et renvoie un entier :
négatif, si chaine1 est inférieure à chaine2 (avant dans l'ordre alphabétique) ;
nul, si chaine1 est égale à chaine2 (.i.e. chaine1 et chaine2 sont identiques) ;
positif, si chaine1 est supérieur à chaine2 (après dans l'ordre alphabétique) .-
-
En C le "non" est considéré par le compilateur comme une chaîne littérale, le compilateur allouant un espace mémoire pour cette chaîne, qui est donc désigné par un pointeur.
Par conséquent, cela ne pose strictement aucun problème d'écrire, en C :#include <stdio.h> #include <string.h> int main(void) { char mot[] = "non"; if (strcmp(mot, "non") == 0) { printf("c'est non\n"); } return 0; }
note la déclaration de mot, qui ne nécessite pas que tu mentionnes la taille, le compilateur calculant cela tout seul (de plus, tonchar mot[3]="non";
était erroné, car il manquait un byte. Pour une chaîne de 3 lettres on a besoin d'au moins 4 char, le 4ème étant pour le '\0' terminant la chaîne.
https://www.commentcamarche.net/contents/118-langage-c-les-chaines-de-caracteres- Merci pour cette réponse complète et claire !
C'est rigolo de voir que le compilateur alloue de la mémoire pour le "non" alors qu'on en l'a pas déclaré avec le char.
Oui j'ai conscience du fait que l'on peut ne pas spécifier la taille de la chaîne sauf que si on veut demander la taille de la chaîne à l'utilisateur je vais donc le programmer avec char mot[n+1]="..." où n sera demandé grâce à un scanf.
Je pense que ce n'est pas du tout utilisé par les programmeurs mais je suis débutant O:)
-
Effectivement, il est rare que l'on demande à l'utilisateur d'indiquer quelle est la taille de la chaîne (qu'on va lui demander de saisir) : en général, le programme fixe cette limite, et devrait en informer l'utilisateur d'une façon ou d'une autre (sur l'interface utilisateur, dans la documentation, etc.)... cela dit, pourquoi pas :-)
Par contre, le programme ne devrait pas faire confiance à l'utilisateur et vérifier, en tout état de cause (que la limite soit fixée d'avance ou non), que la chaîne saisie grâce à un scanf ou un fgets, ne dépasse pas l'espace mémoire alloué.
Pour allouer l'espace, tu devrais utiliser unmalloc()
(et unfree()
quand tu n'en as plus besoin), plutôt qu'unchar mot[n+1];
, si tu veux que ton code reste compatible avec le C89.
quant àchar mot[n+1]="..."
, je ne sais pas trop ce que tu voudrais faire. Ce n'est pas très cohérent de mettre un littéral à droite (qui a donc une taille fixe), alors qu'à gauche tu aurais une déclaration avec un espace mémoire dépendant de "n", qui, si j'ai bien compris serait déterminé par l'utilisateur... il y a un petit problème là. Je ne crois pas que cela donne rien de bon en C.
Dal- Oui je sais très bien que ce code et TRES limité car cela oblige par exemple l'utilisateur à compter le nombre de caractères dans son pseudo (peu pertinent). Je n'ai pas pensé à rajouter une limite car j'avais pensé à l'optimisation de la mémoire vive ^^ Imaginons que l'on mette 20 caractères au plus alors que l'utilisateur en rentre que 2 ^^
Mais bon à mon niveau je ne devrait pas encore parler d'optimisation, j'en suis assez loin ^^
Vous parlez de norme 89 mais avez vous une page décrivant chaque norme s'il vous plait? Pour une petite comparaison O:)
-
-
Utilise fgets et strncmp
#include <stdlib.h> #include <stdio.h> #include <string.h> const int SIZE = 10; int main(void) { char mot[] = "non"; char buffer[SIZE]; printf("%s", "buffer ? "); fgets(buffer, SIZE, stdin); puts(buffer); if (strncmp(mot, buffer, strlen(mot)) == 0) { printf("c'est non\n"); } return 0; }
Compilation et exécution:johand@bata:~/src/CCM/C$ gcc -o test_strcmp test_strcmp.c
johand@bata:~/src/CCM/C$ ./test_strcmp
buffer ? 0123456789012345
012345678
johand@bata:~/src/CCM/C$ ./test_strcmp
buffer ? non
non
c'est non
https://linux.die.net/man/3/strcmp
https://linux.die.net/man/3/fgets-
-
je ne suis pas sûr que cela soit ce que tu veuilles faire
en utilisantstrncmp()
, jisisv limite la comparaison à 3 caractères saisis, alors qu'il en stocke jusqu'à 9 en raison de la taille du buffer.
ainsi, si tu saisis "nonne", le test passera quand même (essaye)
il faudrait utiliserstrcmp()
, pour vraiment tester ce qui a été saisi. Mais comme fgets inclue le '\n'
tapé (le retour à la ligne est inclus avant le'\0'
à moins que tu aies tapé exactement le nombre de caractères tenant dans le buffer), tu verras que pour que la comparaison fonctionne, il faut que tu le supprimes.
pour t'en convaincre, change la ligne 11 avec le puts et au lieu de cela metsprintf("vous avez tapé : >%s<\n", buffer);et répond "non" à la question, tu verras que ce qui a été stocké dans buffer contient le retour à la ligne, cela affiche :$ ./a.out buffer ? non vous avez tapé : >non <
et la comparaison échoue aussi.
donc, pour n'avoir que ce que l'on veut, avec fgets, il faut supprimer le retour à la ligne s'il existe, et cela se fait comme cela :char * p; if ((p = strchr(buffer, '\n')) != NULL) *p = '\0';
insére cela avant le printf, et désormais, tu auras :$ ./a.out buffer ? non vous avez tapé : >non< c'est non
au final, cela donne :#include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { const int SIZE = 10; char mot[] = "non"; char buffer[SIZE]; printf("%s", "buffer ? "); fgets(buffer, SIZE, stdin); char * p; if ((p = strchr(buffer, '\n')) != NULL) *p = '\0'; printf("vous avez tapé : >%s<\n", buffer); if (strcmp(mot, buffer) == 0) { printf("c'est non\n"); } return 0; }
avec scanf on a d'autres types de problèmes :-) mais, cela suffit pour ce soir.
Dal -
-