LINUX.ORG.RU

[C][noob][getchar][ЧЯДНТ][console]Считать 1 (один) символ с клавиатуры.

 , , ,


0

1

Как считать с клавиатуры один единственный байт, читай: нажатие одной клавиши, записать этот байт в переменную и продолжить исполнение программы. Вот канонический пример:

#include <stdio.h>

int main ()
{
  char c;
  puts ("Enter text. Include a dot ('.') in a sentence to exit:");
  do {
    c=getchar();
    putchar (c);
  } while (c != '.');
  return 0;
}
Чего я ожидаю от этой программы? Набираю «abc.», вижу на экране «aabbcc..». А вместо этого
abc.<enter>
abc.
Где это «abc.» хранится? Я же только 1 байт отвёл под эту переменную, а «abc.» это как минимум 4. ЧЯДНТ?

★★★★★

#include <stdio.h>

int main ()
{
  char c;
  int i = 0;
  puts ("Enter text. Include a dot ('.') in a sentence to exit:");
  do {
    i ++;
    c=getchar();
    putchar (c);
  } while (c != '.');
  printf("%d\n", i);
  return 0;
}
ttnl ★★★★★
()

классика (=

while(c=getchar() != '.')
{
   putchar(c);  
}
[[/code]]
Andersen ★★
()

Ввод и вывод буферизуются терминалом (ЕМНИП).
Нужно перейти в raw-mode.


Normally the terminal driver buffers the characters a user types until a new line or carriage return is encountered.

schizoid ★★★
()

>abc.<enter>
У тебя по сути Enter и есть конец ввода. Зачем точка?

Чего я ожидаю от этой программы? Набираю «abc.», вижу на экране «aabbcc..». А вместо этого

Если нужен повтор каждого введённого символа, то

#include <stdio.h>

#define SIZE 100

static char buffer[SIZE];

int main(void)
{
int tmp;
fgets(buffer, SIZE, stdin);
for (tmp=0; tmp < SIZE; tmp++){
printf(«%c», buffer[tmp]);
printf(«%c», buffer[tmp]);
}
return 0;
}

sched
()

Да, если нужно отправить ввода сразу программе, нужно жать не Enter, а Ctrl-D.

sched
()

> Как считать с клавиатуры один единственный байт, читай: нажатие одной клавиши

Чтобы считать символ сразу после того, как он введен, нужно перевести stdin в режим raw.

Где это «abc.» хранится? Я же только 1 байт отвёл под эту переменную, а «abc.» это как минимум 4. ЧЯДНТ?

stdin - буферизованный поток, данные передаются getchar при нажатии Enter.

tailgunner ★★★★★
()

нужно отFLUSHить stdout же.

просто сейчас происходит буферизированный вывод. т.е. текст отображается только по заполнению буфера/переводе строки

do0dlez ★★
()
Ответ на: комментарий от tailgunner

tailgunner

stdin - буферизованный поток, данные передаются getchar при нажатии Enter.

ой да, неправ

do0dlez ★★
()
Ответ на: комментарий от schizoid

Нашёл решение.

Нужно перейти в raw-mode.

stdin - буферизованный поток, данные передаются getchar при нажатии Enter.

Пользуясь этими подсказками я нашёл решение. На StackOverflow есть пример кода:

#include<stdio.h>
#include <termios.h>            //termios, TCSANOW, ECHO, ICANON
#include <unistd.h>     //STDIN_FILENO


int main(void){   
    int c;   
    static struct termios oldt, newt;

    /*tcgetattr gets the parameters of the current terminal
    STDIN_FILENO will tell tcgetattr that it should write the settings
    of stdin to oldt*/
    tcgetattr( STDIN_FILENO, &oldt);
    /*now the settings will be copied*/
    newt = oldt;

    /*ICANON normally takes care that one line at a time will be processed
    that means it will return if it sees a "\n" or an EOF or an EOL*/
    newt.c_lflag &= ~(ICANON);          

    /*Those new settings will be set to STDIN
    TCSANOW tells tcsetattr to change attributes immediately. */
    tcsetattr( STDIN_FILENO, TCSANOW, &newt);

    /*This is your part:
    I choose 'e' to end input. Notice that EOF is also turned off
    in the non-canonical mode*/
    while((c=getchar())!= 'e')      
        putchar(c);                 

    /*restore the old settings*/
    tcsetattr( STDIN_FILENO, TCSANOW, &oldt);


    return 0;
}

Camel ★★★★★
() автор топика
Ответ на: Нашёл решение. от Camel

Может быть лучше использовать что-нибудь вроде ncurses, чтобы было более кроссплатформенно?

Yareg ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.