Как правильно сравнить строки?
Я пытаюсь получить программу, позволяющую пользователю вводить слово или символ, сохранять его, а затем распечатывать, пока пользователь не наберет его снова, выйдя из программы. Мой код выглядит так:
#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;
}
Это очень простое решение, в котором вы получите свой результат, как вы хотите.