elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Guía rápida para descarga de herramientas gratuitas de seguridad y desinfección


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Desde que pulse una tecla, que ejecuta dicha acción
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Desde que pulse una tecla, que ejecuta dicha acción  (Leído 5,118 veces)
Meta


Desconectado Desconectado

Mensajes: 3.439



Ver Perfil WWW
Desde que pulse una tecla, que ejecuta dicha acción
« en: 2 Febrero 2023, 20:54 pm »

Buenas gente:

Aquí tengo un programa que solo se ejecuta una orden si pulso el 1 y luego Enter.

¿Hay alguna manera que pulse la tecla 1 y me ejecute una acción sin luego pulsar Enter?

El código que es este.
Código
  1. #include <iostream>
  2. #include <fstream>
  3. #include <Windows.h>    // Para mostrar texto en el título de la ventana.
  4. #include <stdio.h>      // Cambio color de fondo y letras.
  5. #include "SerialClass.h"
  6.  
  7. using namespace std;
  8. //using std::cout;
  9. //using std::cin;
  10.  
  11. // Función posición del cursor.
  12. void gotoxy(int x, int y)
  13. {
  14.    HANDLE hcon;
  15.    hcon = GetStdHandle(STD_OUTPUT_HANDLE);
  16.    COORD dwPos;
  17.    dwPos.X = x;
  18.    dwPos.Y = y;
  19.    SetConsoleCursorPosition(hcon, dwPos);
  20. }
  21.  
  22. int main()
  23. {
  24.  
  25. #pragma region "Configuración ventana."
  26.    // Mostrar caracteres correctamente en pantalla y título de la ventana.
  27.    SetConsoleOutputCP(65001);
  28.    wchar_t titulo[128];
  29.    MultiByteToWideChar(CP_UTF8, 0, "Led Arduino C++ nativo", -1, titulo, 128);
  30.    SetConsoleTitleW(titulo);
  31.  
  32.    // Tamaño de la pantalla. Se cambia en los dos últimos dígitos.
  33.    SMALL_RECT r = { 0, 0, 80, 20 }; // X = 49, Y = 9.
  34.    SetConsoleWindowInfo(GetStdHandle(STD_OUTPUT_HANDLE), TRUE, &r);
  35.  
  36.    // Cambio color de 6 (naranja claro), color letras 0 (negro).
  37.    system("color 60");
  38.  
  39.    // Ocultar cursor.
  40.    CONSOLE_CURSOR_INFO cci;
  41.    GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci);
  42.    cci.bVisible = 0; // 0 oculta. 1 muestra cursor.
  43.    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci);
  44. #pragma endregion
  45.  
  46.    // Puerto serie.
  47.    Serial* Puerto = new Serial("COM4");
  48.  
  49.    // Comandos para Arduino.
  50.    char Luz_ON[] = "Luz_ON";       // Envía "Luz_ON" al puerto serie.
  51.    char Luz_OFF[] = "Luz_OFF";
  52.    char lectura[50] = "\0";        // Guardan datos de entrada del puerto.
  53.  
  54.    int opc; // Guarda un 1 o 2 tipo entero queintroduces desde la consola.
  55.  
  56.    while (Puerto->IsConnected())
  57.    {
  58.        cout << endl;       // Retorno.
  59.        cout << "Introduzca la opcion deseada: " << endl;
  60.        cout << "Pulse 1 para encender el Led, pulse 2 para apagar." << endl << endl; // Muestra texto en pantalla.
  61.  
  62.        cin >> opc;         // Aquí introduces un número, el 1 o el 2.
  63.  
  64.        switch (opc)        // Espera recibir un 1 o un 2.
  65.        {
  66.        case 1:
  67.            // Encener luz.
  68.            cout << "Enviando: " << Luz_ON << endl;         // Muestra en pantalla textos.
  69.            Puerto->WriteData(Luz_ON, sizeof(Luz_ON) - 1);  // Envía al puerto el texto "Luz_ON".
  70.            break;
  71.  
  72.        case 2:
  73.            // Apagar luz.
  74.            cout << "Enviando: " << Luz_OFF << endl;
  75.            Puerto->WriteData(Luz_OFF, sizeof(Luz_OFF) - 1);
  76.            break;
  77.  
  78.        default: // Si haz pulsado otro número distinto del 1 y 2, muestra
  79.            cout << "Puse del 1 al 2.";                     // este mensaje.
  80.        }
  81.  
  82.  
  83.        Sleep(500);
  84.        int n = Puerto->ReadData(lectura, 49);          // Recibe datos del puerto serie.
  85.        if (n > 0)
  86.        {
  87.            lectura[n + 1] = '\0';                      // Limpia de basura la variable.
  88.            cout << "Recibido: " << lectura << endl;    // Muestra en pantalla dato recibido.
  89.            cout << "-------------------" << endl;
  90.        }
  91.  
  92.        cin.ignore(256, '\n');                          // Limpiar buffer del teclado.
  93.    }
  94. }

Saludos.


En línea

RayR

Desconectado Desconectado

Mensajes: 239


Ver Perfil
Re: Desde que pulse una tecla, que ejecuta dicha acción
« Respuesta #1 en: 2 Febrero 2023, 21:56 pm »

La forma más sencilla es usar _getch, declarada en conio.h. La aclaración pertinente (porque hay mucha información equivocada u obsoleta al respecto): aunque es sólo para Windows (lo cual claramente no es un problema en tu caso), actualmente es parte oficial de sus APIs, así que debería funcionarte con cualquier compilador para este SO sin necesidad de instalar nada extra.

También podrías implementar esta funcionalidad mediante SetConsoleMode, pero no le veo mucho caso, cuando _getch ya hace todo el trabajo sucio (internamente llama a SetConsoleMode y ReadConsoleInput).


En línea

Meta


Desconectado Desconectado

Mensajes: 3.439



Ver Perfil WWW
Re: Desde que pulse una tecla, que ejecuta dicha acción
« Respuesta #2 en: 2 Febrero 2023, 22:47 pm »

Suena jaleo, deja ver como implemento el

https://learn.microsoft.com/es-es/cpp/c-runtime-library/reference/getch-getwch?view=msvc-170

Saludos y gracias.



La forma más sencilla es usar _getch, declarada en conio.h. La aclaración pertinente (porque hay mucha información equivocada u obsoleta al respecto): aunque es sólo para Windows (lo cual claramente no es un problema en tu caso), actualmente es parte oficial de sus APIs, así que debería funcionarte con cualquier compilador para este SO sin necesidad de instalar nada extra.

También podrías implementar esta funcionalidad mediante SetConsoleMode, pero no le veo mucho caso, cuando _getch ya hace todo el trabajo sucio (internamente llama a SetConsoleMode y ReadConsoleInput).

¿Te refieres algo así?

Código
  1. #include <iostream>
  2. #include <conio.h>
  3.  
  4. using namespace std;
  5.  
  6. int main() {
  7.  
  8.  cout<<"Presione una tecla: \n";
  9.  
  10.  int tecla = _getch();
  11.  
  12.  cout << "La tecla pulsada es: "<<char(tecla)<< endl;
  13.  
  14.  return 0;
  15.  
  16. }

Por ahora he hecho este código de abajo, sin embargo, todavía hay que pulsar una tecla y luego Enter, la idea es pulsar una tecla, sea con números o letras, automáticamente me ejecute una acción, en este ejemplo, enviar un mensaje al puerto serie.

Código
  1. #include <iostream>
  2. #include <fstream>
  3. #include <conio.h>      // Controla el _getch.
  4. #include <Windows.h>    // Para mostrar texto en el título de la ventana.
  5. #include <stdio.h>      // Cambio color de fondo y letras.
  6. #include "SerialClass.h"
  7.  
  8. using namespace std;
  9. //using std::cout;
  10. //using std::cin;
  11.  
  12. // Función posición del cursor.
  13. void gotoxy(int ancho_x, int alto_y)
  14. {
  15.    HANDLE hcon;
  16.    hcon = GetStdHandle(STD_OUTPUT_HANDLE);
  17.    COORD dwPos{};
  18.    dwPos.X = ancho_x;
  19.    dwPos.Y = alto_y;
  20.    SetConsoleCursorPosition(hcon, dwPos);
  21. }
  22.  
  23. int main()
  24. {
  25.  
  26. #pragma region "Configuración ventana."
  27.    // Mostrar caracteres correctamente en pantalla y título de la ventana.
  28.    SetConsoleOutputCP(65001);
  29.    wchar_t titulo[128];
  30.    MultiByteToWideChar(CP_UTF8, 0, "Led Arduino C++ nativo", -1, titulo, 128);
  31.    SetConsoleTitleW(titulo);
  32.  
  33.    // Tamaño de la pantalla. Se cambia en los dos últimos dígitos.
  34.    SMALL_RECT r = { 0, 0, 80, 20 }; // X = 49, Y = 9.
  35.    SetConsoleWindowInfo(GetStdHandle(STD_OUTPUT_HANDLE), TRUE, &r);
  36.  
  37.    // Cambio color de 6 (naranja claro), color letras 0 (negro).
  38.    system("color 60");
  39.  
  40.    // Ocultar cursor.
  41.    CONSOLE_CURSOR_INFO cci;
  42.    GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci);
  43.    cci.bVisible = 0; // 0 oculta. 1 muestra cursor.
  44.    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci);
  45. #pragma endregion
  46.  
  47.    // Puerto serie.
  48.    Serial* Puerto = new Serial("COM4");
  49.  
  50.    // Comandos para Arduino.
  51.    char Luz_ON[] = "Luz_ON";       // Envía "Luz_ON" al puerto serie.
  52.    char Luz_OFF[] = "Luz_OFF";
  53.    char lectura[50] = "\0";        // Guardan datos de entrada del puerto.
  54.  
  55.    char tecla = _getch();          // Guarda un 1, 2 o un 3 tipo entero queintroduces desde la consola.
  56.  
  57.    while (Puerto->IsConnected())
  58.    {
  59.        cout << endl;       // Retorno.
  60.        cout << "Introduzca la opcion deseada: " << endl;
  61.        cout << "Pulse 1 para encender el Led, 2 para apagar, 3 para limpiar pantalla." << endl << endl; // Muestra texto en pantalla.
  62.  
  63.        cin >> tecla;         // Aquí introduces un número, el 1 o el 2.
  64.  
  65.        switch (tecla)        // Espera recibir un 1 o un 2.
  66.        {
  67.        case '1':
  68.            // Encener luz.
  69.            cout << "Enviando: " << Luz_ON << endl;         // Muestra en pantalla textos.
  70.            Puerto->WriteData(Luz_ON, sizeof(Luz_ON) - 1);  // Envía al puerto el texto "Luz_ON".
  71.            break;
  72.  
  73.        case '2':
  74.            // Apagar luz.
  75.            cout << "Enviando: " << Luz_OFF << endl;
  76.            Puerto->WriteData(Luz_OFF, sizeof(Luz_OFF) - 1);
  77.            break;
  78.  
  79.        case '3':
  80.            // Limpiar pantalla.
  81.            cout << "Limpiando pantalla..." << endl;
  82.            system("cls"); // Limpiar pantalla.
  83.            break;
  84.  
  85.        default: // Si haz pulsado otro número distinto del 1 y 2, muestra
  86.            cout << "Puse del 1 al 3.";                     // este mensaje.
  87.        }
  88.  
  89.        Sleep(500);
  90.        int n = Puerto->ReadData(lectura, 49);          // Recibe datos del puerto serie.
  91.        if (n > 0)
  92.        {
  93.            lectura[n + 1] = '\0';                      // Limpia de basura la variable.
  94.            cout << "Recibido: " << lectura << endl;    // Muestra en pantalla dato recibido.
  95.            cout << "-------------------" << endl;
  96.        }
  97.  
  98.        cin.ignore(256, '\n');                          // Limpiar buffer del teclado.
  99.    }
  100.  
  101.    return 0;
  102. }

Saludos.
« Última modificación: 4 Febrero 2023, 12:44 pm por Eternal Idol » En línea

4v1dy4

Desconectado Desconectado

Mensajes: 137



Ver Perfil
Re: Desde que pulse una tecla, que ejecuta dicha acción
« Respuesta #3 en: 12 Febrero 2023, 15:03 pm »

Hola,

Como dijo RayR, puedes utilizar _getch o getche.

Antes de querer implementar algo de otra forma, tienes que saber para que sirve ese algo en primer lugar.

Tienes que presionar [ENTER] cuando llamas a la funcion getchar() (o el equivalente en C++, cin) para determinar CUANDO acaba la cadena de caracteres, porque se supone de antemano que la cadena, por logica, empieza en cuanto presionas una tecla.

puntos clave:

La cadena empieza cuando presionas una tecla.
La cadena termina cuando presionas [ENTER].

La funcion _getch, lo que hace es leer el estado del teclado actual. Es decir, no ESPERA, sino que LEE, el estado actual.

Es como si le hiciera un snapshot a todas las teclas.

En fin, el punto es que _getch es inutil si no determinas CUANDO has presionado una tecla.

Porque de nada sirve que ejecutes el programa e inmediatamente llames a _getch, porque probablemente no estaras presionando nada (O si. El problema es que no lo sabes).

Entonces, ¿Como llamar a _getch?

Haciendo uso de la funcion kbhit()

kbhit retorna 1 cuando alguna tecla del teclado esta siendo presionada actualmente, y retorna 0 cuando ninguna tecla del teclado esta siendo presionada actualmente.

Es decir, para esperar a que una tecla sea presionada, haces:

Código
  1. while(!kbhit());

El ciclo va a terminar inmediatamente cuando se presione una tecla. Es entonces cuando llamas a _getch para que rapidamente tome un snapshot del teclado, y retorne la tecla que esta siendo presionada actualmente:

Código
  1. while(!kbhit());
  2. key=_getch();

Puedes probar el funcionamiento con este codigo:

Código
  1. #include <stdio.h>
  2. #include <conio.h>
  3.  
  4. int main()
  5. {
  6. int key;
  7.  
  8. printf("> ");
  9. while(!kbhit());
  10. key=_getch();
  11.  
  12. printf("%c \n",
  13. key);
  14.  
  15. return 0;
  16. }

IMPORTANTE: Te recomiendo que juegues con ese ultimo codigo. Quita el while(...); para que veas lo que sucede.

PD: Vi que esto lo estas implementando el Windows. Para que sepas, no se si te importa la portabilidad pero en Linux, ademas de que no se si funcione, seria mejor implementarlo con la libreria ncurses.

Un saludo.
En línea

RayR

Desconectado Desconectado

Mensajes: 239


Ver Perfil
Re: Desde que pulse una tecla, que ejecuta dicha acción
« Respuesta #4 en: 12 Febrero 2023, 17:30 pm »

No había visto que escribiste algo más.

El problema es que pones el _getch fuera del while. Lo que debes hacer es cambiar esto:

Código
  1. cin >> tecla;

por:
 
Código
  1. tecla = _getch();

La funcion _getch, lo que hace es leer el estado del teclado actual. Es decir, no ESPERA, sino que LEE, el estado actual.

No, no es así. La que hace eso es GetKeyboardState. _getch espera hasta que haya algo en su buffer (que es distinto del de stdin), y luego lo lee y devuelve el valor.
En línea

4v1dy4

Desconectado Desconectado

Mensajes: 137



Ver Perfil
Re: Desde que pulse una tecla, que ejecuta dicha acción
« Respuesta #5 en: 12 Febrero 2023, 23:49 pm »

Citar
La que hace eso es GetKeyboardState

Claro que no. ¿Por que mientes?



Es broma. Tienes razon XD
No se por que me confundi si los nombres no se parecen en nada. Creo que estoy desarrollando Alzheimer xddd se vienen posts mios a lo win_7. En fin. Gracias por la correccion.
En línea

Meta


Desconectado Desconectado

Mensajes: 3.439



Ver Perfil WWW
Re: Desde que pulse una tecla, que ejecuta dicha acción
« Respuesta #6 en: 13 Febrero 2023, 22:50 pm »

Ya me funciona.

Código
  1. // system("cls"); // Limpiar pantalla.
  2.  
  3. #include <iostream>
  4. #include <fstream>
  5. #include <conio.h>      // Controla el _getch.
  6. #include <Windows.h>    // Para mostrar texto en el título de la ventana.
  7. #include <stdio.h>      // Cambio color de fondo y letras.
  8. #include "SerialClass.h"
  9.  
  10. using namespace std;
  11. //using std::cout;
  12. //using std::cin;
  13.  
  14. // Función posición del cursor.
  15. void gotoxy(int ancho_x, int alto_y)
  16. {
  17.    HANDLE hcon;
  18.    hcon = GetStdHandle(STD_OUTPUT_HANDLE);
  19.    COORD dwPos{};
  20.    dwPos.X = ancho_x;
  21.    dwPos.Y = alto_y;
  22.    SetConsoleCursorPosition(hcon, dwPos);
  23. }
  24.  
  25. int main()
  26. {
  27.  
  28. #pragma region "Configuración ventana."
  29.    // Mostrar caracteres correctamente en pantalla y título de la ventana.
  30.    SetConsoleOutputCP(65001);
  31.    wchar_t titulo[128];
  32.    MultiByteToWideChar(CP_UTF8, 0, "Led Arduino C++ nativo", -1, titulo, 128);
  33.    SetConsoleTitleW(titulo);
  34.  
  35.    // Tamaño de la pantalla. Se cambia en los dos últimos dígitos.
  36.    SMALL_RECT r = { 0, 0, 80, 20 }; // X = 49, Y = 9.
  37.    SetConsoleWindowInfo(GetStdHandle(STD_OUTPUT_HANDLE), TRUE, &r);
  38.  
  39.    // Cambio color de 6 (naranja claro), color letras 0 (negro).
  40.    system("color 60");
  41.  
  42.    // Ocultar cursor.
  43.    CONSOLE_CURSOR_INFO cci;
  44.    GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci);
  45.    cci.bVisible = 0; // 0 oculta. 1 muestra cursor.
  46.    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci);
  47. #pragma endregion
  48.  
  49.  
  50.  
  51.    // Comandos para Arduino.
  52.    char Luz_ON[] = "Luz_ON";       // Envía "Luz_ON" al puerto serie.
  53.    char Luz_OFF[] = "Luz_OFF";
  54.    char limpiar7[] = "       ";    // Siete espacios en blanco para limpiar un área seleccionado.
  55.    char lectura[50] = "\0";        // Guardan datos de entrada del puerto.
  56.    char tecla;                     // Guarda un 1, 2 o un 3 tipo entero queintroduces desde la consola.
  57.  
  58.    // Puerto serie.
  59.    Serial* Puerto = new Serial("COM5");
  60.  
  61.    gotoxy(0, 0);                   // Posición de la pantalla.
  62.    cout << endl;                   // Retorno.
  63.    cout << "Introduzca la opcion deseada: " << endl;
  64.    cout << "Pulse 1 para encender el Led, 2 para apagar, 3 para limpiar pantalla." << endl << endl;
  65.  
  66.    while (Puerto->IsConnected())
  67.    {
  68.        tecla = _getch();     // Aquí introduces un número, el 1 o el 2.
  69.  
  70.        switch (tecla)        // Espera recibir un 1 o un 2.
  71.        {
  72.        case '1':
  73.            // Encener luz.
  74.            gotoxy(10, 5);
  75.            cout << limpiar7;
  76.            gotoxy(0, 5);
  77.            cout << "Enviando: " << Luz_ON << endl;         // Muestra en pantalla textos.
  78.            Puerto->WriteData(Luz_ON, sizeof(Luz_ON) - 1);  // Envía al puerto el texto "Luz_ON".
  79.            gotoxy(0, 9);
  80.            cout << "                             ";        // Borrado del mensaje si haz pulsado distinto del 1 o la tecla 2.
  81.            break;
  82.  
  83.        case '2':
  84.            // Apagar luz.
  85.            gotoxy(10, 5);
  86.            cout << limpiar7;
  87.            gotoxy(0, 5);
  88.            cout << "Enviando: " << Luz_OFF << endl;
  89.            Puerto->WriteData(Luz_OFF, sizeof(Luz_OFF) - 1);
  90.            gotoxy(0, 9);
  91.            cout << "                             ";
  92.            break;
  93.  
  94.        default: // Si haz pulsado otro número distinto del 1 y 2, muestra
  95.            gotoxy(0, 9);
  96.            cout << "Pulse las teclas el 1 o el 2.";                     // este mensaje.
  97.        }
  98.  
  99.        Sleep(500);
  100.        int numeros = Puerto->ReadData(lectura, 49);          // Recibe datos del puerto serie.
  101.        if (numeros > 0)
  102.        {
  103.            lectura[numeros + 1] = '\0';                      // Limpia de basura la variable.
  104.            gotoxy(0, 7);
  105.            cout << "Recibido: " << lectura << endl;    // Muestra en pantalla dato recibido.
  106.            cout << "-----------------------------" << endl;
  107.        }
  108.    }
  109.    return 0;
  110. }

Gracias a todos mi muy distinguidos amigos. :)
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines