用C ++输入超时 [英] Input with a timeout in C++

查看:159
本文介绍了用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<< 时间到了!;
}
std :: cout<< 输入您的密码!\n;
std :: cout<< 密码:;
std :: cin>>密码;
std :: cout<< \n \n;

if(password == password123){

std :: cout<< 正确!;
}否则{
std :: cout<< 错误!;
}

}

这当然是行不通的。 ..但是我不确定下一步该怎么做...有什么想法吗?



如果您需要更多详细信息,请在评论中提问。



编辑:



我刚刚意识到问题出在哪里……花了一个时间标记然后迅速做了另一个时间戳。当发现差异时,它低于0 ...



但是我仍然不知道下一步该怎么做...

解决方案

您要尝试的是从 stdin 中读取非阻塞(异步)数据超时为10秒。

这里的关键概念是 cin>>。密码; 是一个 blocking 调用,即直到完成,该代码中的控制权才会进一步流动。因此,我们需要以某种方式使其变为非阻塞状态,或者使其保持阻塞状态,并在超时到期时中断它。



有一些常见的实现基于系统的设计要求和约束。每个实现因操作系统而异,但技术非常相似。



1。异步:带有超时的STDIN
这种方法通常在网络编程中使用,并且可以扩展到其他形式的输入,例如当前案例。


  1. 将标准输入(STDIN)句柄(句柄= 0)放入监视列表。

  2. 在观察列表上放置超时。 / li>
  3. 只要STDIN发生更改,就对其进行处理。

  4. 超时到期后,请检查我们处理的内容是否能完成工作。 / li>

在Linux(以及许多其他Unix版本)中,监视列表可以使用 FD_SET select 系统调用。在Windows中,您将需要使用 WaitForMultipleEvents



对于这个问题,我不确定我是否可以公正地准确解释这些概念。作为参考,在此处,其中有一些代码指针可以完全相同。 a>。



2。同步:带中断的多线程
这是在需要精细的事件计划程序/计时器的情况下常用的技术。


  1. 创建两个线程,分别为 A B

  2. A 将在指示的超时时间内等待。

  3. B 将等待阻塞读取

  4. 如果 A B 完成之前终止(超时) , A 表示 B B 表示下一步该做什么(终止,重复一条消息,等等)

  5. 如果 B 读取密码并且没问题,则 B 表示 A 并要求其死亡。

另一个实现相同目的的方法是使操作系统中断线程 B



3。同步:轮询
这用于我们在一段时间内不需要太多细粒度控制的情况。


  1. 使用非阻塞读取( kbhit()

  2. 检查输入中是否有内容没有,并且如果超时中还有剩余时间,请等待更短的时间 delta (例如 10ms

  3. 如果超时时间已到,并且没有剩余时间了,请执行所需的任何处理(向用户发送消息,退出等)

请注意,在这种情况下,根据 delta ,此方法可能会消耗大量CPU,并且效率可能很低。例如,如果上述 delta = 10ms ,则线程将每秒被唤醒100次,并且效率不高,尤其是当用户未在键盘上键入字符时这么快。


I want to have a program where the user have 10 seconds to enter the password. If the timer goes over 10 seconds, the program displays a message. My current code is this:

 #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!";
}

}

This of course is not working... But I am not sure what to do next... Any ideas?

If you need more details, ask in the comments.

EDIT:

I just realized what the problem was... It took a time stamp and then quickly made another time stamp. And when the difference was found, it was below 0...

But I still don't know what to do next...

解决方案

What you are trying to do is to have an non-blocking (asynchronous) read from stdin with a timeout of 10 seconds. This is not too tough but may involve many new concepts depending on your current level.

The key concept here is that cin >> password; is a blocking call, i.e., until it is completed, control will not flow further in this code. So we need to make it non-blocking in some way, or keep it blocking and break out of it when the timeout expires.

There are a few common implementations based on the design requirements and constraints of the system. Each implementation is different depending on the OS but the techniques are very similar.

1. Asynchronous: STDIN with timeout This approach is commonly used in network programming and can be extended to other forms of input such as the current case.

  1. Place the standard input (STDIN) handle (handle = 0) into a 'watch-list'.
  2. Place a timeout on the watch-list.
  3. Whenever there is a change in the STDIN, process it.
  4. When the timeout has expired, check if what we have processed does the job.

In Linux (and many other Unix flavors), the watch-list can be handled using FD_SET and a select system call. In Windows, you will need to use WaitForMultipleEvents.

I'm not sure I can do justice to explaining these concepts accurately for the purposes of this question. As a reference, another question which has some code pointers for exactly the same thing is here.

2. Synchronous: Multithreaded with Interrupt This is a common technique used for cases where we need a fine-grained event-scheduler / timer.

  1. Create two threads, A and B.
  2. A will wait on the indicated timeout.
  3. B will wait on a blocking read
  4. If A terminates (times out) before B finishes, A signals B and B decides what to do next (terminate, repeat a message etc)
  5. If B reads the password and it's fine, B signals A and asks it to die.

Another way to achieve the same is to make the OS interrupt thread B as described in one of the comments.

3. Synchronous: Polling This is used for cases where we don't need too much of a fine-grained control over time.

  1. Check if there is anything in the input using a non-blocking read (kbhit())
  2. If there is none, and if there is time remaining in the timeout, wait for a smaller amount of time delta (say 10ms)
  3. If the timeout has expired and there is no more time remaining, do whatever processing is needed (message the user, exit etc)

Note that in this case, depending on the delta, the approach may consume a lot of CPU and may be inefficient. For example, if delta=10ms as above, the thread will be woken up 100 times every second and it will be not efficient, especially when users do not type characters on their keyboard that fast.

这篇关于用C ++输入超时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆