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

如何在linux上通过从键盘获取任何值来打破C中的while循环?,c,linux,while-loop,C,Linux,While Loop,我正在构建的程序在一个无限while循环中运行,其中包含一个开关盒。我想在每种情况下都插入一个while循环,并在循环中执行一些操作,但只要给出键盘输入,循环就会退出。这样,在从键盘获取输入后,另一个case将使用嵌套的while循环运行,并且该过程将继续 结构如下: while()//infinite loop { ............... //operations ............... //operations switch

我正在构建的程序在一个无限while循环中运行,其中包含一个开关盒。我想在每种情况下都插入一个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键盘输入是缓冲的,为了捕获一个在运行中被击中的键,您必须配置IO

在main()的顶部附近添加对的调用(请参见下面的代码)

在不等待回车(CR)的情况下,读取动态按下的键

代码:

注意:
term\u reset()
将在程序退出时自动调用(以重置终端参数)

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

int i = getchar();
并检查是否按下了一个键:

if (i > 0) {
    // key was pressed, code in `i`
}
例如,在您的程序中:

int key = 0;

while (... && key <= 0) {
   // ... 
   key = getchar();
}
int键=0;

虽然(…&&key谢谢大家……尽管我的答案有点不合时宜,但我认为ring0的方法要好得多。 这就是我所做的

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

这个方法对我来说很有效,但肯定也会尝试ring0的方法。

我也有同样的愿望,需要维护一个旧系统。我想添加一个“退出”并提供一些时间。我去掉了所有专有代码,留下了我从这个网站学到的内容。谢谢

我最后使用了上面的例子。我想发表评论,但我还没有达到那个水平

我还从by和

我不能使用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;
}
#包括
#包括
#包括
#包括
#包括
#包括
#定义睡眠时间。/*usec*/
#包括
结构术语标准格式;
无效项_重置(){
tSetAttr(标准文件号、标准名称和标准原件);
tcsetattr(标准文件号、TCSAFLUSH和标准原始文件);
}
无效项_非阻塞(){
结构术语;
tcgetattr(标准文件号和标准原件);
术语=stdin_orig;
术语c|u iflag |=IGNBRK;
//术语c|u iflag&=~(INLCR | ICRNL | IXON | IXOFF);
term.c|lflag&=~(ICANON);/| ECHO | ECHOK | ECHO | ECHONL | ISIG | IEXTEN)*/
术语c_cc[VMIN]=0;
term.c_cc[VTIME]=0;
/*fcntl(标准文件号、设置符、非块);//非块*/
tcsetattr(标准文件号、TCSANOW和术语);
} 
//末端麦克风定时
内部主(空)
{
int键=0;
//mikes测试变量
长mnloops=0;
double mttot=0.0;//以开始和结束之间的差值表示的总时间。
术语_非阻塞();
//端mikes测试变量
/*主回路*/
做{
//麦克风定时
看跌期权(“开始做”);
时间;
结构时间值mtv;
结构时区mtz;
时间(&mnow);
gettimeofday(&mtv,&mtz);
双开始时间=(双)mnow+mtv.tv\u usec/1e6;
//末端麦克风定时
usleep(睡眠);
放置(“得到嘿”);
//麦克风定时
时间(&mnow);
gettimeofday(&mtv,&mtz);
mttot+=((双)mnow+mtv.tv_usec/1e6)-开始时间);
mnloops++;
key=getchar();
//末端麦克风定时
}while(1&&key!='q');/*主循环结束*/
术语_reset();
printf(“完成:每个循环的平均时间=%-10.4e\n”,mttot/mnloops);
返回0;
}

您是在询问如何获得键盘输入,还是如何打破嵌套循环?您是在询问如何进行原始输入,以便在按下任何产生字符或控制代码的键时,等待就结束了,而不是被迫按enter键(在可选地输入一些文本后)?无论键盘问题的解决方案如何,这个函数应该被重构。我需要知道如何用键盘输入来中断嵌套循环,这样,当外部while循环运行时,输入会再次被输入到外壳中。我计划做的是,当按下一个键,嵌套的while循环中断时,该键被写入一个文件。然后,当外部while循环再次运行时,此键将作为文件的输入,用于切换。实际上,可以在切换后进行等待,在所有情况下都是一次,而不是重复代码。如果您读取字符以便外部循环可以再次处理它,您可能需要
ungetc(i,stdin)
。@JonathanLeffler谢谢。这确实是很有价值的信息。请注意,如果没有按下某个键,getchar()将返回-1或0。我使用了
(key@stacey谢谢),编辑了答案,因为它可能会帮助其他人。
int key = 0;

while (... && key <= 0) {
   // ... 
   key = getchar();
}
#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;
}