C Программа не завершится после сравнения с пустой строкой - PullRequest
3 голосов
/ 24 апреля 2020

Я пытаюсь завершить свою программу C, проверив наличие пустой строки (""), но, похоже, она не работает. Я тоже пытался сравнить с \ 0, но безрезультатно.

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

int main(void) {
    char nameInput[128];
    for(;;) {
        printf("Enter nation name: ");
        scanf("%s", nameInput);
        if(!strcmp(nameInput, "")){
            break;
        }
        printf("Got nation named \"%s\"\n", nameInput);
    }
    printf("All done getting nations!\n");
    return 0;
}

Ответы [ 2 ]

5 голосов
/ 24 апреля 2020

Спецификатор "%s" в scanf("%s", nameInput); сначала потребляет 1 и отбрасывает первые пробелы, включая все '\n' из Введите перед сканированием и сохранением в nameInput.

Именно поэтому повторные записи пустых строк не продвигают сканирование. "%s" ожидает некоторого ввода без пробелов.


Лучшей альтернативой scanf() является чтение всего пользовательского ввода с помощью fgets(), а затем анализ строки .

fgets() читает строку и сохраняет результат в виде строки - обычно включая окончание строки '\n'.

// scanf("%s", nameInput);
if (fgets(nameInput, sizeof nameInput, stdin)) {
  // Success at reading input.
  nameInput[strcspn(nameInput, "\n")] = '\0'; // lop off the potential trailing \n

  if(!strcmp(nameInput, "")){  // or simply `if(nameInput[0] == '\0')
    break;
  }
  ...

также пытались сравнить с \ 0, но безрезультатно.

if(!strcmp(nameInput, "")) и if(!strcmp(nameInput, "\0")) делают то же самое. strcmp() сравнивает строк .

"" - строковый литерал из 1 char: нулевой символ .
"\0" - строковый литерал из 2 char: два нулевых символа .
строка сравнение останавливается на первом нулевом символе .


"%s" само по себе также не имеет ограничения по ширине. Код не имеет надежной защиты от ввода типа «BlahBlah ... (120_some_more) Blah») и может привести к неопределенному поведению из-за переполнения буфера char nameInput[128];. Код мог бы использовать "%127s", чтобы предотвратить это, но он обрабатывает только один из недостатков scanf().


1

Пропущенные символы пробела (как определено функцией isspace) пропускаются, если в спецификации не указано * 1078 Спецификатор *, c или n. C17dr § 7.21.6.2 8

3 голосов
/ 24 апреля 2020

Дело не в том, что он не будет завершен, он ожидает ввода, который еще не был (еще) введен.

scanf не использует правильную строку шаблона для сканирования чего-либо (включая ничего) ) до возврата кареты. Вам нужно изучить шаблоны scanf и изменить шаблон с "% s" на то, что scanf примет в качестве входных данных.

Если вы протестируете свою программу, вы увидите, что после нажав «enter», вы можете ввести слово и снова нажать «enter», и, поскольку теперь у вас есть слово во вводе, scanf поднимает его (отбрасывая пробел, как и в случае с «% s»).

...