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
, Если возраст - одна цифра, оригинальная программа работает нормально.