Problème de comparaison de chaine de caractères

Fermé
CrazyGeekMan Messages postés 871 Date d'inscription dimanche 1 novembre 2015 Statut Membre Dernière intervention 29 octobre 2022 - 24 nov. 2016 à 16:40
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 - 28 nov. 2016 à 00:08
Bonjour,

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 :)
A voir également:

2 réponses

Utilisateur anonyme
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

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) .
0
CrazyGeekMan Messages postés 871 Date d'inscription dimanche 1 novembre 2015 Statut Membre Dernière intervention 29 octobre 2022 131
24 nov. 2016 à 17:44
Mais ici je ne peux pas utiliser cette fonction puisque "non" écrit à la main ne peux être pointé à l'aide d'une pointeur.
Je ne suis pas en train de comparer deux chaines de caractères déclarées, seulement la première l'est.
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié par [Dal] le 24/11/2016 à 19:32
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, ton
char 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
0
CrazyGeekMan Messages postés 871 Date d'inscription dimanche 1 novembre 2015 Statut Membre Dernière intervention 29 octobre 2022 131 > [Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024
25 nov. 2016 à 16:00
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:)
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié par [Dal] le 25/11/2016 à 19:51
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 un
malloc()
(et un
free()
quand tu n'en as plus besoin), plutôt qu'un
char 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
0
CrazyGeekMan Messages postés 871 Date d'inscription dimanche 1 novembre 2015 Statut Membre Dernière intervention 29 octobre 2022 131 > [Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024
26 nov. 2016 à 19:14
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:)
0
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
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
0
CrazyGeekMan Messages postés 871 Date d'inscription dimanche 1 novembre 2015 Statut Membre Dernière intervention 29 octobre 2022 131
26 nov. 2016 à 19:15
Merci je vais étudier ce code, en particulier les nouvelles commandes ^^
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
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
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
0
CrazyGeekMan Messages postés 871 Date d'inscription dimanche 1 novembre 2015 Statut Membre Dernière intervention 29 octobre 2022 131 > [Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024
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 ^^
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
28 nov. 2016 à 00:08
quelle première explication ?
0