Problème de comparaison de chaine de caractères
Fermé
CrazyGeekMan
Messages postés
872
Date d'inscription
dimanche 1 novembre 2015
Statut
Membre
Dernière intervention
21 novembre 2024
-
24 nov. 2016 à 16:40
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 - 28 nov. 2016 à 00:08
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 - 28 nov. 2016 à 00:08
A voir également:
- Problème de comparaison de chaine de caractères
- Caractères ascii - Guide
- Plus de chaine tv - Guide
- Exemple de mot de passe à 8 caractères - Guide
- Chaine tnt gratuite sur mobile - Guide
- Caractères spéciaux clavier azerty - Guide
2 réponses
Utilisateur anonyme
24 nov. 2016 à 17:22
24 nov. 2016 à 17:22
google, "c comparaison chaine", premier lien :
https://fr.wikibooks.org/wiki/Programmation_C/Cha%C3%AEnes_de_caract%C3%A8res
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) .
https://fr.wikibooks.org/wiki/Programmation_C/Cha%C3%AEnes_de_caract%C3%A8res
int 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) .
jisisv
Messages postés
3645
Date d'inscription
dimanche 18 mars 2001
Statut
Modérateur
Dernière intervention
15 janvier 2017
934
26 nov. 2016 à 11:31
26 nov. 2016 à 11:31
Utilise fgets et strncmp
Compilation et exécution:
https://linux.die.net/man/3/strcmp
https://linux.die.net/man/3/fgets
#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
CrazyGeekMan
Messages postés
872
Date d'inscription
dimanche 1 novembre 2015
Statut
Membre
Dernière intervention
21 novembre 2024
136
26 nov. 2016 à 19:15
26 nov. 2016 à 19:15
Merci je vais étudier ce code, en particulier les nouvelles commandes ^^
[Dal]
Messages postés
6194
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
11 octobre 2024
1 092
Modifié par [Dal] le 26/11/2016 à 20:33
Modifié par [Dal] le 26/11/2016 à 20:33
je ne suis pas sûr que cela soit ce que tu veuilles faire
en utilisant
ainsi, si tu saisis "nonne", le test passera quand même (essaye)
il faudrait utiliser
pour t'en convaincre, change la ligne 11 avec le puts et au lieu de cela mets
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 :
insére cela avant le printf, et désormais, tu auras :
au final, cela donne :
avec scanf on a d'autres types de problèmes :-) mais, cela suffit pour ce soir.
Dal
en utilisant
strncmp(), 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 utiliser
strcmp(), 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 mets
printf("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
CrazyGeekMan
Messages postés
872
Date d'inscription
dimanche 1 novembre 2015
Statut
Membre
Dernière intervention
21 novembre 2024
136
>
[Dal]
Messages postés
6194
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
11 octobre 2024
27 nov. 2016 à 17:51
27 nov. 2016 à 17:51
J'ai toujours droit à des explications bien détaillés, sympa ;)
Mais je vais rester sur la première proposition , elle semble plus légère ^^
Mais je vais rester sur la première proposition , elle semble plus légère ^^
[Dal]
Messages postés
6194
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
11 octobre 2024
1 092
28 nov. 2016 à 00:08
28 nov. 2016 à 00:08
quelle première explication ?
24 nov. 2016 à 17:44
Je ne suis pas en train de comparer deux chaines de caractères déclarées, seulement la première l'est.
Modifié par [Dal] le 24/11/2016 à 19:32
Par conséquent, cela ne pose strictement aucun problème d'écrire, en C :
note la déclaration de mot, qui ne nécessite pas que tu mentionnes la taille, le compilateur calculant cela tout seul (de plus, ton é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
25 nov. 2016 à 16:00
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:)
Modifié par [Dal] le 25/11/2016 à 19:51
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 un (et un quand tu n'en as plus besoin), plutôt qu'un , si tu veux que ton code reste compatible avec le C89.
quant à , 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
26 nov. 2016 à 19:14
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:)