Я пытаюсь получить программу, позволяющую пользователю вводить слово или символ, сохранять его, а затем распечатывать, пока пользователь не введет его снова, выйдя из программы. Мой код выглядит так:
#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;
}
Проблема в том, что я продолжаю получать печать входной строки, даже когда ввод пользователя (чек) совпадает с оригиналом (ввод). Я сравниваю два неправильно?
gets( )
был удален из стандарта. Используйтеfgets( )
вместо этого.strcmp()
возвращает ноль, когда его входные значения равны», объясняет, как сравнивать строки на равенство, неравенство, меньше, больше, меньше или равно и больше или равно. Не все сравнения строк для равенства. Чувствительные к регистру сравнения снова отличаются; другие специальные сравнения (например, порядок словаря) требуют более специализированных компараторов, и для еще более сложных сравнений существуют регулярные выражения.gets()
стоит. Он также был удален из стандарта с C11 -> Пожалуйста, прочтите Почему функция gets настолько опасна, что ее не следует использовать?Ответы:
Вы не можете (полезно) сравнивать строки, используя
!=
или==
, вам нужно использоватьstrcmp
:Причина этого в том , что
!=
и==
будет сравнивать только базовые адреса этих строк. Не содержимое самих строк.источник
while (strcmp(check, input))
достаточно и считается хорошей практикой.Хорошо, несколько вещей:
gets
небезопасно и должно быть заменено,fgets(input, sizeof(input), stdin)
чтобы избежать переполнения буфера.Затем, чтобы сравнить строки, вы должны использовать
strcmp
, где возвращаемое значение 0 указывает, что две строки совпадают. Использование операторов равенства (т.!=
Е.) Сравнивает адрес двух строк, в отличие от отдельныхchar
s внутри них.Также обратите внимание, что, хотя в этом примере это не вызовет проблемы,
fgets
символ новой строки также сохраняется'\n'
в буферах;gets()
не. Если вы сравните пользовательский ввод сfgets()
строковым литералом,"abc"
который никогда не будет совпадать (если только буфер не слишком мал, чтобы'\n'
он не помещался в нем).источник
fgets()
, то строка может быть"abc\n"
потому, чтоfgets()
сохраняет новую строку . Если вы сравните это с"abc"
, вы получите «не равный» из-за разницы между нулевым завершающим байтом"abc"
и новой строкой в прочитанных данных. Итак, вы должны убить новую строку. Надежный однострочный способ сделать это - это то,buffer[strcspn(buffer, "\n")] = '\0';
что имеет смысл работать правильно независимо от того, есть ли какие-либо данные в буфере, или эти данные заканчиваются символом новой строки или нет. Другие способы запуска новой строки легко терпят крах.использование
strcmp
.Это в
string.h
библиотеке и очень популярно.strcmp
вернуть 0, если строки равны. Смотрите это для лучшего объяснения того, чтоstrcmp
возвращается.По сути, вы должны сделать:
или
или
Вы можете проверить это , учебник по
strcmp
.источник
Вы не можете сравнивать массивы напрямую, как это
Вы должны сравнить их за символом; для этого вы можете использовать функцию и возвращать логическое (True: 1, False: 0) значение. Затем вы можете использовать его в тестовом состоянии цикла while.
Попробуй это:
источник
checker
находит'\0'
в одной из строк, он не проверяет другую строку для'\0'
. Функция возвращает1
(«равно»), даже если одна строка является только префиксом другой (например,"foo"
и"foobar"
).||
вместо&&
.Добро пожаловать в концепцию указателя.Поколения начинающих программистов нашли эту концепцию неуловимой, но если вы хотите стать компетентным программистом, вы должны в конечном итоге овладеть этой концепцией - и, более того, вы уже задаете правильный вопрос. Это хорошо.
Вам понятно, что это за адрес? Смотрите эту диаграмму:
На диаграмме целое число 1 хранится в памяти по адресу 0x4000. Почему по адресу? Поскольку память велика и может хранить много целых чисел, так же, как город большой и может вместить много семей. Каждое целое число хранится в ячейке памяти, так как каждая семья проживает в доме. Каждая ячейка памяти идентифицируется по адресу , а каждый дом - по адресу.
Два поля на диаграмме представляют две различные области памяти. Вы можете думать о них, как будто они были домами. Целое число 1 находится в ячейке памяти по адресу 0x4000 (например, «4000 Elm St.»). Целое число 7 находится в ячейке памяти по адресу 0x4004 (например, «4004 Elm St.»).
Вы думали, что ваша программа сравнивает 1 с 7, но это не так. Он сравнивал 0x4000 с 0x4004. Так что же происходит, когда у вас такая ситуация?
Два целых числа одинаковы, но адреса различаются. Ваша программа сравнивает адреса.
источник
Всякий раз, когда вы пытаетесь сравнить строки, сравнивайте их по отношению к каждому символу. Для этого вы можете использовать встроенную строковую функцию strcmp (input1, input2); и вы должны использовать заголовочный файл с именем
#include<string.h>
Попробуйте этот код:
источник
Давайте копать глубже, чтобы понять, почему
check != input
этого недостаточно .В Си строка является стандартной спецификацией библиотеки.
input
выше не строка .input
это массив 40 из полукокса .Содержимое
input
может стать строкой .В большинстве случаев, когда массив используется в выражении, он преобразуется в адрес своего 1-го элемента.
Ниже преобразуются
check
иinput
в соответствующие им адреса первого элемента, затем эти адреса сравниваются.Сравнивать строки , нам нужно использовать эти адреса, а затем посмотреть на данные, на которые они указывают.
strcmp()
делает работу . §7.23.4.2Код не только может найти, если строки имеют одинаковые данные, но какая из них больше / меньше, если они различаются.
Ниже верно, когда строка отличается.
Для понимания см. Создание моей собственной
strcmp()
функцииисточник
Это очень простое решение, в котором вы получите свой результат, как вы хотите.
источник
gets();
не является частью стандарта C, так как C11.strcmp(s1,s2)
UB, так какs2
содержимое не указано сначала.