Puts() и Gets() не работают при использовании после scanf()

Кажется, что функции puts() и gets() не работают, если я использую scanf() перед gets() и puts(). Пожалуйста, смотрите код ниже.

Если я удалю раздел раньше, puts() и gets() будут работать нормально. Почему это?

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

int main (void)
{
    int numberOutcomes;
    char outcomeOne[50];

    printf("How many outcomes do you have on your form?\n");
    scanf(" %d", &numberOutcomes);
    printf("The number of outcomes you have on your form is %d\n", numberOutcomes);

    printf("Type in your first outcome then press Enter. For example: good outcome or bad outcome.\n");
    gets(outcomeOne);

    puts(outcomeOne);

    return 0;
}

person stephen Ong    schedule 18.08.2020    source источник


Ответы (1)


Первый совет: не используйте gets() — нет безопасного способа его использования, чтобы избежать возможного переполнения буфера (это одна из немного вещей, которые даже был удален из стандарта ISO, начиная с C11). Вместо этого используйте fgets(), который может ограничить считывание.

Что касается вашей конкретной проблемы, scanf(" %d", &numberOutcomes) после пропуска пробелов потребляет достаточно символов во входном потоке, чтобы заполнить numberOutcomes, и не более того. Важно отметить, что это не будет использовать завершающие пробелы, такие как символ \n, который был помещен туда, когда вы нажали ENTER для подтверждения ввода.

Следовательно, при вызове gets() он просто получит пустую строку.

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

Вы можете заставить работать, смешав их, но это требует немного больше усилий.

Я бы посоветовал использовать линейный ввод для всего, а затем sscanf определенные данные из строки, которую вы читаете. Это имеет следующие преимущества:

  • избегание именно той проблемы, которую вы обнаружили; а также
  • позволяя вам sscanf несколько раз в одной и той же строке, если вам нужно обрабатывать несколько форматов строк.

Для этого надежная процедура линейного ввода (например, in-c/4023921#4023921">этот) очень удобен.

person paxdiablo    schedule 18.08.2020