I have a console application that prints on standard output. I want to implement the following behaviour:
- Output is printed in a turns (2 seconds break after every turn)
- User may (it’s optional for him) press a key to start printing other data
- When user don’t click anything, output is just printed, nothing changes
- When user clicks a predefined key (he may be able to do that even during output is being printed) some function should be called
At first I thought about doing it in other thread (one thread for printing, one for waiting for input), but I suppose it’s useless in this case, because it’s impossible to wait for an input in a thread.
So I found two libraries that might be able to do that:
- Simple and Fast Multimedia Library (SFML): http://www.sfml-dev.org/index.php
- ncurses: http://www.gnu.org/software/ncurses/ncurses.html
I don’t know either of them, so I am not sure which one I should learn to obtain a goal. Or maybe there is another, simpler solution?
OS: Unix
EDIT: g-makulik asked me to show, why it wasn’t possible to write using threads insisting, that it is possible and indeed, it is, but I don’t think this is how it should look like:
#include <pthread.h>
#include <iostream>
#include <string>
#include <stdio.h>
void* print_message_function(void *doPrint) {
bool* vDoPrint = (bool*) doPrint;
while (*vDoPrint) {
sleep(0.5);
std::cout << "Thread 1" << std::endl;
}
return NULL;
}
void* keyPressed(void* doPrint) {
bool* vDoPrint = (bool*) doPrint;
while (*vDoPrint) {
*vDoPrint = (char) getchar() == 'k' ? false : true;
std::cout << "THIS ISN'T DISPLAYED UNLESS 'k' PRESSED.";
}
return NULL;
}
int main(int argc, char* argv[]) {
pthread_t thread1, thread2;
int iret1, iret2;
bool doPrint = true;
iret2 = pthread_create(&thread2, NULL, print_message_function,
(void*) &doPrint);
iret1 = pthread_create(&thread1, NULL, keyPressed,
(void*) &doPrint);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
std::cout << "Thread 1 returns: " << iret1 << std::endl;
std::cout << "Thread 2 returns: " << iret2 << std::endl;
return 0;
}
I’ve used ncurses before and while the following solution may not be the prettiest, it should work.
Ncurses allows you to put input into ‘no-delay’ mode. This makes
getch(), which reads a character from input, non-blocking and it will immediately return ERR if user has not pressed anything.You can wait for the standard input file descriptor to see if the input file descriptor is ready for reading. That is,
select()orepoll()or whatever you want. If you have to do something every 2 seconds, you can just put that time toselect()orepoll(). If you do get a keypress, you can then decide whatever you want to do with it.This solution needs no multithreading.
I have no knowledge of SFML so I don’t know if it would make this any easier. Ncurses is a C-library which may or may not be convenient for a C++ application. If you have man pages installed, you probably can see documentation on any ncurses function directly (for example,
man getch).