Как сравнить строки: strcmp, а не ==
Строки сравнивает функция strcmp из string.h. Она возвращает 0, если строки одинаковые:
#include <stdio.h>
#include <string.h>
int main(void) {
char answer[50];
scanf("%49s", answer);
if (strcmp(answer, "yes") == 0) {
printf("Согласие получено\n");
} else {
printf("Ответ: %s\n", answer);
}
return 0;
}yesСогласие полученоПочему == не работает
Имя массива — это адрес его первого символа, строка в кавычках — тоже адрес. answer == "yes" сравнивает два адреса, а не буквы. Массив answer и строка "yes" лежат в разных местах памяти, поэтому сравнение ложно, даже если введено ровно yes. gcc предупреждает:
warning: comparison with string literal results in unspecified behavior [-Waddress]Так же нельзя скопировать строку через =: для этого есть strcpy.
Что возвращает strcmp
- 0 — строки равны;
- меньше нуля — первая строка идёт раньше по алфавиту;
- больше нуля — первая строка идёт позже.
Сравнение идёт по кодам символов слева направо, до первого различия. Сами числа, кроме нуля, не определены стандартом — это может быть −1 и 1, а может разница кодов. Поэтому проверяют знак: < 0, > 0, == 0, но не == 1 или == -1.
#include <stdio.h>
#include <string.h>
int main(void) {
printf("%d\n", strcmp("apple", "banana") < 0);
printf("%d\n", strcmp("apple", "app") > 0);
printf("%d\n", strcmp("Zoo", "apple") < 0);
return 0;
}1
1
1appleраньшеbanana: первая же букваaменьшеb.appleпозжеapp: начало совпало, а более короткая строка идёт раньше.Zooраньшеapple: у больших латинских букв коды меньше, чем у маленьких (Z— 90,a— 97).
Другие варианты сравнения
Только начало строки — strncmp(a, b, n) сравнивает не больше n первых символов. Проверка, начинается ли строка с http: strncmp(s, "http", 4) == 0.
Без учёта регистра (чтобы Yes и yes считались одинаковыми) — в стандарте C такой функции нет. В Linux и macOS есть strcasecmp из <strings.h>, в Windows — _stricmp из <string.h>. Переносимый способ — перевести обе строки в один регистр функцией tolower из ctype.h и сравнить.
Один символ — это не строка, его сравнивают через ==: if (s[0] == 'y'). Одинарные кавычки — символ, двойные — строка.
Подводные камни
\nпослеfgets. Введеноyes, а в массивеyes\n—strcmpне вернёт 0. Уберите перевод строки:s[strcspn(s, "\n")] = '\0';.- Русские буквы.
strcmpсравнивает байты UTF-8. Равенство строк он проверяет верно, а порядок по алфавиту для русских слов в одном регистре — почти верно. Исключение — «ё»: маленькая окажется после «я», а большая «Ё» — перед «А». if (strcmp(a, b))— условие верно, когда строки разные (результат не ноль). Запись легко понять наоборот, поэтому лучше писать явно:strcmp(a, b) != 0.