249 votes

Comment comparer correctement les cordes en C ?

J'essaie de faire en sorte qu'un programme permette à un utilisateur de saisir un mot ou un caractère, de le mémoriser, puis de l'imprimer jusqu'à ce que l'utilisateur le saisisse à nouveau, en quittant le programme. Mon code ressemble à ceci :

#include <stdio.h>

int main()
{
    char input[40];
    char check[40];
    int i=0;
    printf("Hello!\nPlease enter a word or character:\n");
    gets(input);   /* obsolete function: do not use!! */
    printf("I will now repeat this until you type it back to me.\n");

    while (check != input)
    {
        printf("%s\n", input);
        gets(check);   /* obsolete function: do not use!! */
    }

    printf("Good bye!");

    return 0;
}

Le problème est que je continue à obtenir l'impression de la chaîne d'entrée, même lorsque l'entrée de l'utilisateur (check) correspond à l'original (input). Est-ce que je compare les deux de manière incorrecte ?

17 votes

gets( ) a été supprimé de la norme. Utilisez fgets( ) à la place.

1 votes

Notez que cette respuesta à Pourquoi est-ce que strcmp() retourne zéro lorsque ses entrées sont égales explique comment comparer des chaînes de caractères pour l'égalité, l'inégalité, moins que, plus que, moins que ou égal, et plus que ou égal. Les comparaisons de chaînes de caractères ne sont pas toutes des comparaisons d'égalité. Les comparaisons sensibles à la casse sont encore différentes ; d'autres comparaisons spéciales (ordre du dictionnaire, par exemple) nécessitent des comparateurs plus spécialisés, et il existe des regex pour des comparaisons encore plus complexes.

0 votes

Notez également qu'il y a une question essentiellement dupliquée Comment vérifier si une valeur correspond à une chaîne de caractères ? qui a été posée des années auparavant.

364voto

Mysticial Points 180300

Vous ne pouvez pas (utilement) comparer des chaînes de caractères en utilisant != o == vous devez utiliser strcmp :

while (strcmp(check,input) != 0)

La raison en est que != y == ne comparera que les adresses de base de ces chaînes. Pas le contenu des chaînes elles-mêmes.

12 votes

La même chose en Java, qui peut juste comparer avec l'adresse.

42 votes

Rédaction while (strcmp(check, input)) est suffisante et est considérée comme une bonne pratique.

0 votes

En savoir plus... codificare.in/codes/c/

44voto

AusCBloke Points 10179

Ok, quelques trucs : gets n'est pas sûr et devrait être remplacé par fgets(input, sizeof(input), stdin) afin d'éviter un débordement de tampon.

Ensuite, pour comparer des chaînes de caractères, vous devez utiliser strcmp où une valeur de retour de 0 indique que les deux chaînes de caractères correspondent. En utilisant les opérateurs d'égalité (c'est-à-dire != ) compare l'adresse des deux chaînes de caractères, par opposition à l'adresse individuelle de chaque chaîne. char à l'intérieur.

Et notez également que, bien que dans cet exemple, cela ne posera pas de problème, fgets enregistre le caractère de nouvelle ligne, '\n' dans les tampons également ; gets() ne le fait pas. Si vous comparez l'entrée utilisateur de fgets() à une chaîne littérale telle que "abc" il ne correspondrait jamais (à moins que le tampon ne soit trop petit pour que le '\n' ne rentrerait pas dedans).

0 votes

Pouvez-vous s'il vous plaît clarifier la relation/problème de " \n " et chaîne littérale ? J'obtiens un résultat différent en comparant les chaînes de caractères (ligne) d'un fichier avec un autre fichier entier.

1 votes

@incompetent - si vous lisez une ligne d'un fichier avec fgets() alors la chaîne pourrait être "abc\n" parce que fgets() conserve la nouvelle ligne. Si vous comparez cela avec "abc" vous obtiendrez un résultat "non égal" en raison de la différence entre un octet nul et une terminaison d'octet. "abc" et le saut de ligne dans les données lues. Il faut donc supprimer le saut de ligne. La façon fiable de le faire en une ligne est buffer[strcspn(buffer, "\n")] = '\0'; qui a le mérite de fonctionner correctement, qu'il y ait ou non des données dans le tampon, ou que ces données se terminent par une nouvelle ligne ou non. Les autres méthodes de suppression de la nouvelle ligne se plantent facilement.

0 votes

Cette réponse aborde les questions du code de manière précise, tandis que la réponse la plus votée et acceptée ne couvre que le titre de la question. Surtout pour mentionner le dernier paragraphe est super. +1

17voto

fortunate_man Points 3713

Utilice strcmp .

Ceci est en string.h bibliothèque, et est très populaire. strcmp retourne 0 si les chaînes sont égales. Voir ce pour une meilleure explication de ce que strcmp retours.

En gros, vous devez faire :

while (strcmp(check,input) != 0)

o

while (!strcmp(check,input))

o

while (strcmp(check,input))

Vous pouvez vérifier ce un tutoriel sur strcmp .

11voto

mugetsu Points 138

Vous ne pouvez pas comparer directement des tableaux comme ceci

array1==array2

Vous devez les comparer char par char ; pour cela, vous pouvez utiliser une fonction et renvoyer une valeur booléenne (Vrai:1, Faux:0). Vous pouvez ensuite l'utiliser dans la condition de test de la boucle while.

Essayez ça :

#include <stdio.h>
int checker(char input[],char check[]);
int main()
{
    char input[40];
    char check[40];
    int i=0;
    printf("Hello!\nPlease enter a word or character:\n");
    scanf("%s",input);
    printf("I will now repeat this until you type it back to me.\n");
    scanf("%s",check);

    while (!checker(input,check))
    {
        printf("%s\n", input);
        scanf("%s",check);
    }

    printf("Good bye!");

    return 0;
}

int checker(char input[],char check[])
{
    int i,result=1;
    for(i=0; input[i]!='\0' || check[i]!='\0'; i++) {
        if(input[i] != check[i]) {
            result=0;
            break;
        }
    }
    return result;
}

9voto

thb Points 4370

Bienvenue dans le concept de la pointeur. Des générations de programmeurs débutants ont trouvé ce concept insaisissable, mais si vous souhaitez devenir un programmeur compétent, vous devez finir par maîtriser ce concept - et d'ailleurs, vous vous posez déjà la bonne question. C'est une bonne chose.

Vous savez ce qu'est une adresse ? Regardez ce diagramme :

----------     ----------
| 0x4000 |     | 0x4004 |
|    1   |     |    7   |
----------     ----------

Dans le schéma, le nombre entier 1 est stocké en mémoire à l'emplacement adresse 0x4000. Pourquoi à une adresse ? Parce que la mémoire est grande et peut stocker de nombreux entiers, tout comme une ville est grande et peut abriter de nombreuses familles. Chaque nombre entier est stocké à un emplacement mémoire, comme chaque famille réside dans une maison. Chaque emplacement mémoire est identifié par un adresse car chaque maison est identifiée par une adresse.

Les deux cases du diagramme représentent deux emplacements mémoire distincts. Vous pouvez les imaginer comme s'il s'agissait de maisons. Le nombre entier 1 réside dans l'emplacement mémoire à l'adresse 0x4000 (pensez à "4000 Elm St."). Le nombre entier 7 se trouve dans l'emplacement mémoire à l'adresse 0x4004 (pensez à "4004 Elm St.").

Vous pensiez que votre programme comparait le 1 au 7, mais ce n'était pas le cas. Il comparait le 0x4000 au 0x4004. Alors que se passe-t-il dans cette situation ?

----------     ----------
| 0x4000 |     | 0x4004 |
|    1   |     |    1   |
----------     ----------

Les deux entiers sont les mêmes mais les adresses diffèrent. Votre programme compare les adresses.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X