Quiero agregar un ejemplo:
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{
char buf[20];
fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK);
sleep(4);
int numRead = read(0, buf, 4);
if (numRead > 0) {
printf("You said: %s", buf);
}
}
Cuando ejecuta este programa, tiene 4 segundos para proporcionar la entrada a la entrada estándar. Si no se encuentra ninguna entrada, no se bloqueará y simplemente regresará.
2 ejemplos de ejecución:
Korays-MacBook-Pro:~ koraytugay$ ./a.out
fda
You said: fda
Korays-MacBook-Pro:~ koraytugay$ ./a.out
Korays-MacBook-Pro:~ koraytugay$
Al igual que Pete Kirkham, encontré cc.byexamples.com y funcionó para mí. Vaya allí para obtener una buena explicación del problema, así como la versión de ncurses.
Mi código necesitaba tomar un comando inicial de la entrada estándar o un archivo, luego buscar un comando de cancelación mientras se procesaba el comando inicial. Mi código es C++, pero debería poder usar scanf()
y el resto donde uso la función de entrada de C++ getline()
.
La carne es una función que comprueba si hay alguna entrada disponible:
#include <unistd.h>
#include <stdio.h>
#include <sys/select.h>
// cc.byexamples.com calls this int kbhit(), to mirror the Windows console
// function of the same name. Otherwise, the code is the same.
bool inputAvailable()
{
struct timeval tv;
fd_set fds;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
return (FD_ISSET(0, &fds));
}
Esto tiene que llamarse antes de cualquier función de entrada estándar cuando usé std::cin
antes de usar esta función, nunca volvió a ser verdadero. Por ejemplo, main()
tiene un ciclo que se ve así:
int main(int argc, char* argv[])
{
std::string initialCommand;
if (argc > 1) {
// Code to get the initial command from a file
} else {
while (!inputAvailable()) {
std::cout << "Waiting for input (Ctrl-C to cancel)..." << std::endl;
sleep(1);
}
std::getline(std::cin, initialCommand);
}
// Start a thread class instance 'jobThread' to run the command
// Start a thread class instance 'inputThread' to look for further commands
return 0;
}
En el hilo de entrada, se agregaron nuevos comandos a una cola, que fue procesada periódicamente por el jobThread
. El inputThread
se parecía un poco a esto:
THREAD_RETURN inputThread()
{
while( !cancelled() ) {
if (inputAvailable()) {
std::string nextCommand;
getline(std::cin, nextCommand);
commandQueue.lock();
commandQueue.add(nextCommand);
commandQueue.unlock();
} else {
sleep(1);
}
}
return 0;
}
Esta función probablemente podría haber estado en main()
, pero estoy trabajando con un código base existente, no contra él.
Para mi sistema, no había entrada disponible hasta que se envió una nueva línea, que era justo lo que quería. Si desea leer cada carácter cuando se escribe, debe desactivar el "modo canónico" en stdin. cc.byexamples.com tiene algunas sugerencias que no he probado, pero el resto funcionó, así que debería funcionar.