Проблема с scanf и fgets - PullRequest
       32

Проблема с scanf и fgets

3 голосов
/ 08 февраля 2011

Это домашнее задание для сортировки заданных строк.Я запрашиваю у пользователя количество строк, которые они хотели бы отсортировать с помощью scanf, выделяя массив на основе этого числа, а затем получаю сами строки с помощью fgets.

Все отлично работаетесли количество строк жестко запрограммировано, но добавление scanf позволяет пользователю решить проблему.Вот код:

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

#define LENGTH  20 // Maximum string length.

int main(void)
{
    int index, numStrings = 0;
    char **stringArray;
    printf("Input the number of strings that you'd like to sort: ");
    assert(scanf("%d", &numStrings) == 1);
    stringArray = (char **)malloc(numStrings * sizeof(char *));

    for (index = 0; index < numStrings; index++)
    {
        stringArray[index] = (char *)malloc(LENGTH * sizeof(char));
        assert(stringArray[index] != NULL);
        printf("Input string: ");
        assert(fgets(stringArray[index], LENGTH, stdin) != NULL);
    }

    // Sort strings, free allocated memory.

    return 0;
}

А вот как выглядит консоль:

Input the number of strings that you'd like to sort: 3
Input string: Input string: foo
Input string: bar

Она пропускает первую итерацию цикла, что приводит к пустой строке в началемассив.У меня вопрос, почему он это делает и как я могу это исправить?


Вот как выглядит консоль со строкой формата "%d\n", переданной scanf:

Input the number of strings that you'd like to sort: 3
foo
Input string: Input string: bar
Input string: baz

Итак, я могу ввести все строки, но первая подсказка для строки находится не в том месте.

Ответы [ 2 ]

6 голосов
/ 08 февраля 2011

Вы должны сказать scanf, что нужно заглушить \ n, вставив \ n в scanf:

scanf("%d\n", &numStrings)

без него, scanf будет читать остаточный символ новой строки [после нажатия кнопки ввода] какпервая строка в цикле

3 голосов
/ 08 февраля 2011

Реальный ответ (по моему скромному, но очень правильному мнению: P) - не использовать scanf. Используйте fgets, чтобы прочитать первую строку (то есть число), а затем проанализируйте эту строку, скажем, sscanf или strtoul. Таким образом, у вас есть возможность обрабатывать ошибки, когда кто-то не вводит данные в хорошем формате, и вам не нужно взламывать отсутствие надежной обработки пробелов scanf.

Кроме того, никогда не используйте int для хранения размеров, если вы не предполагаете, что у вас будет много массивов с длиной -4. Стандарт определяет тип без знака size_t как тип без знака, достаточно большой для хранения размеров объектов и индексов массива. Использование любого другого типа не гарантированно работает.

...