如何在 C++ 中使用计时器在给定时间内强制输入?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28944972/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use a timer in C++ to force input within a given time?
提问by Ankita Rane
I want to implement a time out feature in C++.
我想在 C++ 中实现超时功能。
If the user does not input the value within 2 seconds then the program must display the time-out statement and ask the input again
如果用户没有在 2 秒内输入值,则程序必须显示超时语句并再次询问输入
EX(OUTPUT SCREEN):
EX(输出屏幕):
Timer=0;
Please enter the input: //if input is not given within 2 seconds then
Time-out: 2 seconds
Timer again set to 0
Please enter the input: //if input is not given within 2 seconds then
Time-out: 2 seconds
Timer again set to 0
Please enter the input:22
Data accepted
Terminate the program`
Code:
代码:
#include<iostream>
#include<time.h>
using namespace std;
int main()
{
clock_t endwait;
endwait = 2000 ;
cout<<endwait;
while (clock() < endwait)
{
cout<<"Please enter the input:";
}
return 0;
}
I have worked on the above code. But this happens only while entering the WHILE loop. How shall i do it in a way so that, I get the required output.
我已经处理了上面的代码。但这只会在进入 WHILE 循环时发生。我该如何做才能获得所需的输出。
回答by Akki
#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
回答by edmz
I am afraid, it is not possible in a standard way because I/O operations will block, by default, the calling process until it's finalized or an error is encountered.
You could work it around by creating a thread which checks whether the input has been completed and go sleeping, if needed. But that's not really practical.
恐怕以标准方式是不可能的,因为默认情况下,I/O 操作会阻塞调用进程,直到它完成或遇到错误。
您可以通过创建一个线程来解决它,该线程检查输入是否已完成并在需要时进入睡眠状态。但这并不实际。
The issue lies in the abstraction iostream
/FILE
s give you: you don't have access to the underlying source, the one the OS "understands" as well and therefore capable to give you that kind of functionality (namely, I/O polling).
问题在于抽象iostream
/ FILE
s 给您:您无法访问底层源代码,操作系统也“理解”并因此能够为您提供这种功能(即 I/O 轮询)。
回答by Ben Voigt
A separate thread is not enough, because the console read function is still running after the timeout occurs.
单独的线程是不够的,因为发生超时后控制台读取功能仍在运行。
On POSIX you could set a timer which produces a signal and causes the read to fail with -EINTR
.
在 POSIX 上,您可以设置一个计时器,该计时器会产生一个信号并导致读取失败-EINTR
。
On Windows you can implement low-level console I/O timeouts with ReadConsoleInput
and WaitForSingleObject
... but then you need to do your own line-buffering.
在 Windows 上,您可以使用ReadConsoleInput
and实现低级控制台 I/O 超时WaitForSingleObject
……但是您需要进行自己的行缓冲。
Another idea would be to use ReadFile
in OVERLAPPED
mode and wait on the completion event with a timeout, but that doesn't work for consoles, see Using overlapped IO for console input?
另一个想法是ReadFile
在OVERLAPPED
模式下使用并等待超时完成事件,但这不适用于控制台,请参阅使用重叠 IO 进行控制台输入?
Finally, new Windows versions (Vista and later) allow you to overcome the "blocking read is not cancelled by timeout" problem using CancelIoEx
. If you call that from a separate thread, it will trigger ReadFile
to return early; you won't have to implement line-buffering yourself.
最后,新的 Windows 版本(Vista 及更高版本)允许您使用CancelIoEx
. 如果你从一个单独的线程调用它,它会触发ReadFile
提前返回;您不必自己实现行缓冲。
回答by Akash
I think there is no need to use complex code (multithreading or mutex) for this purpose. See the code below :
我认为没有必要为此使用复杂的代码(多线程或互斥)。请参阅下面的代码:
#include <iostream>
#include <time.h>
#include <conio.h>
using namespace std;
int main()
{
int numInput;
clock_t start = clock();
cout << "Timer: 2 sec"<<endl;
cout << "Please enter the input: ";
while ( ! _kbhit() ) //Check for keyboard hit
{
//Check if 2 sec timer expired or not
if (((clock () - start)/ CLOCKS_PER_SEC ) >= 2)
{
cout << "\nTimeout 2 sec . . ." << endl;
cout << "Please enter the input: ";
start = clock(); //Set new timer
}
}
//Get the input here
cin >> numInput;
cout << "Data accepted: " << numInput << endl;
_getch();
return 0;
}
回答by Naman Gupta
I have used kbhit() function to solve your problem. The code is as follows:-
我已经使用 kbhit() 函数来解决您的问题。代码如下:-
#include <conio.h>
#include <iostream>
#include <windows.h>
using namespace std;
int main()
{
int i;
DWORD start_time, check_time;
start_time=GetTickCount();
check_time=start_time+2000;
while(!kbhit())
{
cout<<"Please enter the input:"<<endl;
while((check_time>GetTickCount()))
{
if (kbhit())
{
i=getch();
cout<<"Data accepted"<<endl;
return 0;
}
}
cout<<"Time-out: 2 seconds"<<endl;
cout<<"Timer again set to 0"<<endl;
start_time=GetTickCount();
check_time=start_time+2000;
}
return 0;
}