usar tecla pulsada presionar leer esperar detectar como c++ c inputstream

pulsada - leer tecla sin presionar enter c++



Capture caracteres de la entrada estándar sin esperar a que se presione la tecla enter (14)

Nunca recuerdo cómo hago esto porque aparece muy poco para mí. Pero en C o C ++, ¿cuál es la mejor manera de leer un carácter de la entrada estándar sin esperar una nueva línea (presione enter).

También idealmente no se haría eco del carácter de entrada en la pantalla. Solo quiero capturar las teclas sin afectar la pantalla de la consola.


Asumiendo Windows, eche un vistazo a la función ReadConsoleInput .


C y C ++ tienen una vista muy abstracta de E / S, y no hay una forma estándar de hacer lo que usted desea. Hay formas estándar de obtener caracteres del flujo de entrada estándar, si hay alguno para obtener, y ninguno de los dos idiomas está definido. Cualquier respuesta, por lo tanto, tendrá que ser específica de la plataforma, quizás dependiendo no solo del sistema operativo sino también del marco del software.

Aquí hay algunas conjeturas razonables, pero no hay forma de responder a su pregunta sin saber cuál es su entorno objetivo.


CONIO.H

las funciones que necesitas son:

int getch(); Prototype int _getch(void); Description _getch obtains a character from stdin. Input is unbuffered, and this routine will return as soon as a character is available without waiting for a carriage return. The character is not echoed to stdout. _getch bypasses the normal buffering done by getchar and getc. ungetc cannot be used with _getch. Synonym Function: getch int kbhit(); Description Checks if a keyboard key has been pressed but not yet read. Return Value Returns a non-zero value if a key was pressed. Otherwise, returns 0.

libconio http://sourceforge.net/projects/libconio

o

Implementación de Linux c ++ de conio.h http://sourceforge.net/projects/linux-conioh


En Linux (y otros sistemas unix) esto se puede hacer de la siguiente manera:

#include <unistd.h> #include <termios.h> char getch() { char buf = 0; struct termios old = {0}; if (tcgetattr(0, &old) < 0) perror("tcsetattr()"); old.c_lflag &= ~ICANON; old.c_lflag &= ~ECHO; old.c_cc[VMIN] = 1; old.c_cc[VTIME] = 0; if (tcsetattr(0, TCSANOW, &old) < 0) perror("tcsetattr ICANON"); if (read(0, &buf, 1) < 0) perror ("read()"); old.c_lflag |= ICANON; old.c_lflag |= ECHO; if (tcsetattr(0, TCSADRAIN, &old) < 0) perror ("tcsetattr ~ICANON"); return (buf); }

Básicamente, debe desactivar el modo canónico (y el modo de eco para suprimir el eco).


Encontré esto en otro foro mientras buscaba resolver el mismo problema. Lo modifiqué un poco de lo que encontré. Funciona muy bien. Estoy ejecutando OS X, así que si está ejecutando Microsoft, necesitará encontrar el comando correcto del sistema () para cambiar a los modos crudos y cocinados.

#include <iostream> #include <stdio.h> using namespace std; int main() { // Output prompt cout << "Press any key to continue..." << endl; // Set terminal to raw mode system("stty raw"); // Wait for single character char input = getchar(); // Echo input: cout << "--" << input << "--"; // Reset terminal to normal "cooked" mode system("stty cooked"); // And we''re out of here return 0; }


Eso no es posible de forma portátil en C ++ puro, ya que depende demasiado del terminal utilizado que puede estar conectado con stdin (por lo general son líneas amortiguadas). Sin embargo, puede usar una biblioteca para eso:

  1. conio disponible con compiladores de windows. Use la función _getch() para darle un carácter sin esperar la tecla Intro. No soy un desarrollador frecuente de Windows, pero he visto a mis compañeros de clase incluir simplemente conio.h y usarlo. Ver conio.h en wikipedia. Enumera getch , que se declara obsoleto en Visual C ++.
  2. las maldiciones disponibles para Linux, las implementaciones de curses compatibles también están disponibles para Windows. También tiene una función getch . (prueba man getch para ver su página de manual). Ver Curses en wikipedia.

Te recomendaría usar maldiciones si tu objetivo es la compatibilidad multiplataforma. Dicho esto, estoy seguro de que hay funciones que puedes utilizar para desactivar el almacenamiento en línea de la línea (creo que se llama "modo crudo", en lugar de "modo cocido" (mira en el man stty ). Las maldiciones manejarían eso para usted de una manera portátil si no me equivoco.


La siguiente es una solución extraída de Expert C Programming: Deep Secrets , que se supone que funciona en SVr4. Utiliza stty y ioctl .

#include <sys/filio.h> int kbhit() { int i; ioctl(0, FIONREAD, &i); return i; /* return a count of chars available to read */ } main() { int i = 0; intc=''''; system("stty raw -echo"); printf("enter ''q'' to quit /n"); for (;c!=''q'';i++) { if (kbhit()) { c=getchar(); printf("/n got %c, on iteration %d",c, i); } } system("stty cooked echo"); }


Lo más parecido a lo portable es usar la biblioteca ncurses para poner el terminal en el "modo cbreak". La API es gigantesca; las rutinas que más desearás son

  • initscr y endwin
  • cbreak y nocbreak
  • getch

¡Buena suerte!


Puede hacerlo de forma portátil usando SDL (la Biblioteca de DirectMedia Simple), aunque sospecho que puede no gustarle su comportamiento. Cuando lo probé, tuve que hacer que SDL creara una nueva ventana de video (aunque no la necesitaba para mi programa) y que esta ventana "agarrara" casi todo el teclado y el mouse (lo cual estaba bien para mi uso pero podría ser molesto o impracticable en otras situaciones). Sospecho que es excesivo y que no vale la pena a menos que sea imprescindible una portabilidad completa; de lo contrario, pruebe una de las otras soluciones sugeridas.

Por cierto, esto te dará presionar y soltar eventos por separado, si te interesa eso.


Si está en Windows, puede usar PeekConsoleInput para detectar si hay alguna entrada,

HANDLE handle = GetStdHandle(STD_INPUT_HANDLE); DWORD events; INPUT_RECORD buffer; PeekConsoleInput( handle, &buffer, 1, &events );

luego use ReadConsoleInput para "consumir" el carácter de entrada.

PeekConsoleInput(handle, &buffer, 1, &events); if(events > 0) { ReadConsoleInput(handle, &buffer, 1, &events); return buffer.Event.KeyEvent.wVirtualKeyCode; } else return 0

para ser honesto, esto es de algún código antiguo que tengo, así que tienes que jugar un poco con él.

Lo bueno es que lee la entrada sin preguntar nada, por lo que los caracteres no se muestran en absoluto.


Siempre quise un bucle para leer mi entrada sin presionar la tecla de retorno. esto funcionó para mí.

#include<stdio.h> main() { char ch; system("stty raw");//seting the terminal in raw mode while(1) { ch=getchar(); if(ch==''~''){ //terminate or come out of raw mode on "~" pressed system("stty cooked"); //while(1);//you may still run the code exit(0); //or terminate } printf("you pressed %c/n ",ch); //write rest code here } }


Uso kbhit () para ver si hay un carácter presente y luego getchar () para leer los datos. En Windows, puede usar "conio.h". En Linux, tendrás que implementar tu propio kbhit ().

Vea el código a continuación:

// kbhit #include <stdio.h> #include <sys/ioctl.h> // For FIONREAD #include <termios.h> #include <stdbool.h> int kbhit(void) { static bool initflag = false; static const int STDIN = 0; if (!initflag) { // Use termios to turn off line buffering struct termios term; tcgetattr(STDIN, &term); term.c_lflag &= ~ICANON; tcsetattr(STDIN, TCSANOW, &term); setbuf(stdin, NULL); initflag = true; } int nbbytes; ioctl(STDIN, FIONREAD, &nbbytes); // 0 is STDIN return nbbytes; } // main #include <unistd.h> int main(int argc, char** argv) { char c; //setbuf(stdout, NULL); // Optional: No buffering. //setbuf(stdin, NULL); // Optional: No buffering. printf("Press key"); while (!kbhit()) { printf("."); fflush(stdout); sleep(1); } c = getchar(); printf("/nChar received:%c/n", c); printf("Done./n"); return 0; }


funciona para mí en Windows:

#include <conio.h> char c = _getch();


#include <conio.h> if (kbhit() != 0) { cout << getch() << endl; }

Esto usa kbhit() para verificar si el teclado está siendo presionado y usa getch() para obtener el carácter que se está presionando.