Как правильно сравнить строки? - PullRequest
163 голосов
/ 04 ноября 2011

Я пытаюсь получить программу, позволяющую пользователю вводить слово или символ, сохранять его, а затем распечатывать, пока пользователь не введет его снова, выйдя из программы. Мой код выглядит так:

#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;
}

Проблема в том, что я продолжаю получать печать входной строки, даже когда ввод пользователя (проверка) совпадает с оригиналом (ввод). Я неправильно сравниваю их?

Ответы [ 9 ]

245 голосов
/ 04 ноября 2011

Вы не можете (полезно) сравнивать строки, используя != или ==, вам нужно использовать strcmp:

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

Причина этого в том, что != и == будет сравнивать только базовые адреса этих строк.Не содержимое самих строк.

30 голосов
/ 04 ноября 2011

Хорошо, несколько вещей: gets небезопасен и должен быть заменен на fgets(input, sizeof(input), stdin), чтобы избежать переполнения буфера.

Далее, чтобы сравнить строки, вы должны использовать strcmpгде возвращаемое значение 0 указывает, что две строки совпадают.Использование операторов равенства (т. Е. !=) сравнивает адрес двух строк, в отличие от отдельных char s внутри них.

И также обратите внимание, что, хотя в этом примере это не будетвызвать проблему, fgets сохраняет символ новой строки, '\n' также в буферах;gets() нет.Если вы сравните пользовательский ввод из fgets() со строковым литералом, таким как "abc", он никогда не совпадет (если буфер не слишком мал, чтобы '\n' не помещался в нем).

РЕДАКТИРОВАТЬ: и снова побил супер быстрый Мистик.

8 голосов
/ 13 февраля 2016

Использование strcmp.

Это в string.h библиотеке, и она очень популярна. strcmp вернуть 0, если строки равны. См. this для лучшего объяснения того, что strcmp возвращает.

По сути, вы должны сделать:

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

или

while (!strcmp(check,input))

или

while (strcmp(check,input))

Вы можете проверить это , учебник по strcmp.

7 голосов
/ 06 апреля 2015

Вы не можете сравнивать массивы напрямую, как это

array1==array2

Вы должны сравнивать их символ за символом;для этого вы можете использовать функцию и вернуть логическое (True: 1, False: 0) значение.Затем вы можете использовать его в тестовом состоянии цикла while.

Попробуйте:

#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;
}
1 голос
/ 02 февраля 2019

Добро пожаловать в концепцию указателя . Поколения начинающих программистов нашли эту концепцию неуловимой, но если вы хотите стать компетентным программистом, вы должны в конечном итоге освоить эту концепцию & mdash; и более того, вы уже задаете правильный вопрос. Это хорошо.

Вам понятно, что это за адрес? Смотрите эту диаграмму:

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

На диаграмме целое число 1 хранится в памяти по адресу адрес 0x4000. Почему по адресу? Поскольку память велика и может хранить много целых чисел, так же, как город большой и может вместить много семей. Каждое целое число хранится в ячейке памяти, так как каждая семья проживает в доме. Каждая ячейка памяти идентифицируется адресом , а каждый дом идентифицируется по адресу.

Два поля на диаграмме представляют две различные области памяти. Вы можете думать о них, как будто они были домами. Целое число 1 находится в ячейке памяти по адресу 0x4000 (например, «4000 Elm St.»). Целое число 7 находится в ячейке памяти по адресу 0x4004 (например, «4004 Elm St.»).

Вы думали, что ваша программа сравнивает 1 с 7, но это не так. Он сравнивал 0x4000 с 0x4004. Так что же происходит, когда у вас такая ситуация?

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

Два целых числа одинаковы, но адреса различаются. Ваша программа сравнивает адреса.

1 голос
/ 03 марта 2016

Всякий раз, когда вы пытаетесь сравнить строки, сравнивайте их по отношению к каждому символу.Для этого вы можете использовать встроенную строковую функцию с именем strcmp (input1, input2);и вы должны использовать заголовочный файл с именем #include<string.h>

Попробуйте этот код:

#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");  
} 
0 голосов
/ 10 января 2019

Как правильно сравнивать строки?

char input[40];
char check[40];
strcpy(input, "Hello"); // input assigned somehow
strcpy(check, "Hello"); // check assigned somehow

// insufficient
while (check != input)

// good
while (strcmp(check, input) != 0)
// or 
while (strcmp(check, input))

Давайте копать глубже, чтобы увидеть почему check != input недостаточно .

В C строка - это стандартная спецификация библиотеки.

A строка - это непрерывная последовательность символов, оканчивающаяся на первый нулевой символ включительно
C11 §7.1.1 1

input выше не является строкой .input - это массив 40 символов .

Содержимое input может стать строкой .

В большинстве случаев, когдаВ выражении используется массив, он преобразуется в адрес своего 1-го элемента.

Ниже приведено преобразование check и input в их соответствующие адреса первого элемента, затем эти адреса сравниваются.

check != input   // Compare addresses, not the contents of what addresses reference

Для сравнения строки ,нам нужно использовать эти адреса, а затем посмотреть на данные, на которые они указывают.
strcmp() выполняет работу .§7.23.4.2

int strcmp(const char *s1, const char *s2);

Функция strcmp сравнивает строку, на которую указывает s1, со строкой, на которую указывает s2.

Функция strcmp возвращает целое число больше, равно или меньше нуля, соответственно, поскольку строка, на которую указывает s1, больше, равна или меньше, чем строка, на которую указывает s2.

Не только код может найти, если строки имеют одинаковые данные, но и то, какая из них больше / меньше, если они различаются.

Приведенные ниже значения верны, когда строки различаются.

strcmp(check, input) != 0

Для получения подробной информации см. Создание моей собственной strcmp() функции

0 голосов
/ 23 марта 2018
    #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;
    }

Это очень простое решение, в котором вы получите желаемый результат.

0 голосов
/ 28 августа 2015

К сожалению, вы не можете использовать strcmp из <cstring>, потому что это заголовок C ++, и вы специально сказали, что это для приложения C. У меня была такая же проблема, поэтому мне пришлось написать свою собственную функцию, которая реализует 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;
}

Надеюсь, это хорошо вам послужит.

...