Como evitar pressionar enter com getchar ()

Esta é uma questão “novato” para a linguagem de programação C:

No próximo código:

#include  int main(void) { int c; while ((c=getchar())!= EOF) putchar(c); return 0; } 

Eu tenho que pressionar Enter para imprimir todas as letras que eu getchar com getchar , mas eu não quero fazer isso, o que eu quero fazer é pressionar a letra e ver imediatamente a letra que eu introduzi repetida sem pressionar Enter . Por exemplo, se eu pressionar a letra ‘a’, eu quero ver um outro ‘a’ próximo a ele, e assim por diante:

 aabbccddeeff..... 

Mas quando pressiono ‘a’ nada acontece, posso escrever outras letras e a cópia aparece somente quando pressiono Enter :

 abcdef abcdef 

Como posso fazer isso?

Eu estou usando o comando cc -o example example.c no Ubuntu para compilar.

    Em um sistema linux, você pode modificar o comportamento do terminal usando o comando stty . Por padrão, o terminal armazenará todas as informações em buffer até que Enter seja pressionado, antes mesmo de enviá-las para o programa em C.

    Um exemplo rápido, sujo e não particularmente portátil para alterar o comportamento de dentro do próprio programa:

     #include int main(void){ int c; /* use system call to make terminal send all keystrokes directly to stdin */ system ("/bin/stty raw"); while((c=getchar())!= '.') { /* type a period to break out of the loop, since CTRL-D won't work raw */ putchar(c); } /* use system call to set terminal behaviour to more normal behaviour */ system ("/bin/stty cooked"); return 0; } 

    Por favor, note que isso não é realmente ideal, já que ele presume que stty cooked é o comportamento que você quer quando o programa sai, ao invés de verificar quais eram as configurações originais do terminal. Além disso, como todo processamento especial é ignorado no modo raw, muitas seqüências de teclas (como CTRL-C ou CTRL-D ) não funcionam como você espera, sem processá-las explicitamente no programa.

    Você pode man stty para obter mais controle sobre o comportamento do terminal, dependendo exatamente do que você deseja alcançar.

    Isso depende do seu sistema operacional, se você estiver em um ambiente semelhante ao UNIX, o sinalizador ICANON é ativado por padrão, portanto, a input é armazenada em buffer até o próximo '\n' ou EOF . Ao desativar o modo canônico, você receberá os caracteres imediatamente. Isso também é possível em outras plataformas, mas não há uma solução direta entre plataformas.

    EDIT: vejo que você especificou que você usa o Ubuntu. Acabei de postar algo semelhante ontem, mas esteja ciente de que isso desativará muitos comportamentos padrão do seu terminal.

     #include #include  //termios, TCSANOW, ECHO, ICANON #include  //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; } 

    Você notará que todo personagem aparece duas vezes. Isso ocorre porque a input é imediatamente retornada ao terminal e, em seguida, seu programa a coloca de volta com putchar() também. Se você quiser desassociar a input da saída, você também precisará ativar a sinalização ECHO. Você pode fazer isso simplesmente mudando a linha apropriada para:

     newt.c_lflag &= ~(ICANON | ECHO); 

    getchar () é uma function padrão que em muitas plataformas requer que você pressione ENTER para obter a input, porque a plataforma armazena a input até que a tecla seja pressionada. Muitos compiladores / plataformas suportam o getch () não padrão que não se importa com o ENTER (ignora o buffer de plataforma, trata o ENTER como apenas uma outra chave).

    E / S é uma function do sistema operacional. Em muitos casos, o sistema operacional não passará o caractere typescript para um programa até que ENTER seja pressionado. Isso permite que o usuário modifique a input (como retrocesso e redigitação) antes de enviá-la ao programa. Para a maioria das finalidades, isso funciona bem, apresenta uma interface consistente para o usuário e alivia o programa de ter que lidar com isso. Em alguns casos, é desejável que um programa obtenha os caracteres das teclas à medida que eles são pressionados.

    A própria biblioteca C lida com arquivos e não se preocupa com a forma como os dados entram no arquivo de input. Portanto, não há como a própria linguagem obter chaves à medida que elas são pressionadas; em vez disso, isso é específico da plataforma. Como você não especificou o sistema operacional ou o compilador, não podemos procurar por você.

    Além disso, a saída padrão é normalmente armazenada em buffer para eficiência. Isso é feito pelas bibliotecas C e, portanto, há uma solução C, que é fflush(stdout); depois de cada personagem escrito. Depois disso, se os caracteres são exibidos imediatamente é até o sistema operacional, mas todos os sistemas operacionais que eu conheço irá exibir a saída imediatamente, então isso não é normalmente um problema.

    Como você está trabalhando em um derivado Unix (Ubuntu), aqui está uma maneira de fazer isso – não é recomendado, mas funcionará (contanto que você possa digitar comandos com precisão):

     echo "stty -g $(stty -g)" > restore-sanity stty cbreak ./your_program 

    Use a interrupção para interromper o programa quando estiver entediado com ele.

     sh restore-sanity 
    • A linha ‘echo’ salva as configurações atuais do terminal como um script de shell que irá restaurá-las.
    • A linha ‘stty’ desativa a maior parte do processamento especial (portanto, o Control-D não tem efeito, por exemplo) e envia caracteres para o programa assim que eles estiverem disponíveis. Isso significa que você não pode mais editar sua digitação.
    • A linha ‘sh’ restabelece as configurações originais do terminal.

    Você pode economizar se ‘stty sane’ restaurar suas configurações com precisão suficiente para seus propósitos. O formato de ‘-g’ não é portátil entre as versões de ‘stty’ (portanto, o que é gerado no Solaris 10 não funciona no Linux, ou vice-versa), mas o conceito funciona em todos os lugares. A opção ‘stty sane’ não está disponível universalmente, AFAIK (mas está no Linux).

    Eu gosto de Lucas responder, mas gostaria de elaborar um pouco. Existe uma function termios.h em termios.h chamada cfmakeraw() que o homem descreve como:

     cfmakeraw() sets the terminal to something like the "raw" mode of the old Version 7 terminal driver: input is available character by character, echoing is disabled, and all special processing of terminal input and output characters is disabled. [...] 

    Isso basicamente faz o mesmo que o Lucas sugeriu e mais, você pode ver os flags exatos que ele define nas man pages: termios (3) .

    Caso de uso

     int c = 0; static struct termios oldTermios, newTermios; tcgetattr(STDIN_FILENO, &oldTermios); newTermios = oldTermios; cfmakeraw(&newTermios); tcsetattr(STDIN_FILENO, TCSANOW, &newTermios); c = getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &oldTermios); switch (c) { case 113: // q printf("\n\n"); exit(0); break; case 105: // i printf("insert\n"); break; default: break; 

    Por padrão, a biblioteca C armazena em buffer a saída até ver um retorno. Para imprimir os resultados imediatamente, use fflush :

     while((c=getchar())!= EOF) { putchar(c); fflush(stdout); } 

    Você pode include a biblioteca ‘ncurses’ e usar getch() vez de getchar() .

    sim você pode fazer isso no windows também, aqui está o código abaixo, usando a biblioteca conio.h

     #include  //basic input/output #include  //provides non standard getch() function using namespace std; int main() { cout < < "Password: "; string pass; while(true) { char ch = getch(); if(ch=='\r'){ //when a carriage return is found [enter] key cout << endl << "Your password is: " << pass < 

    Eu tive este problema / pergunta em uma tarefa que estou trabalhando atualmente. Também depende de qual input você está pegando. estou usando

     /dev/tty 

    para obter input enquanto o programa está em execução, de modo que precisa ser o stream de arquivos associado ao comando.

    Na máquina ubuntu eu tenho que testar / target, é preciso mais que apenas

     system( "stty -raw" ); 

    ou

     system( "stty -icanon" ); 

    Eu tive que adicionar o sinalizador –file, bem como o caminho para o comando, assim:

     system( "/bin/stty --file=/dev/tty -icanon" ); 

    Tudo é copacético agora.