我正在构建的程序在无限while循环中运行,其中包含一个switch case。我想在每种情况下插入一个while循环,并在循环中执行一些操作,但循环应该在键盘输入后立即退出。因此,在从键盘获取输入后,将运行另一个case,其中包含嵌套的while循环,并继续执行该过程。
结构为:
while()//infinite loop
{
............... //operations
............... //operations
switch()
{
case 1:
............... //operations
............... //operations
while()//infinite loop
{
..............
..............
exit if there is any input from keyboard
}
break;
case 2:
............... //operations
............... //operations
while()//infinite loop
{
..............
..............
exit if there is any input from keyboard
}
break;
case n:
............... //operations
............... //operations
while()//infinite loop
{
..............
..............
exit if there is any input from keyboard
}
break;
}
}
有办法吗??
Linux的键盘输入是缓冲的,为了捕捉在飞行中被击中的键,您必须配置TERM IO
在的顶部附近main()添加一个调用到(参见下面的代码)
term_nonblocking();
读取在运行中按下的键,而不等待回车(CR)。
代码:struct termios stdin_orig; // Structure to save parameters
void term_reset() {
tcsetattr(STDIN_FILENO,TCSANOW,&stdin_orig);
tcsetattr(STDIN_FILENO,TCSAFLUSH,&stdin_orig);
}
void term_nonblocking() {
struct termios newt;
tcgetattr(STDIN_FILENO, &stdin_orig);
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); // non-blocking
newt = stdin_orig;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
atexit(term_reset);
}
注意:当你的程序退出时,term_reset()
将被自动调用(重置终端参数)。
你可以在程序的任何地方调用现在非阻塞的getchar()
来检测按键
int i = getchar();
并检查是否按下了一个键:
if (i > 0) {
// key was pressed, code in `i`
}
在你的程序中例如:
int key = 0;
while (... && key <= 0) {
// ...
key = getchar();
}
注意:如果你想让输出不被缓冲,调用setbuf(stdout, NULL);
(@stacey的注释:getchar()可能在没有键可用时返回0或-1)
谢谢大家....尽管我的答案有点不合常规,但我认为ring0的方法要好得多。以下是我所做的。
- 在外部while循环中添加了代码,允许编译器从文件中获取switch case的参数,例如data.dat
- 在每个嵌套的while循环中添加类似的代码,如果从data.dat中检索到的变量是运行循环所需的,则继续,否则中断。
- 由于在linux中我可以在后台运行进程,所以我在后台运行主程序,并相应地编辑data.dat。
这个方法对我来说很有效,但我肯定也会尝试ring0的方法。
对于我必须维护的旧系统,我也有类似的愿望。我想添加一个"退出",并提供一些时间。我去掉了所有的专有代码,留下了我从这个网站学到的东西的外壳。谢谢你。
我最终通过ring0使用了上面的例子。我想评论一下,但我还没到那个水平。
我也从这里得到了Ulf和Walter的一些信息
我不能使用fcntl,因为在我们的代码中使用的全局变量与fcntl中的某些内容冲突,而我不想弄清楚如何避免这种冲突。
不管怎样,这里有一个例子。它在Debian(旧版本)上对我有效。你的里程可能会有所不同。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#define SLEEP 500000. /*usec*/
#include <termios.h>
struct termios stdin_orig;
void term_reset() {
tcsetattr(STDIN_FILENO, TCSANOW, &stdin_orig);
tcsetattr(STDIN_FILENO, TCSAFLUSH, &stdin_orig);
}
void term_nonblocking() {
struct termios term;
tcgetattr(STDIN_FILENO, &stdin_orig);
term = stdin_orig;
term.c_iflag |= IGNBRK;
//term.c_iflag &= ~(INLCR | ICRNL | IXON | IXOFF);
term.c_lflag &= ~(ICANON);// | ECHO | ECHOK | ECHOE | ECHONL | ISIG | IEXTEN);*/
term.c_cc[VMIN] = 0;
term.c_cc[VTIME] = 0;
/* fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); // non-blocking */
tcsetattr(STDIN_FILENO, TCSANOW, &term);
}
// end mikes timing
int main (void)
{
int key=0;
// mikes test variables
long mnloops = 0;
double mttot = 0.0;//total time elapsed in difference between start-end.
term_nonblocking();
// end mikes test variables
/*main loop*/
do{
//mikes timing
puts("Start Do");
time_t mnow;
struct timeval mtv;
struct timezone mtz;
time(&mnow);
gettimeofday(&mtv, &mtz);
double startTime = (double)mnow + mtv.tv_usec/1e6;
// end mikes timing
usleep(SLEEP);
puts("got hey");
//mikes timing
time(&mnow);
gettimeofday(&mtv, &mtz);
mttot += (((double)mnow + mtv.tv_usec/1e6) - startTime);
mnloops++;
key = getchar();
// end mikes timing
}while (1 && key != 'q');/* end of main loop*/
term_reset();
printf("DONE: average time per loop = %-10.4en",mttot/mnloops);
return 0;
}