У меня есть такая программа:
int main(int argc, char *argv[])
{
char ch1, ch2;
printf("Input the first character:"); // Line 1
scanf("%c", &ch1);
printf("Input the second character:"); // Line 2
ch2 = getchar();
printf("ch1=%c, ASCII code = %d\n", ch1, ch1);
printf("ch2=%c, ASCII code = %d\n", ch2, ch2);
system("PAUSE");
return 0;
}
Как объяснил автор приведенного выше кода: Программа не будет работать должным образом, потому что в строке 1, когда пользователь нажимает Enter, во входном буфере остается 2 символа: Enter key (ASCII code 13)
и \n (ASCII code 10)
. Следовательно, в строке 2 он будет читать \n
и не будет ждать, пока пользователь введет символ.
Хорошо, я понял. Но мой первый вопрос: почему второй getchar()
( ch2 = getchar();
) не читает Enter key (13)
, а не \n
символ?
Далее автор предложил 2 способа решения таких проблем:
использовать
fflush()
напишите такую функцию:
void clear (void) { while ( getchar() != '\n' ); }
Этот код действительно работал. Но я не могу себе объяснить, как это работает? Поскольку в операторе while, который мы используем getchar() != '\n'
, это означает чтение любого отдельного символа, кроме '\n'
? если да, то во входном буфере все равно остается '\n'
символ?
getchar()
будет читать и возвращать эти символы; пользователю не нужно будет нажимать Enter в другой раз. Кроме того, в то время как termios может быть общим на Linux , это не является частью стандартной библиотеки C .scanf(" %c", &char_var)
работы и игнорирования новой строки, просто добавив пробел перед спецификатором% c?Вы можете сделать это (также) следующим образом:
fseek(stdin,0,SEEK_END);
источник
fseek
доступно дляstdin
?Переносимый способ очистить до конца строку, которую вы уже пытались частично прочитать:
int c; while ( (c = getchar()) != '\n' && c != EOF ) { }
Он читает и отбрасывает символы до тех пор, пока не получит
\n
сигнал о конце файла. Он также проверяет,EOF
закрывается ли входной поток до конца строки. Типc
должен бытьint
(или больше), чтобы можно было хранить значениеEOF
.Нет переносимого способа узнать, есть ли еще строки после текущей строки (если их нет, то
getchar
ввод будет заблокирован).источник
Линии:
int ch; while ((ch = getchar()) != '\n' && ch != EOF) ;
не читает только символы перед переводом строки (
'\n'
). Он считывает все символы в потоке (и отбрасывает их) вплоть до следующего перевода строки (или встречается EOF). Чтобы тест был верным, он должен сначала прочитать перевод строки; поэтому, когда цикл останавливается, перевод строки был последним прочитанным символом, но он был прочитан.Что касается того, почему он читает перевод строки вместо возврата каретки, это потому, что система перевела возврат на перевод строки. Когда нажата клавиша ввода, это сигнализирует об окончании строки ... но вместо этого поток содержит перевод строки, поскольку это обычный маркер конца строки для системы. Это может зависеть от платформы.
Кроме того, использование
fflush()
входящего потока работает не на всех платформах; например, это обычно не работает в Linux.источник
while ( getchar() != '\n' );
долженgetchar()
возвращаться бесконечный циклEOF
из-за конца файла.int ch; while ((ch = getchar()) != '\n' && ch != EOF);
можно также использоватьВы можете не осознавать, что сравнение происходит после
getchar()
удаления символа из входного буфера. Итак, когда вы дойдете до'\n'
, он потребляется, а затем вы выходите из цикла.источник
ты можешь попробовать
scanf("%c%*c", &ch1);
где% * c принимает и игнорирует новую строку
еще один метод вместо fflush (stdin), который вызывает неопределенное поведение, вы можете написать
while((getchar())!='\n');
не забывайте точку с запятой после цикла while
источник
"%*c"
сканирует любой символ (и не сохраняет его), будь то перевод строки или что-то еще. Код полагается на то, что второй символ - это новая строка. 2)while((getchar())!='\n');
- бесконечный цикл долженgetchar()
возвращатьсяEOF
из-за конца файла.Я столкнулся с проблемой при попытке реализовать решение
while ((c = getchar()) != '\n' && c != EOF) { }
Я публикую небольшую корректировку «Код В» для всех, у кого может быть такая же проблема.
Проблема заключалась в том, что программа заставляла меня ловить символ '\ n', независимо от символа ввода, вот код, который дал мне проблему.
Код А
int y; printf("\nGive any alphabetic character in lowercase: "); while( (y = getchar()) != '\n' && y != EOF){ continue; } printf("\n%c\n", toupper(y));
и корректировка заключалась в том, чтобы `` поймать '' символ (n-1) непосредственно перед вычислением условного оператора в цикле while, вот код:
Код B
int y, x; printf("\nGive any alphabetic character in lowercase: "); while( (y = getchar()) != '\n' && y != EOF){ x = y; } printf("\n%c\n", toupper(x));
Возможное объяснение состоит в том, что для прерывания цикла while он должен присвоить значение '\ n' переменной y, так что это будет последнее присвоенное значение.
Если я что-то пропустил с пояснением, кодом A или кодом B, скажите, пожалуйста, я новичок в c.
надеюсь, это поможет кому-то
источник
while
цикла. После цикла вы можете считатьstdin
его чистым / чистым иy
удерживать либо '\n
', либоEOF
.EOF
возвращается, когда новой строки нет и буфер исчерпан (если ввод переполнял буфер до того, как[ENTER]
был нажат). - Вы эффективно используете,while((ch=getchar())!='\n'&&ch!=EOF);
чтобы пережевывать каждый символ воstdin
входном буфере.unsigned char a=0; if(kbhit()){ a=getch(); while(kbhit()) getch(); } cout<<hex<<(static_cast<unsigned int:->(a) & 0xFF)<<endl;
-или же-
использовать возможно использовать
_getch_nolock()
.. ???источник
kbhit()
иgetch()
- это функции, объявленные в<conio.h>
Windows и доступные только в качестве стандартных. Их можно эмулировать на Unix-подобных машинах, но это требует некоторой осторожности.Другое решение, о котором еще не упоминалось, - это использовать: rewind (stdin);
источник
Я удивлен, что никто об этом не упомянул:
scanf("%*[^\n]");
источник
Короткий, переносимый и заявленный в stdio.h
stdin = freopen(NULL,"r",stdin);
Не зависает в бесконечном цикле, когда на стандартном вводе нечего сбрасывать, как в следующей хорошо известной строке:
while ((c = getchar()) != '\n' && c != EOF) { }
Немного дорого, поэтому не используйте его в программе, которая должна многократно очищать буфер.
Украл у коллеги :)
источник
freopen
том, что вы не можете переноситьstdin
. Это макрос.Попробуй это:
stdin->_IO_read_ptr = stdin->_IO_read_end;
источник