Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблема getchar(), Считывается только один символ с stdin 
V
    Опции темы
den140387
Дата 16.1.2012, 13:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 21.12.2011

Репутация: нет
Всего: нет



Добрый день!
Возникла проблема при использовании функции 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();

но это почему- то не помогло...
PM MAIL   Вверх
bsa
Дата 16.1.2012, 13:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



den140387, когда ты нажимаешь клавишу ввод, то программа от клавиатуры получает именно код этой клавиши. Так всегда было, есть и будет. Это абсолютно нормальное поведение.
Решить твою проблему можно считывая лишний символ или используя 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;
}


Это сообщение отредактировал(а) bsa - 16.1.2012, 13:28
PM   Вверх
xvr
Дата 16.1.2012, 13:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



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

PM MAIL   Вверх
den140387
Дата 16.1.2012, 14:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 21.12.2011

Репутация: нет
Всего: нет



bsa, xvr, спасибо за помощь!
Цитата

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

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

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

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

Это сообщение отредактировал(а) den140387 - 16.1.2012, 14:02
PM MAIL   Вверх
bsa
Дата 16.1.2012, 14:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Цитата(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.

PM   Вверх
den140387
Дата 16.1.2012, 14:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 21.12.2011

Репутация: нет
Всего: нет



Спасибо! smile 
Теперь понятно, что fflush не всегда очищает входной буфер.
PM MAIL   Вверх
bsa
Дата 16.1.2012, 14:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



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

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

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

PM   Вверх
den140387
Дата 16.1.2012, 14:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 21.12.2011

Репутация: нет
Всего: нет



Цитата

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

Видимо, у меня не такая реализация библиотеки libc
Спасибо за помощь!
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0503 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.