[英]Input with a timeout in C++
我想要一个程序,用户有 10 秒的时间输入密码。 如果计时器超过 10 秒,程序会显示一条消息。 我目前的代码是这样的:
#include <iostream>
#include <ctime>
#include <string>
int main(){
std::string password;
int start_s=clock();
int stop_s=clock();
if(stop_s-start_s <= 0){
std::cout << "TIME RAN OUT!";
}
std::cout << "Enter your password! \n";
std::cout << "Password: ";
std::cin >> password;
std::cout << "\n \n";
if (password == "password123"){
std::cout << "Correct!";
} else {
std::cout << "Wrong!";
}
}
这当然不起作用......但我不知道下一步该怎么做......有什么想法吗?
如果您需要更多详细信息,请在评论中询问。
编辑:
我刚刚意识到问题是什么......它花了一个时间戳,然后又快速制作了另一个时间戳。 当发现差异时,它低于0......
但是我还是不知道接下来要做什么...
您要做的是从stdin
读取非阻塞(异步),超时为 10 秒。 这不是太难,但可能会涉及许多新概念,具体取决于您当前的水平。
这里的关键概念是cin >> password;
是一个阻塞调用,即在它完成之前,控制不会在此代码中进一步流动。 所以我们需要以某种方式使其非阻塞,或者在超时到期时保持阻塞并打破它。
根据系统的设计要求和约束,有几种常见的实现方式。 每个实现都因操作系统而异,但技术非常相似。
1. 异步:STDIN with timeout这种方式在网络编程中很常用,可以扩展到其他形式的输入,比如当前的情况。
在 Linux(以及许多其他 Unix 版本)中,可以使用FD_SET
和select
系统调用来处理监视列表。 在 Windows 中,您需要使用WaitForMultipleEvents
。
我不确定我是否可以出于这个问题的目的准确地解释这些概念。 作为参考,另一个问题有一些完全相同的代码指针是here 。
2. 同步:带中断的多线程这是一种常用技术,用于需要细粒度事件调度程序/计时器的情况。
A
和B
。A
将等待指定的超时时间。B
将等待阻塞读取A
在B
完成之前终止(超时),则A
向B
发出信号, B
决定下一步做什么(终止、重复消息等)B
读取了密码并且没问题, B
向A
发送信号并要求它死掉。 另一种实现相同目的的方法是使 OS 中断线程B
如其中一条评论中所述。
3. 同步:轮询这用于随着时间的推移我们不需要太多细粒度控制的情况。
kbhit()
)检查输入中是否有任何内容delta
(例如10ms
) 请注意,在这种情况下,根据delta
,该方法可能会消耗大量 CPU 并且可能效率低下。 例如,如果delta=10ms
如上所述,线程将每秒被唤醒 100 次,并且效率不高,尤其是当用户没有那么快地在键盘上输入字符时。
这段代码使用线程来完成。
#include <iostream>
#include <thread>
#include <chrono>
#include <string>
int main()
{
std::string password;
std::cout << "Enter your password! \n";
std::cout << "Password: ";
//try to read a passsword in 10 seconds
std::thread t1([&]() {
std::cin >> password;
});
std::this_thread::sleep_for(std::chrono::seconds(10));
t1.detach();
//check if password was entered
if (password.empty())
std::cout << "TIME IS OUT\n";
else
if (password == "password123")
std::cout << "Correct";
else
std::cout << "Worng";
return 0;
}
但是,如果您签出,您会看到即使用户及时输入了密码,它也会一直等到 10 秒结束。 所以你可以这样改进它:
#include <iostream>
#include <thread>
#include <chrono>
#include <string>
int main()
{
std::string password;
std::cout << "Enter your password! \n";
std::cout << "Password: ";
time_t start = time(NULL);
time_t waitTime = 10;
//try to read a passsword in 10 seconds
while (time(NULL) < start + waitTime && password.empty())
{
std::thread t1([&]() {
std::cin >> password;
});
std::this_thread::sleep_for(std::chrono::milliseconds(20));
t1.detach();
}
//check if password was entered
if (password.empty())
std::cout << "\nTIME IS OUT\n";
else
if (password == "password123")
std::cout << "Correct";
else
std::cout << "Worng";
return 0;
}
规范的 C++ 解决方案应如下所示:
#include <iostream>
#include <chrono>
#include <string>
int main() {
std::string password;
std::cout << "Enter your password! \n";
std::cout << "Password: ";
auto start_s = std::chrono::system_clock::now();
std::cin >> password;
auto stop_s = std::chrono::system_clock::now();
if(stop_s - start_s >= std::chrono::seconds(10)) {
std::cout << "TIME RAN OUT!";
}
else if (password == "password123") {
std::cout << "Correct!";
} else {
std::cout << "Wrong!";
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.