strcmp на строке читается с помощью fgets - PullRequest
7 голосов
/ 09 марта 2010

Я пытаюсь сравнить две строки. Один хранится в файле, другой получен от пользователя (stdin).

Вот пример программы:

int main()
{
    char targetName[50];
    fgets(targetName,50,stdin);

    char aName[] = "bob";
    printf("%d",strcmp(aName,targetName));

    return 0;
}

В этой программе strcmp возвращает значение -1, когда ввод "bob". Почему это? Я думал, что они должны быть равны. Как я могу получить так, чтобы они были?

Ответы [ 6 ]

9 голосов
/ 09 марта 2010

strcmp - это одна из немногих функций, которая имеет обратные результаты true и false ... если строки равны, результатом будет 0, а не 1, как вы могли бы подумать ....

if (strcmp(a, b)) {
    /* Do something here as the strings are not equal */
} else {
    /* Strings are equal */
}

Говоря о fgets, есть вероятность, что к концу строки добавлена ​​новая строка ... вам нужно от нее избавиться ...

+-+-+-+--+--+
|b|o|b|\n|\0|
+-+-+-+--+--+

Чтобы избавиться от перевода строки, сделайте это. ПРЕДУПРЕЖДЕНИЯ: не используйте «strlen (aName) - 1», потому что строка, возвращаемая fgets, может начинаться с символа NUL - таким образом, индекс в буфере становится -1:

aName[strcspn(aName, "\n")] = '\0';

+-+-+-+--+
|b|o|b|\0|
+-+-+-+--+

Теперь strcmp должен вернуть 0 ...

6 голосов
/ 09 марта 2010

fgets читает до тех пор, пока не увидит символ новой строки, а затем вернется, поэтому при вводе bob в консоли targetName содержит «bob \ n», который не соответствует «bob». Из документации fgets: (добавлено жирным шрифтом)

Считывает символы из потока и сохраняет их в виде строки C в строке str до тех пор, пока не будет прочитано (num-1) символов или не будет достигнута новая строка или конец файла, в зависимости от того, что произойдет раньше. Символ новой строки заставляет fgets перестать читать, но он считается допустимым символом и поэтому включен в строку, скопированную в str. Нулевой символ автоматически добавляется в строку после символов, прочитанных для обозначения конца строки C.

Перед сравнением необходимо удалить символ новой строки в конце targetName.

int cch = strlen(targetName);
if (cch > 1 && targetName[cch-1] == '\n')
   targetName[cch-1] = '\0';

или добавьте новую строку в тестовую строку.

char targetName[50];
fgets(targetName,50,stdin);

char aName[] = "bob\n";
printf("%d",strcmp(aName,targetName));
3 голосов
/ 30 августа 2012

fgets добавляет \n к строке, которую вы извлекаете от пользователя, когда он нажимает Enter. Вы можете обойти это, используя strcspn или просто добавив \n в конец строки, которую вы пытаетесь сравнить.

printf("Please enter put FILE_NAME (foo1, 2, or 3), ls, or exit: \n");
fgets(temp, 8, stdin);
temp[strcspn(temp, "\n")] = '\0';
if(strcmp(temp, "ls") == 0 || strcmp(temp, "exit") == 0)

Это просто заменяет \n на \0, но если вы хотите быть ленивым, вы можете просто сделать это:

printf("Please enter put FILE_NAME (foo1, 2, or 3), ls, or exit: \n");
fgets(temp, 8, stdin);
if(strcmp(temp, "ls\n") == 0 || strcmp(temp, "exit\n") == 0)

Но это не так элегантно.

2 голосов
/ 09 марта 2010

Поскольку fgets встраивает символ новой строки в переменную targetName. Это скинуть сравнение.

1 голос
/ 09 марта 2010

Главным образом из-за конца строки char на входе "\ n" в unix-подобной системе.

1 голос
/ 09 марта 2010

fgets добавляет новую строку к строке, так что в итоге вы получите bob\n\0, что не совпадает с bob\0.

...