fgets() не запрашивает пользователя второй раз

Вот как код написан.

int main()
{   
    char enteredName[30];
    char stringNum[4];
    char continueLetter = 0;
    int continueProgram = 0;
    int enteredAge;
    int i;

    do
    {
    memset(enteredName,'\0', 30);
    printf("Please enter a name: ");
    fgets(enteredName, 29, stdin);

    printf("\n\nNow please enter your age: ");
    fgets(stringNum, 3, stdin );

    for(i = 0; i < 30; i++)
    {
        if (enteredName[i] == '\n')
        {
            enteredName[i] = '\0';
            break;
        }
    }

    for(i = 0; i < 4; i++)
    {
        if (stringNum[i] == '\n')
        {
            stringNum[i] = '\0';
            break;
        }
    }

    enteredAge = atol(stringNum);
} while();

Когда я повторяю цикл во второй раз, я не могу ввести новое имя в массив символов, оно просто переходит к следующему приглашению (возраст). Если эта проблема не связана со связанными списками, проблема, похоже, связана с чем-то другим. Не могли бы вы помочь мне найти ошибку? Спасибо!

4 ответа

Проблема в том, что вы не очищаете входной буфер, поэтому fgets() Переносит вас непосредственно ко второму запросу, спрашивающему возраст. Это распространенная проблема, просто добавьте fflush(stdin);//my compiler supports itпосле fgets();Вот код, который работал для меня, надеюсь, он работает и для вас:

РЕДАКТИРОВАТЬ: Есть один очень полезный пост, предоставляющий информацию о fflush(). Как описано, fflush в основном предназначен для вызова в выходной поток. Хотя некоторые компиляторы предоставляют поддержку для очистки stdin, это считается неопределенным поведением. Хотя, еще раз посмотрев на программу, я обнаружил, что с помощью sizeof может творить чудеса и действительно, поэтому я изменил программу в лучшую сторону. Использование sizeof также описано в одном из ответов здесь.

#include<stdio.h>
#include<stdlib.h>
int main()
{   
    char enteredName[30];
    char stringNum[4];
    int continueProgram=0;
    int i;

   while(continueProgram<3)
      {
        setbuf(stdout,NULL);
    printf("Please enter a name: ");
    fgets(enteredName, sizeof enteredName, stdin);
    printf("\n\nNow please enter your age: ");
    fgets(stringNum,sizeof stringNum, stdin );

   for(i = 0; i < 30; i++)
    {
        if (enteredName[i] == '\n')
        {
            enteredName[i] = '\0';
            break;
        }
    }

    for(i = 0; i < 4; i++)
    {
        if (stringNum[i] == '\n')
        {
            stringNum[i] = '\0';
            break;
        }
    }

    //enteredAge = atol(stringNum);
    continueProgram++;
    }
    return 0;
}

Ваш второй fgets вызов оставляет символы (в частности, символ новой строки), ожидающие чтения stdin если вы введете двузначный возраст.

Увеличьте параметр длины, чтобы он соответствовал размеру массива:

fgets(stringNum, 4, stdin);

Или лучше:

fgets(stringNum, sizeof stringNum, stdin);

Вы, вероятно, хотите сделать то же самое для enteredName,

От fgets(3) справочная страница:

fgets() функция читает не более, чем на количество символов, указанное size из данного потока и сохраняет их в строке str,

Вам не нужно резервировать дополнительную запись массива для нулевого терминатора, как вы делаете - fgets справится с этим самостоятельно.

Вы попробуйте следующий фрагмент кода:

if(stringNum[strlen(arr)-1]=='\n')
     stringNum[strlen(arr)-1]='\0';
else
     while(getchar()!='\n');

Всякий раз, когда вы вводите двухзначный возраст, символ новой строки, который вы вставляете при нажатии клавиши ввода, сохраняется в буфере. Что делает этот фрагмент кода выше, так это то, что он проверит, заполнен ли последний символ вашего хранилища символом новой строки, если да, то он заменит его нулевым терминатором. Иначе, он будет продолжать чтение из буфера до тех пор, пока символ новой строки не будет удален из буфера.

PS: Если вы используете borland, то у вас будет fflush(stdin) для удаления любого дополнительного символа из буфера, как указано PHlFounder, но если вам случится использовать gcc, тогда этот метод очень хорош.

Также вы можете создать функцию или макрос для этого фрагмента кода и вызывать его каждый раз, когда вам нужно, например.

void function(char * arr)
{
        if(arr[strlen(arr)-1]=='\n')
                arr[strlen(arr)-1]='\0';
        else
                while(getchar()!='\n')
}

Проблема в том, что вы не знаете, содержит ли прочитанная строка newline или нет. Если он не содержит newlineто это будет прочитано при следующем вызове fgetsоставляя в нем пустую строку. Чтобы предотвратить это, проверьте, содержит ли строка newline персонаж в конце. Если не просто прочитать, используя getchar() и вуаля!!(Обратите внимание, что это решение относится только к вашей проблеме, а не в целом). Этот код должен быть добавлен после прочтения stringNum строка.

if(stringNum[strlen(stringNum)-1]!='\n')
{
    getchar();
}

Это происходило потому, что если возраст двузначный, то fgets будет читать до последней цифры, а не newline персонаж. Итак, вам нужно прочитать его, если последний символ не \n, Если возраст - одна цифра, оригинальная программа работает нормально.

Другие вопросы по тегам