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

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

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

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

13 ответов

Решение

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

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

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

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

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

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

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

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

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

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

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

или же

while (!strcmp(check,input))

или же

while (strcmp(check,input))

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

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

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

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

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

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

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

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

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

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

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

Всякий раз, когда вы пытаетесь сравнить строки, сравните их по отношению к каждому символу. Для этого вы можете использовать встроенную строковую функцию с именем 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");  
} 

Ты можешь:

Использовать от string.h, что является более простой версией

Или, если вы хотите свернуть свой собственный, вы можете использовать что-то вроде этого:

      int strcmp(char *s1, char *s2)
{
    int i;
    while(s1[i] != '\0' && s2[i] != '\0')
    {
        if(s1[i] != s2[i])
        {
            return 1;
        }
        i++;
    }
    return 0;
}

Я бы использовал strcmp() таким образом:

      while(strcmp(check, input))
{
    // code here
}

Вам нужно использовать strcmp() и тебе нужно #include <string.h>

В != а также ==операторы сравнивают только базовые адреса этих строк. Не содержимое строк

      while (strcmp(check, input))

Пример кода:

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

int main()
{
    char input[40];
    char check[40] = "end\n"; //dont forget to check for \n

    while ( strcmp(check, input) ) //strcmp returns 0 if equal
    {
        printf("Please enter a name: \n");
        fgets(input, sizeof(input), stdin);
        printf("My name is: %s\n", input);
    }

    printf("Good bye!");
    return 0;
}

Примечание 1: gets()небезопасно. Используйте вместо

Примечание 2: при использовании fgets() вам нужно проверить '\n' символ новой строки тоже

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

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 недостаточно

В Си строка является стандартной спецификацией библиотеки.

Строка - это непрерывная последовательность символов, оканчивающаяся первым нулевым символом и включающая его.
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() функция

К сожалению, вы не можете использовать 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;
}

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

Мне нравится ответ, выбранный как лучший, за исключением того, что мне не нравится это использование strcmp() вместо этого вы должны 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);
    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;
}

А вот зачем использовать 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;
}

Я только начал программировать и начал смотреть видео cs50 на YouTube. там я столкнулся с проблемой: нельзя сравнивать две строки, используя "==". поэтому я попробовал:

      #include <iostream>

using namespace std;

int main()
{

   string str[] = {"tom", "chris"};

   if (str[0] == "tom")
   {
       return 0;
   }

return 1;
}

Почему-то программа работает и возвращает 0. Видео и посты здесь говорят об обратном.

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

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

Другие вопросы по тегам