使 C++ 不等待用户输入
Make c++ not wait for user input
所以,我正在尝试做一个c ++ WinSock2的聊天,只是为了学习。这是一个控制台应用程序,我想接受用户输入(用于发送给对应方(,但我仍然希望能够接收。(因此,您可以在仍然能够接收消息的同时编写消息(...
当使用cin >> input;
程序"暂停"直到用户输入某些内容时,这样它是"基于回合的"(一个用户编写内容并发送它,然后另一个用户写入某些内容并发送它(。
有没有办法让用户能够在接收内容仍在运行时编写一些东西?(最好是多线程以外的其他东西(
检查缓冲区是否为空怎么样?但是代码不会真正可移植,因为据我所知,您需要进行一些系统调用。看到这里。
但也许你可以用一些 C 代码来做,我会做一些研究并更新我的答案。
UPD:好的,我做到了。您需要的是选择功能。
它可以等到stdin
准备好阅读,这就是我们所需要的。但看起来它不适用于C++流,因此您只需要使用 C 代码进行读取。
让我们跳到定义:
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout)
好的,我们只需要检查读取缓冲区,因此可以NULL
writefds
和errorfds
。我们只需要检查stdin
,所以nfds
是1
(fds
es的数量(
超时呢?它应该是0
的,所以我们需要初始化变量struct timeval timeout
,并通过timeout.tv_sec = 0
和timeout.tv_usec = 0
将秒和纳秒设置为0。
所以,只剩下readfds
了。这也很简单:我们需要初始化变量,将其"归零",然后添加stdin
。
它可以通过fd_set readfds
、FD_ZERO(&readfds)
和FD_SET(STDIN_FILENO, &readfds)
来完成。
好的,最后一步:函数调用。应该是select(1, &readfds, NULL, NULL, &timeout)
.
如果输入缓冲区为空,这将返回0
,如果不是,则返回1
。
UPD2:看起来它不是C++流,发生了一些奇怪的事情,当缓冲区在第一次调用时为空时它会中断。我会尝试抓住问题。
UPD3:好的,现在我想通了。看起来您可以将select
与C++流一起使用。
Select
具有非常奇怪(恕我直言(的功能:它会重置readfds
。我不确定如何防止它这样做,所以我只是再用一个fd_set
变量来保存它,所以你需要在readfds
初始化后添加fd_set savefds = readfds
,并在每次调用后添加readfds = savefds
。这是一个糟糕的解决方案,但我不知道如何改进它。
所以代码是:
初始化:
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(STDIN_FILENO, &readfds);
fd_set savefds = readfds;
超时初始化:
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
和用法:
if (select(1, &readfds, NULL, NULL, &timeout)) {
cin >> input;
send(input);
}
readfds = savefds;
UPD4:不要忘记包括unistd.h
和cstdlib
上面的答案很有帮助。
下面是一个示例(基本代码取自 SELECT 手册页(:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <iostream>
int main(void)
{
fd_set rfds, save_rfds;
struct timeval tv;
int retval;
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(0, &rfds);
/* Make a copy of rfds, as after running select, it gets reset */
save_rfds = rfds;
/* Wait for zero seconds. */
tv.tv_sec = 0;
tv.tv_usec = 0;
while(true){
retval = select(1, &rfds, NULL, NULL, &tv);
rfds = save_rfds;
if (retval == -1)
perror("select()");
else if (retval){
/* Runs as soon as you enter a value and press enter. */
std::cout<<"Data is available now.n";
std::string s;
getline(std::cin, s);
std::cout<<"Data Input: "<<s<<"n";
/* FD_ISSET(0, &rfds) will be true. */
}
}
exit(EXIT_SUCCESS);
}
- C++如何通过用户输入删除列表元素
- 如何使用用户输入在C++中正确填充2D数组
- C++MySQL C api用户输入行
- 如何只允许用户输入正整数
- C++如何计算用户输入的数字中的偶数位数
- 通过for循环使用用户输入填充列表
- 在C++中,我如何接受不同于同一行的用户输入
- 如果用户输入无效,如何使用字符串变量-C++重复输入命令
- 显示基于用户输入的整数的字符
- 根据用户输入用字母填充矢量,并将"开始"和"结束"放在四肢
- 我试图制作一个程序,要求用户输入问题和答案,但程序循环不正确
- 打印时有二叉树问题.用户输入不打印任何内容
- C ++奇怪的数组由用户输入
- 如何允许大写和小写用户输入?
- C++读取用户输入而不按回车键(Mac OS X),与Turbo Pascal中的读取键相同
- 如何存储用户输入的所有数据,然后在他们想要查看所有数据时显示它们
- 如何使用用户输入变量制作二维数组?
- 用户输入字符串的文件附加问题..C++
- 遇到此问题时遇到困难:允许用户输入数组的值并使用 for,而循环也输出输入的最大数字
- 如何使用递归循环我的代码(当用户输入无效输入时,它会再次提示他们)?