如何在linux上通过从键盘中获取任何值来中断C中的while循环



我正在构建的程序在无限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;
}

相关内容

最新更新