I am trying to do an implementation of htop (system monotitoring) in c++.
So I am using ncurses to refresh my terminal.
I need to get new info every 5 seconds for example, im using a loop to do so.
while (42)
{
key = std::cin.get();
std::cout << key;
this->gereEvent(key);
std::cout << i<< std::endl;
if (i == 500000000)
{
std::cout << "test"<< std::endl;
// fputs(tgetstr((char *)"cl", 0), stdout);
this->refresh();
i = 0;
}
i++;
}
But problem is cin.get() stops the loop..
I cannot do a thread eitheir because std::thread needs c++11.
Have you an idea of how I can do that ?
You need to poll the keyboard events. This can be done in ncurses with getch.
#include<stdio.h>
#include<curses.h>
#include<unistd.h>
int main ()
{
int i=0;
initscr(); //in ncurses
timeout(0);
while(!i)
{
usleep(1);
i=getch();
printw("%d ",i);
if(i>0)
i=1;
else
i=0;
}
endwin();
printf("\nhitkb end\n");
return 0;
}
This example is from http://cc.byexamples.com/2007/04/08/non-blocking-user-input-in-loop-without-ncurses/comment-page-1/#comment-2100.
Related
i have an infinite loop that should be ended if i pressed any key. The program runs in linux. I have stumbled upon a function Here is a bit of my code :
int main(){
While(1){
ParseData(); //writing data to a text file
}
return 0;
}
so i know that i can terminate the process by using ctrl + c in terminal, but it seems that it will interrupt the writing process so the datas are not written completely halfway through the process. I read that i need to use function from ncurses library , but i can't quite understand any.
Can someone help me with it? Thanks!
You can declare an atomic_bool and move your main loop to another thread. Now you can wait with a simple cin, once the user presses any key you exit your loop.
std::atomic_boolean stop = false;
void loop() {
while(!stop)
{
ParseData(); // your loop body here
}
}
int main() {
std::thread t(loop); // Separate thread for loop.
// Wait for input character (this will suspend the main thread, but the loop
// thread will keep running).
std::cin.get();
// Set the atomic boolean to true. The loop thread will exit from
// loop and terminate.
stop = true;
t.join();
return 0;
}
Why do you need a key to exit a program that didn't finish writing to a file, even if you make the loop exits on key press it will interrupt the file writing too if not finished.
Why you just exit the loop when the data finishes writing to the file, like the following:
isFinished = false;
While(!isFinished ){
ParseData(); //writing data to a text file
//after data finsihes
isFinished = false;
}
thread.cpp
#include <atomic>
#include <iostream>
#include <thread>
std::atomic<bool> dataReady(false);
void waitingForWork(){
std::cout << "Waiting... " << std::endl;
while ( !dataReady.load() ){
std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
std::cout << "Work done " << std::endl;
}
int main(){
std::cout << std::endl;
std::thread t1(waitingForWork);
std::cout << "Press Enter to Exit" << std::endl;
std::cin.get();
dataReady= true;
t1.join();
std::cout << "\n\n";
}
g++ -o thread thread.cpp -std=c++11 -pthread
The C way actually (include conio.h ):
char key;
while (1)
{
key = _getch();
// P to exit
if (key == 'p' || key == 'P')
{
writer.close();
exit(1);
}
}
I am trying to create a function that will be done many times over and over but with a pause in between each cycle.
I have tried to use "sleep" but that pauses the console. And I have searched online and only found answers that paused the console during usual.
Code:
int i;
for(i=0; i<500; i++) {
std::cout << "Hello" << std::endl;
}
How can I make it print "Hello" 500 times and as well allow the user to use the console while it is doing the said function?
As some people commented, you need to create an async task in order to do some work while still handling user input.
The following is a minimal, working example about how to acomplish this task by using a thread. It is based on boost so you'll have to link it using -lboost_thread lboost_system:
g++ test.cpp -lboost_thread -lboost_system -o test
The code has several comments in order to explain what you should do:
#include <queue>
#include <iostream>
#include <boost/thread.hpp>
// set by the main thread when the user enters 'quit'
bool stop = false;
boost::mutex stopMutex; // protect the flag!
// the function that runs in a new thread
void thread_function() {
// the following is based on the snippet you wrote
int i;
for(i=0; i<500; i++) {
// test if I have to stop on each loop
{
boost::mutex::scoped_lock lock(stopMutex);
if (stop) {
break;
}
}
// your task
std::cout << "Hello" << std::endl;
// sleep a little
::usleep(1000000);
}
}
int main() {
std::string str;
boost::thread t(thread_function);
while(true) {
std::cout << "Type 'quit' to exit: ";
// will read user input
std::getline(std::cin, str);
if (str == "quit") {
// the user wants to quit the program, set the flag
boost::mutex::scoped_lock lock(stopMutex);
stop = true;
break;
}
}
// wait for the async task to finish
t.join();
return 0;
}
I'm a bit new to C++, so I beg your pardon for being a bit nooby.
Is there a function I can use to make the console pause until a specific key is pressed?
Example being:
#include <iostream>
using namespace std;
int main()
{
int i = 0;
if (specific key pressed) {
i = 1;
} else if (other key pressed) {
i = 2;
}
cout << i << endl;
return 0;
}
The console should output 1 if the right key is pressed, and 2 if another key is.
What you're trying to do is a bit more complex, C++ makes use of the cin stream where the input into the console is fed into your program. Where as a key-press event would be something the operating system would handle and would vary between operating systems. So using something like this would require the user to press enter/return for the input to be received by the program.
char key;
std::cin >> key;
if (key == 'a') {
std::cout << 1;
}
else {
std::cout << 2;
}
Find some answers here How to handle key press events in c++
Works on Windows only:
#include <iostream>
#include <vector>
#include <Windows.h>
char GetKey(std::vector<char> KeysToCheckFor)
{
while (true)
{
Sleep(1);
for (int i = 0; i < KeysToCheckFor.size(); i++)
{
if (GetKeyState(toupper(KeysToCheckFor[i])) < 0) { return KeysToCheckFor[i]; }
}
}
}
int main()
{
std::cout << "Press one of the keys: a,b,c\n";
char returnedkey = GetKey({ 'a', 'b', 'c' });
std::cout << returnedkey << " has been pressed!\n";
system("pause");
}
I need to have a while-loop running and accept input to it whenever there is an input. I'm not new to C++, but this hurdle is quite difficult. Due to an NDA (this school project is apparently some secret stuff) I can only show you the test case.
I've been grasping for straws trying to solve the problem; try catch, cin.get, cin.peek, if(cin.peek){}. If anybody can point me in the right direction I would be very grateful!
The program is not time-critical, but a function needs to be called with a fixed interval. It is not essential that the code is portable, that it is a while-cin-combination or anything like that; the code will only ever run on a Windows 7 or Windows 8 PC with at least dual core processor.
#include <iostream>
#include <ctime>
using namespace std;
int main()
{
int input = 0;
int pastTime, nowTime;
pastTime = nowTime = time(0);
cin >> input;
while(input != -1)
{
if(input == 1)
{
cout << "Entered 1" << endl;
//To be done instead of the two 'elses',
//bypassing interval-dependant code
}
else if(input == 2)
{
cout << "Entered 2" << endl;
//To be done instead of the interval-dependant code
}
else if(pastTime == (nowTime - 5))
{
cout << "Nothing entered." << endl;
//Needs to be done with a fixed interval.
}
nowTime = time(0);
cin >> input;
}
return 0;
}
The solution was, based om James Beilby's link:
// This program is based on counter.cpp from Boost\lib\thread\tutorial
#include <boost/thread/thread.hpp>
#include <iostream>
#include <ctime>
int timeNow = time(0);
int timePast = time(0);
void fct_one()
{
while(1) //keeps running all the time
{
if(timePast == (timeNow - 3)) // only executed once every three seconds
{
//do some stuff
timePast = time(0);
}
timeNow = time(0); // time is continuously updated
}
}
void fct_two()
{
int input = 0;
int timeTemp = time(0);
while(1) //keeps running all the time
{
std::cin >> input; // cin blocking for input
if(input == 1)
{
//do some stuff
}
if(input == 2)
{
//do some stuff
}
if(input == -1)
{
std::cout << "Program is done. ";
system("pause");
exit(1);
}
}
}
int main()
{
boost::thread_group threads;
threads.create_thread(&fct_one)
threads.create_thread(&fct_two);
threads.join_all();
return 0;
}
I would completely separate reading input from cin and performing the default timeout function. You'll need something like a background thread that performs the default function based on the time interval. To handle the 1st two cases you'll need to signal the thread skipping the next execution (if this is really necessary), and just call any function you want or do nothing.
The simple answer is to put the code that runs at some interval on another thread. Since you've noted this is Windows, you could use a Timer Queue:
Begin with routines to start and stop your time dependent work:
HANDLE Start(HANDLE hTimerQueue)
{
DWORD timerMS = 5000; /* every 5 seconds */
HANDLE hTimer;
if (!CreateTimerQueueTimer(&hTimer,
hTimerQueue,
(WAITORTIMERCALLBACK)timerWork,
/*lpParam*/NULL,
/*start in ___ ms:*/0,
/*run every __ ms:*/timerMS,
/*flags*/0))
{
return NULL;
}
return hTimer;
}
BOOLEAN Stop(HANDLE hTimerQueue, HANDLE hTimer)
{
if (!DeleteTimerQueueTimer(hTimerQueue,
hTimer,
/*wait for our timer to complete*/INVALID_HANDLE_VALUE))
{
return FALSE;
}
return TRUE;
}
Then put your time dependent work into its own callback:
VOID CALLBACK timerWork(PVOID lpParam, BOOLEAN TimerOrWaitFired /*ignored*/)
{
for (int ii = 0; ii < 10; ++ii) {
std::cout << "timer work: " << ii << std::endl;
Sleep(250);
}
}
Finally, integrate these into your workflow:
int main(int argc, char* argv[])
{
HANDLE hTimerQueue = CreateTimerQueue(hTimerQueue);
if (NULL == hTimerQueue) return -1;
HANDLE hTimer = Start(hTimerQueue);
if (NULL == hTimer) return -1;
/* our timed callback is now running in the background */
int input = 0;
std::cin >> input;
while(input != -1)
{
if(input == 1)
{
if (Stop(hTimerQueue, hTimer)) {
std::cout << "Entered 1" << std::endl;
if (NULL == (hTimer = Start(hTimerQueue))) return -2;
}
}
else if(input == 2)
{
if (Stop(hTimerQueue, hTimer)) {
std::cout << "Entered 2" << std::endl;
if (NULL == (hTimer = Start(hTimerQueue))) return -2;
}
}
std::cin >> input;
}
DeleteTimerQueue(hTimerQueue);
return 0;
}
How would I effectively cancel a call for user input if there is no input within a certain time? (I'm programming a game for a terminal/cmd window with Mac OS X).
I have tried turning off canonical buffering and using a timer thread that joins after the call for user input. I also tried implementing the call to pthread_join() within the parameters of the while loop. Still nothing. The problem is that even though canonical buffering is off, the call for user input is still held up when there is no input. It works fine if there is input though.
It would be great if I could do this without fiddling around with downloading and installing ncurses, but I'll do it if I have to.
Edit: Source code:
//Most headers only pertain to my main program.
#include <iostream>
#include <termios.h>
#include <pthread.h>
#include <time.h>
#include <cstring>
#include <stdio.h>
#include <string.h>
using namespace std;
//Timer function.
void *Timer(void*) {
time_t time1, time2;
time1 = time(NULL);
while (time2 - time1 < 1) {
time2 = time(NULL);
}
pthread_exit(NULL);
}
int main() {
//Remove canonical buffering.
struct termios t_old, t_new;
tcgetattr(STDIN_FILENO, &t_old);
t_new = t_old;
t_new.c_lflag &= ~ICANON;
tcsetattr(STDIN_FILENO, TCSANOW, &t_new);
cout << "Press any key to continue." << endl;
string szInput;
int control = 0;
do {
pthread_t inputTimer;
pthread_create(&inputTimer, NULL, Timer, NULL);
szInput = "";
while (szInput == "") {
szInput = cin.get();
//Handle keypresses instantly.
if (szInput == "a") {
cout << endl << "Instant keypress." << endl;
}
}
pthread_join(inputTimer, NULL);
cout << endl << "One second interval." << endl;
control ++;
} while (control < 25);
cout << "Game Over." << endl;
return 0;
}
See if this works!
char ch; //Input character
int time = 0; //Time iterator
int TIMER = 5000; //5 seconds
while(time<TIMER)
{
if(!kbhit())
{
time = 0;
ch = getch();
//Do your processing on keypress
}
time++;
delay(1);
}
kbhit() detects if any keystroke has occurred. If yes, then get the key character in ch.
One way of checking if there is input is to poll the file descriptor STDIN_FILENO using e.g. the select system call. If STDIN_FILENO is readable, then you can read at at least one character. You can also pass a timeout to the select call.
Thanks Shashwat, it works with the below modifications:
1) Changing if(!kbhit()) to if(kbhit())
2) Changing delay(1); to Sleep(1);
I do not have enough rep to post a comment, hence adding as an answer.