Je veux ajouter un exemple :
#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);
}
}
Lorsque vous exécutez ce programme, vous avez 4 secondes pour fournir une entrée à l'entrée standard. Si aucune entrée n'est trouvée, il ne se bloquera pas et reviendra simplement.
2 exemples d'exécution :
Korays-MacBook-Pro:~ koraytugay$ ./a.out
fda
You said: fda
Korays-MacBook-Pro:~ koraytugay$ ./a.out
Korays-MacBook-Pro:~ koraytugay$
Comme Pete Kirkham, j'ai trouvé cc.byexamples.com, et cela a fonctionné pour moi. Allez-y pour une bonne explication du problème, ainsi que la version ncurses.
Mon code devait prendre une commande initiale à partir de l'entrée standard ou d'un fichier, puis surveiller une commande d'annulation pendant le traitement de la commande initiale. Mon code est C++, mais vous devriez pouvoir utiliser scanf()
et le reste où j'utilise la fonction d'entrée C++ getline()
.
La viande est une fonction qui vérifie s'il y a une entrée 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));
}
Cela doit être appelé avant toute fonction d'entrée stdin Lorsque j'ai utilisé std::cin
avant d'utiliser cette fonction, elle ne retournait plus jamais true. Par exemple, main()
a une boucle qui ressemble à ceci :
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;
}
Dans le thread d'entrée, de nouvelles commandes étaient ajoutées à une file d'attente, qui était périodiquement traitée par le jobThread
. Le inputThread
ressemblait un peu à ceci :
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;
}
Cette fonction aurait probablement pu être en main()
, mais je travaille avec une base de code existante, pas contre elle.
Pour mon système, il n'y avait pas d'entrée disponible jusqu'à ce qu'une nouvelle ligne soit envoyée, ce qui était exactement ce que je voulais. Si vous souhaitez lire chaque caractère lors de la saisie, vous devez désactiver le "mode canonique" sur stdin. cc.byexamples.com a quelques suggestions que je n'ai pas essayées, mais le reste a fonctionné, donc ça devrait marcher.