我想有一个程序,用户有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以下。。
但我还是不知道下一步该怎么办...
4条答案
按热度按时间inn6fuwd1#
这段代码使用了线程。
字符串
但是如果你检查一下,你可以看到它会等到10秒结束,即使用户及时输入了密码。你可以这样改进它:
型
jchrr9hc2#
我最近遇到了同样的问题。我从@user1952500找到了答案,提出了有趣的方法。其中,第二个对我来说更容易理解。
但是,我还没有找到好的代码解决方案。更一般地说,使用detach不会杀死线程,但它允许独立运行(“在主线程之外”)。这意味着线程将永远运行,直到整个代码终止,如果我们分离多个线程,这将是更糟糕的情况。
要使用线程正确地实现超时的键盘输入,必须从另一个线程中杀死该线程。问题是:只使用C++标准库是不可能的。
必须使用依赖于平台的函数。这是我的Linux解决方案:
字符串
对于不同的平台,您需要调用不同的函数,而不是
pthread_cancel(t_handle)
。例如,在Windows上,您可以使用TerminateThread。
nuypyhwy3#
一个规范的C++解决方案应该是这样的:
字符串
u5i3ibmn4#
您要做的是从
stdin
进行一次非阻塞(异步)读取,超时时间为10秒。这不是太坚韧,但可能涉及到许多新的概念,这取决于你目前的水平。这里的关键概念是
cin >> password;
是一个 * 阻塞 * 调用,也就是说,在它完成之前,控制不会在此代码中进一步流动。所以我们需要以某种方式使它非阻塞,或者保持它阻塞,并在超时到期时打破它。根据系统的设计要求和约束,有几种常见的实现方式。每种实现方式都因操作系统而异,但技术非常相似。
1.异步:带超时的STDIN这种方法通常用于网络编程,可以扩展到其他形式的输入,例如当前情况。
1.将标准输入(STDIN)句柄(handle = 0)放入“监视列表”。
1.在监视列表中设置超时。
1.无论何时STDIN发生变化,都应进行处理。
1.当超时过期时,检查我们处理的内容是否完成了工作。
在Linux(以及许多其他Unix版本)中,可以使用
FD_SET
和select
系统调用来处理监视列表。在Windows中,您需要使用WaitForMultipleEvents
。我不确定我是否能为这个问题的目的准确地解释这些概念。作为参考,另一个有一些代码指针的问题是here。
2.同步:带中断的多线程这是一种常见的技术,用于需要细粒度事件调度程序/定时器的情况。
1.创建两个线程
A
和B
。A
将等待指示的超时。B
将等待阻塞读取1.如果
A
在B
完成之前终止(超时),则A
向B
发送信号,B
决定下一步要做什么(终止、重复消息等)1.如果
B
读取了密码并且它正常,则B
向A
发送信号并要求它死亡。另一种实现相同的方法是使OS中断线程
B
如comments之一中所述。3.同步:轮询这是用于我们不需要太多细粒度控制的情况。
1.使用非阻塞读取(
kbhit()
)检查输入中是否有任何内容1.如果没有,并且超时还有剩余时间,则等待更短的时间
delta
(例如10ms
)1.如果超时已经过期并且没有剩余时间,则执行任何需要的处理(通知用户、退出等)
注意,在这种情况下,根据
delta
,该方法可能会消耗大量CPU,并且可能效率低下。例如,如果delta=10ms
如上所述,线程将每秒被唤醒100次,这将是低效的,特别是当用户在键盘上输入字符不那么快时。