Voglio aggiungere un esempio:
#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);
}
}
Quando esegui questo programma hai 4 secondi per fornire l'input allo standard in. Se non viene trovato alcun input, non si bloccherà e tornerà semplicemente.
2 esecuzioni di esempio:
Korays-MacBook-Pro:~ koraytugay$ ./a.out
fda
You said: fda
Korays-MacBook-Pro:~ koraytugay$ ./a.out
Korays-MacBook-Pro:~ koraytugay$
Come Pete Kirkham, ho trovato cc.byexamples.com e ha funzionato per me. Vai lì per una buona spiegazione del problema, così come la versione ncurses.
Il mio codice doveva prendere un comando iniziale dall'input standard o da un file, quindi cercare un comando di annullamento mentre il comando iniziale veniva elaborato. Il mio codice è C++, ma dovresti essere in grado di usare scanf()
e il resto dove uso la funzione di input C++ getline()
.
La carne è una funzione che controlla se c'è qualche input disponibile:
#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));
}
Questo deve essere chiamato prima di qualsiasi funzione di input stdin Quando ho usato std::cin
prima di utilizzare questa funzione, non ha mai più restituito true. Ad esempio, main()
ha un ciclo simile a questo:
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;
}
Nel thread di input, nuovi comandi venivano aggiunti a una coda, che veniva periodicamente elaborata dal jobThread
. Il inputThread
assomigliava un po' a questo:
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;
}
Questa funzione probabilmente avrebbe potuto essere in main()
, ma sto lavorando con una base di codice esistente, non contro di essa.
Per il mio sistema, non era disponibile alcun input fino a quando non veniva inviata una nuova riga, che era proprio quello che volevo. Se vuoi leggere ogni carattere quando viene digitato, devi disattivare la "modalità canonica" su stdin. cc.byexamples.com ha alcuni suggerimenti che non ho provato, ma il resto ha funzionato, quindi dovrebbe funzionare.