Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

165
Vistas
Best way to monitor for a key press without stopping a loop

I'm writing a program in C++ for Linux. I plan on using popen() to run another program. While I'm waiting for that program to finish, I want to be able to detect if the user presses keys on the keyboard so I know if they want to continue processing their files or if they want to pause after pclose(). What is the best way to accomplish this?

over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

You can use a thread waiting for a key before calling popen, call popen, cancel the thread and check if any key was pressed before calling pclose.

An example using C (it is trivial to adapt it to C++), I'm ommiting error checks for brevity:

#define _XOPEN_SOURCE

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void *handler(void *arg)
{
    int *key = arg;
    char c;

    while (read(STDIN_FILENO, &c, 1))
    {
        if (*key == 0)
        {
            *key = c;
        }
    }
    return NULL;
}

int main(void)
{
    pthread_t thread;
    int key = 0;

    pthread_create(&thread, NULL, handler, &key);

    // Simulate a long read using sleep 5
    // to give you enough time to press a key + enter
    FILE *cmd = popen("sleep 5; echo 'command finished'", "r");
    char str[1024];

    while (fgets(str, sizeof str, cmd))
    {
        printf("%s", str);
    }
    pthread_cancel(thread);
    pthread_join(thread, NULL);
    if (key != 0)
    {
        printf("%c was pressed\n", key);
    }
    pclose(cmd);
    return 0;
}

EDIT:

Someone suggested in comments to use select instead of pthreads, I don't see much advantage in using select but here we go:

select() allows to wait until a file descriptor (in this case stdin) become ready, it can be connected to a timeout that specifies the interval that select() should block waiting for the file descriptor to become ready, in this case, since we want to read what is pending on stdin as soon as popen finishes, we set the timeout to 0, at the end we need to clean stdin, otherwise we end up poluting the terminal with garbage if the user starts typing but doesn't hit enter, or types more than one digit pressing enter.

IMHO threads are a cleaner alternative in this case. Same approach using select:

#define _XOPEN_SOURCE

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <termios.h>

void clear_stdin(void)
{
    int stdin_copy = dup(STDIN_FILENO);

    tcdrain(stdin_copy);
    tcflush(stdin_copy, TCIFLUSH);
    close(stdin_copy);
}

int keypress(int state)
{
    int key = 0;

    // state 0 = timeout (nothing to get)
    if (state == 1)
    {
        char c;

        if (read(STDIN_FILENO, &c, 1))
        {
            key = c;
        }
    }
    clear_stdin();
    return key;
}

int main(void)
{
    fd_set set;

    FD_ZERO(&set);
    FD_SET(STDIN_FILENO, &set);

    FILE *cmd = popen("sleep 5; echo 'command finished'", "r");
    char str[1024];

    while (fgets(str, sizeof str, cmd))
    {
        printf("%s", str);
    }

    struct timeval timeout;

    timeout.tv_sec = 0;
    timeout.tv_usec = 0;

    int state = select(FD_SETSIZE, &set, NULL, NULL, &timeout);
    int key = keypress(state);

    if (key != 0)
    {
        printf("%c was pressed\n", key);
    }
    pclose(cmd);
    return 0;
}
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda