web-dev-qa-db-fra.com

Comment comparer correctement les chaînes?

J'essaie d'obtenir un programme permettant à un utilisateur de saisir un mot ou un caractère, de le stocker, puis de l'imprimer jusqu'à ce que l'utilisateur le ressaisisse, 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);
    printf("I will now repeat this until you type it back to me.\n");

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

    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 (vérification) correspond à l'original (entrée). Est-ce que je compare les deux de manière incorrecte?

152
nmagerko

Vous ne pouvez pas (utilement) comparer des chaînes avec != ou ==, vous devez utiliser strcmp:

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

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

234
Mysticial

Ok, quelques petites choses: gets est dangereux et doit être remplacé par fgets(input, sizeof(input), stdin) afin d'éviter tout débordement de mémoire tampon.

Ensuite, pour comparer des chaînes, vous devez utiliser strcmp, où une valeur de retour de 0 indique que les deux chaînes correspondent. L’utilisation des opérateurs d’égalité (c.-à-d. !=) compare l’adresse des deux chaînes, par opposition à la chars individuelle qu’elles contiennent.

Notez également que, même si, dans cet exemple, cela ne posera pas de problème, fgets enregistre également le caractère de nouvelle ligne, '\n', dans les tampons; gets() ne le fait pas. Si vous compariez l'entrée utilisateur de fgets() à un littéral de chaîne tel que "abc", il ne correspondrait jamais (à moins que le tampon soit trop petit pour que le '\n' ne puisse pas s'y glisser).

EDIT: et encore une fois battu par le super rapide Mysticial.

30
AusCBloke

Vous ne pouvez pas comparer les tableaux directement comme ceci

array1==array2

Vous devriez les comparer caractère par caractère; Pour cela, vous pouvez utiliser une fonction et renvoyer une valeur booléenne (Vrai: 1, Faux: 0). Ensuite, vous pouvez l'utiliser dans la condition de test de la boucle while.

Essaye ç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;
}
7
mugetsu

Utilisez strcmp .

Ceci est dans la bibliothèque string.h et est très populaire. strcmp renvoie 0 si les chaînes sont égales. Voir this pour une meilleure explication de ce que strcmp renvoie.

Fondamentalement, vous devez faire:

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

ou

while (!strcmp(check,input))

ou 

while (strcmp(check,input))

Vous pouvez vérifier this , un tutoriel sur strcmp.

6
Ashish Ahuja

Lorsque vous essayez de comparer les chaînes, comparez-les en fonction de chaque caractère. Pour cela, vous pouvez utiliser la fonction de chaîne intégrée appelée strcmp (entrée1, entrée2); et vous devriez utiliser le fichier d'en-tête appelé #include<string.h> 

Essayez ce code:

#include<stdio.h> 
#include<stdlib.h> 
#include<string.h>  

int main() 
{ 
    char s[]="STACKOVERFLOW";
    char s1[200];
    printf("Enter the string to be checked\n");//enter the input string
    scanf("%s",s1);
    if(strcmp(s,s1)==0)//compare both the strings  
    {
        printf("Both the Strings match\n"); 
    } 
    else
    {
        printf("Entered String does not match\n");  
    } 
    system("pause");  
} 
1

Malheureusement, vous ne pouvez pas utiliser strcmp à partir de <cstring> car il s'agit d'un en-tête C++ et vous avez spécifiquement indiqué qu'il s'agissait d'une application C. J'ai eu le même problème, donc j'ai dû écrire ma propre fonction qui implémente strcmp:

int strcmp(char input[], char check[])
{
    for (int i = 0;; i++)
    {
        if (input[i] == '\0' && check[i] == '\0')
        {
            break;
        }
        else if (input[i] == '\0' && check[i] != '\0')
        {
            return 1;
        }
        else if (input[i] != '\0' && check[i] == '\0')
        {
            return -1;
        }
        else if (input[i] > check[i])
        {
            return 1;
        }
        else if (input[i] < check[i])
        {
            return -1;
        }
        else
        {
            // characters are the same - continue and check next
        }
    }
    return 0;
}

J'espère que cela vous sert bien.

0
Steztric
    #include<stdio.h>
    #include<string.h>
    int main()
    {
        char s1[50],s2[50];
        printf("Enter the character of strings: ");
        gets(s1);
        printf("\nEnter different character of string to repeat: \n");
        while(strcmp(s1,s2))
        {
            printf("%s\n",s1);
            gets(s2);
        }
        return 0;
    }

C'est une solution très simple dans laquelle vous obtiendrez votre sortie comme vous le souhaitez.

0
Rupani T D

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

Est-ce clair pour vous ce qu'est une adresse? Voir ce diagramme:

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

Dans le diagramme, l'entier 1 est stocké en mémoire à l'adresse adresse 0x4000. Pourquoi à une adresse? Parce que la mémoire est grande et peut stocker de nombreux entiers, une ville est grande et peut accueillir de nombreuses familles. Chaque entier est stocké dans un emplacement de mémoire, chaque famille résidant dans une maison. Chaque emplacement de mémoire est identifié par une adresse ,, chaque maison étant identifiée par une adresse.

Les deux zones du diagramme représentent deux emplacements de mémoire distincts. Vous pouvez penser à eux comme à des maisons. Le nombre entier 1 réside dans l'emplacement de la mémoire à l'adresse 0x4000 (pensez, "4000 Elm St."). Le nombre entier 7 réside dans l'emplacement de la 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 qu'est-ce qui se passe quand vous avez cette situation?

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

Les deux entiers sont identiques mais les adresses diffèrent. Votre programme compare les adresses.

0
thb

J'aime la réponse choisie comme meilleure, sauf que je n'aime pas l'utilisation de strcmp() à la place. strncmp(), associé aux macros Alors, voici votre code avec de petites améliorations.

#include <stdio.h>

#define MAXLEN 40
int main()
{
    char input[MAXLEN];
    char check[MAXLEN];
    int i=0;
    printf("Hello!\nPlease enter a Word or character:\n");
    gets(input);
    printf("I will now repeat this until you type it back to me.\n");

    while (strcmp(check, input))
    {
        printf("%s\n", input);
        gets(check); 
    }

    printf("Good bye!");


    return 0;
}

Et voici pourquoi utiliser strncmp():

#include <stdio.h>

#define MAXLEN 40
int main()
{
    char input[MAXLEN];
    char check[MAXLEN];
    int i=0;
    printf("Hello!\nPlease enter a Word or character:\n");
    gets(input);
    int len = strlen(input);
    for (; i < 10000; ++i)
        input [len - 2 + i] = 'A';

    printf("I will now repeat this until you type it back to me.\n");

    while (strncmp(check, input, MAXLEN))
    {
        printf("%s\n", input);
        gets(check); 
    }

    printf("Good bye!");


    return 0;
}
0
Gox