Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Проблема getchar()


Автор: den140387 16.1.2012, 13:12
Добрый день!
Возникла проблема при использовании функции getchar.
Хочу с клавиатуры ввести 2 символа, но getchar считывает только один, а в качестве второго пишет код '\n'

Код

int main( void)
{
    int c1, c2;

    /* Тут все правильно работает. getchar блокирует терминал и ждет ввода
     * символа. Я ввожу 'a' и нажимаю <Enter> */
    c1 = getchar( );

    /* Код символа 'a': c1 = 97 */
    printf("c1=%d\n", c1);

    /* В этом месте не происходит блокировки терминала.
     * В качестве c2 getchar воспринимает код клавиши <Enter>, введенный ранее,
     * то есть по сути код символа '\n'*/
    c2 = getchar( );

    /* с2 = 10 */
    printf("c2=%d\n", c2);

    return 0;
}


Компиляция и запуск:
$ gcc-4.1.2 -Wall t.c
$ ./a.out
a

c=97
c=10

Я понимаю, почему так происходит. В качестве второго символа getchar воспринимает ранее введенный код клавиши <Enter>
(символ '\n',  если я не ошибаюсь.)

А как сделать так, чтобы и при втором вводе getchar блокировал терминал и ожидал ввод нового символа?
Да, есть конечно решение в лоб:
Код

while( ( c = getchar() ) != '\n' )
 
но не хотелось бы каждый раз при вводе символа писать данную конструкцию..
Может быть, эксперты Си подскажут более изящное решение?
Пробывал между первым и вторым вводом ставить:
Код

c1 = getchar();
fflush( stdin);
c2 = getchar();

но это почему- то не помогло...

Автор: bsa 16.1.2012, 13:26
den140387, когда ты нажимаешь клавишу ввод, то программа от клавиатуры получает именно код этой клавиши. Так всегда было, есть и будет. Это абсолютно нормальное поведение.
Решить твою проблему можно считывая лишний символ или используя http://www.cplusplus.com/reference/clibrary/cstdio/scanf/ вместо getchar():
Код
int main( void)
{
    int c1, c2;
    scanf(" %c", &c1);
    printf("c1=%d\n", c1);
    scanf(" %c", &c2); //пробел перед %c обязателен!!!
    printf("c2=%d\n", c2);
    return 0;
}

Автор: xvr 16.1.2012, 13:46
Еще можно заставить не ждать нажатия Enter (т.е. перевести терминал в так называемый raw режим), но это делается системно зависимыми средствами.
Есть еще вариант - удалять все из буфера ввода перед чтением: fflush(stdin);

Автор: den140387 16.1.2012, 14:01
bsa, xvr, спасибо за помощь!
Цитата

Есть еще вариант - удалять все из буфера ввода перед чтением: fflush(stdin);

Так я пробывал.. Результат от этого не меняется..
Код

c1 = getchar();
fflush( stdin);
c2 = getchar();

Вы не могли бы объяснить, что я неправильно сделал в этом коде?
Почему из буфер ввода не очищается перед вводом c2?

Автор: bsa 16.1.2012, 14:12
Цитата(http://www.cplusplus.com/reference/clibrary/cstdio/fflush/)
If it was open for reading and the last operation was an input operation, the behavior depends on the specific library implementation. In some implementations this causes the input buffer to be cleared, but this is not standard behavior.

Автор: den140387 16.1.2012, 14:14
Спасибо! smile 
Теперь понятно, что fflush не всегда очищает входной буфер.

Автор: bsa 16.1.2012, 14:20
Цитата(den140387 @  16.1.2012,  15:14 Найти цитируемый пост)
Теперь понятно, что fflush не всегда очищает входной буфер. 
Вывод ты сделал не верный. Поведение fflush() для файлов, отрытых на чтения, не определено. В некоторых системах (точнее, реализациях libc) может происходить очистка входного буфера.

Добавлено через 42 секунды

M
bsa
den140387, если ответ на вопрос получен, то пометь тему решенной

Автор: den140387 16.1.2012, 14:22
Цитата

В некоторых системах (точнее, реализациях libc) может происходить очистка входного буфера. 

Видимо, у меня не такая реализация библиотеки libc
Спасибо за помощь!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)