How to Use a Timer in C++ to Force Input Within a Given Time

How to use a timer in C++ to force input within a given time?

#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>
#include <condition_variable>
using namespace std;
condition_variable cv;

int value;

void read_value() {
cin >> value;
cv.notify_one();
}

int main()
{
cout << "Please enter the input: ";
thread th(read_value);

mutex mtx;
unique_lock<mutex> lck(mtx);
while (cv.wait_for(lck, chrono::seconds(2)) == cv_status::timeout)
{
cout << "\nTime-Out: 2 second:";
cout << "\nPlease enter the input:";
}
cout << "You entered: " << value << '\n';

th.join();

return 0;
}

Output:

Please enter the input:  
Time-Out: 2 second:
Please enter the input:
Time-Out: 2 second:
Please enter the input:22
You entered: 22

Running a timer while other commands are being executed c++

The clock continues running while a program's waiting for input, so there's no problem timing an input operation (i.e. to see how long it took). But if you want to abort the input operation when 10 seconds have lapsed, then you'd have to use platform-specific means, such as keyboard polling. All standard C++ input operations are blocking. So with only standard C++ you could attempt to put the input operation it in its own thread of execution, reasoning that asynchronous, that's what threads are for. But then you'd discover that there's no way to terminate that thread while it's waiting for input, and (getting creative) no way to post faux input to it.

Still, regarding

can you have a timer running while it's asking for input?

if you mean to have a running display of time, why, that's no problem.

You can just put that in its own thread.

However, if you want input of more than a single character per line, then you will probably have to use system-specific means, because with the standard library's facilities for text display modification (which essentially consists of the ASCII \b and \r controls) any way to do it that I can think of messes up the text cursor position each time the displayed time is changed, as exemplified below:

#include <atomic>
#include <chrono>
#include <exception> // std::terminate
#include <iostream>
#include <iomanip> // std::setw
#include <thread>
using namespace std;

auto fail( string const& s )
-> bool
{ cerr << "!" << s << "\n"; terminate(); }

auto int_from( istream& stream )
-> int
{
int x;
stream >> x || fail( "Input operation failed" );
return x;
}

namespace g {
atomic<bool> input_completed;
} // namespace g

void count_presentation( string const& prompt )
{
for( int n = 1; not g::input_completed; ++n )
{
string const count_display = to_string( n );
string const s = count_display + prompt.substr( count_display.length() );
cout << "\r" << s << flush;

using namespace std::chrono_literals;
this_thread::sleep_for( 100ms );
}
}

auto main()
-> int
{
string const prompt = string( 20, ' ' ) + "What's 6*7? ";
auto counter = thread( count_presentation, ref( prompt ) );
const int x = int_from( cin );
g::input_completed = true;
counter.join();
cout << x << "\n";
}

How do I force user to input after certain time?

I'd use a task and wait for it 5 seconds.

    static void Main(string[] args)
{
List<ConsoleKeyInfo> userInput = new List<ConsoleKeyInfo>();
var userInputTask = Task.Run(() =>
{
while (true)
userInput.Add(Console.ReadKey(true));
});

userInputTask.Wait(5000);
string userInputStr = new string(userInput.Select(p => p.KeyChar).ToArray());
Console.WriteLine("Time's up: you pressed '{0}'", userInputStr);
Console.ReadLine();
}

How to add a timer in a C++ program

If your platform has conio.h available and your compiler supports C++11 (including <chrono>) you can do it like this:

#include <iostream>
#include <chrono>
#include <conio.h>

int main(int argc, char* argv[]){
std::chrono::time_point<std::chrono::system_clock> start;
start = std::chrono::system_clock::now(); /* start timer */
while(true){
__int64 secondsElapsed = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now()-start).count();
if(secondsElapsed >= 20){ /* 20 seconds elapsed -> leave main lopp */
break;
}
if(_kbhit()){ /* keypressed */
char c = _getch(); /* get character */
std::cout << c; /* output character to stdout */
}
}
return 0;
}

After 20 seconds are passed the programm terminates - until that, you can enter characters to the console window (tested on Windows 7 with Visual Studio 2012).

See also the documentation for _kbhit(), _getch() and <chrono>.

Add a countdown timer to a math program quiz

The task is quite hard, but if you dare trying, I suggest doing it in two steps:

Implement inaccurate solution: timer expiration is checked between queries to user.

If there is some time left, next question is asked, otherwise statistics is shown. So program always waits for user input on the last question despite timer has run out. Not what exactly quizzes look like, but good move to start with.

Method: before starting quiz save current time, before each question take delta between saved time and current one and compare with time limit. Example with chrono (starting from C++11), example with oldschool clock

Add middle-question interruption

This part requires function, which will wait for user input not longer, than specified amount of time. So instead of using std::cin() you'll need to calculate amount of time left (time limit minus delta between cur time and start time) and call some sort of cin_with_timeout(time_left).

The hardest thing is implementing cin_with_timeout(), which requires solid knowledge of multithreading and thread synchronization. Great inspiration can be found here, but it is direction to start thinking rather than complete solution.

Is it possible to set timeout for std::cin?

It isn't possible to set a time out for std::cin in a portable way. Even when resorting to non-portable techniques, it isn't entirely trivial to do so: you will need to replace std::cin's stream buffer.

On a UNIX system I would replace the default stream buffer used by std::cin by a custom one which uses file descriptor 0 to read the input. To actually read the input I would use poll() to detect presence of input and set a timeout on this function. Depending on the result of poll() I would either read the available input or fail. To possibly cope with typed characters which aren't forwarded to the file descriptor, yet, it may be reasonable to also turn off the buffering done until a newline is entered.

When using multiple threads you can create a portable filtering stream buffer which uses on thread to read the actual data and another thread to use a timed condition variable waiting either for the first thread to signal that it received data or for the time out to expire. Note that you need to guard against spurious wake-ups to make sure that the timeout is indeed reached when there is no input. This would avoid having to tinker with the actual way data is read from std::cin although it still replaces the stream buffer used by std::cin to make the functionality accessible via this name.

Making a countdown timer in C++

//Please note that this is Windows specific code
#include <iostream>
#include <Windows.h>
using namespace std;

int main()
{
int counter = 60; //amount of seconds
Sleep(1000);
while (counter >= 1)
{
cout << "\rTime remaining: " << counter << flush;
Sleep(1000);
counter--;
}
}


Related Topics



Leave a reply



Submit