Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

167
Visualizações
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 Respostas
Responde à pergunta

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda