5

我正在构建的程序在无限循环中运行,其中包含一个开关盒。我想在每种情况下插入一个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;
        }
  }

有什么办法吗???

4

3 回答 3

6

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()当您的程序退出时将自动调用,(以重置终端参数)。

您可以在程序中的任何位置调用 now non-blockinggetchar()来检测按键

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)

于 2013-06-05T11:09:26.700 回答
0

谢谢大家......尽管我的回答有点开箱即用,但我认为 ring0 的方法要好得多。这就是我所做的。

  • 在外部 while 循环中添加了代码,允许编译器从文件中获取 switch case 的参数,例如 data.dat
  • 如果从 data.dat 检索到的变量是运行循环所必需的,则在每个嵌套的 while 循环中添加类似的代码以继续,如果不是,则中断。
  • 由于在linux中我可以在后台运行进程,所以我在后台运行主程序,并相应地编辑了data.dat。

这种方法对我有用,但肯定也会尝试 ring0 的方法。

于 2013-06-06T07:48:46.320 回答
0

我对必须维护的旧系统也有类似的愿望。我想添加一个“退出”并提供一些时间。我剥离了所有专有代码,并留下了我从这个站点学到的东西的外壳。谢谢你。

我最终通过ring0使用了上面的示例。我想发表评论,但我还没有达到那个水平。

我还从UlfWalter那里获取了一些信息

我无法使用 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.4e\n",mttot/mnloops);
  return 0;
}
于 2017-03-31T18:16:06.773 回答