中断C语言中的程序流

中断C语言中的程序流,c,keyboard,program-flow,C,Keyboard,Program Flow,我已经运行了一个循环,每次迭代都会增加一个变量的值,我希望能够点击键盘上的一个键来停止循环并报告变量的最终值。问题是,我不知道如何在C语言中实现这一点。我觉得自己很愚蠢,因为我似乎忽略了一些简单易行的方法,但我尝试的每件事都会停止循环,直到我按下键盘上的一个键,这基本上与我想要的恰恰相反 基本上我想做的是这样的: 当(按键未按下时) 增量值 打印最终值 这有意义吗?无论如何,关于如何在C中实现这一点的任何提示都取决于您的平台。C语言没有定义这样的东西 窗户?linux?(gnome应用程序?

我已经运行了一个循环,每次迭代都会增加一个变量的值,我希望能够点击键盘上的一个键来停止循环并报告变量的最终值。问题是,我不知道如何在C语言中实现这一点。我觉得自己很愚蠢,因为我似乎忽略了一些简单易行的方法,但我尝试的每件事都会停止循环,直到我按下键盘上的一个键,这基本上与我想要的恰恰相反

基本上我想做的是这样的:


当(按键未按下时)
增量值
打印最终值


这有意义吗?无论如何,关于如何在C中实现这一点的任何提示都取决于您的平台。C语言没有定义这样的东西


窗户?linux?(gnome应用程序?kde应用程序?终端?)还有什么吗?

这取决于您的平台。C语言没有定义这样的东西


窗户?linux?(gnome应用程序?kde应用程序?终端?)还有什么吗?

您正在调用以读取字符的函数正在阻塞。如果没有字符,您希望它返回


这里的神奇搜索词是非阻塞和非/非阻塞输入。

您正在调用的读取字符的函数是阻塞。如果没有字符,您希望它返回


这里的神奇搜索词是非阻塞和非/非缓冲输入。

为什么循环计数直到有人按下键才有意义

如果你真的想要这样的东西,你可以检查一下10公里的时间安排。
然后在非阻塞状态下等待睡眠()。当你得到时间时,你可以用它来近似“最终值”是多少

为什么循环计数直到有人按下键才有意义

如果你真的想要这样的东西,你可以检查一下10公里的时间安排。
然后在非阻塞状态下等待睡眠()。当您获得时间时,您可以使用它来近似“最终值”是多少

如果您试图一次从linux中的终端读取一个字符(不按enter键),则需要将终端设置为非缓冲输入

请参见此示例:


如果您试图在linux中从终端一次读取一个字符(不按enter键),则需要将终端设置为非缓冲输入

请参见此示例:


如果您在windows上工作,并且正在使用MSVC,那么您可能需要getch()和kbhit(),类似的东西

#include <conio.h>

while( looping ) {

    // do regular loop stuff

    // check if a key is hit, w/o blocking, using kbhit()
    if( kbhit() ) {
        // only runs when user has hit a key
        // so display stuff here,
        // and wait for permission to resume with getch()
        getch();
    }
}
#包括
while(循环){
//做常规的循环
//使用kbhit()检查键是否被击中,不带阻塞
if(kbhit()){
//仅在用户按下键时运行
//所以在这里展示东西,
//并等待使用getch()恢复的权限
getch();
}
}

如果您使用的是windows,并且使用的是MSVC,那么您可能需要getch()和kbhit(),类似的东西

#include <conio.h>

while( looping ) {

    // do regular loop stuff

    // check if a key is hit, w/o blocking, using kbhit()
    if( kbhit() ) {
        // only runs when user has hit a key
        // so display stuff here,
        // and wait for permission to resume with getch()
        getch();
    }
}
#包括
while(循环){
//做常规的循环
//使用kbhit()检查键是否被击中,不带阻塞
if(kbhit()){
//仅在用户按下键时运行
//所以在这里展示东西,
//并等待使用getch()恢复的权限
getch();
}
}

如果允许您指定按下的内容,并且您使用的是兼容POSIX.1的系统,则可以设置信号处理程序来捕获SIGINT(通过Ctrl+C发送)。让处理程序更改变量的值,使您脱离while循环


如果你选择这种方法,要小心。如果不正确的实现导致无限循环和捕获的SIGINT,您将无法通过Ctrl+C终止程序。在这种情况下,您需要使用kill(1)来终止程序。

如果允许您指定按下的内容,并且您在符合POSIX.1的系统上,您可以设置一个信号处理程序来捕获SIGINT(由Ctrl+C发送)。让处理程序更改变量的值,使您脱离while循环


如果你选择这种方法,要小心。如果不正确的实现导致无限循环和捕获的SIGINT,您将无法通过Ctrl+C终止程序。在这种情况下,您需要使用kill(1)来终止程序。

这是C标准让程序员无所事事的地方。这个问题的最可移植的解决方案是使用库进行I/O操作,该库处理所谓的“原始”键盘输入(这是您想要的)以及更多。学习曲线有点陡峭,但是有很好的教程,特别是在BSD程序员文档中。

这是C标准让程序员们绞尽脑汁的地方。这个问题的最可移植的解决方案是使用库进行I/O操作,该库处理所谓的“原始”键盘输入(这是您想要的)以及更多。学习曲线有点陡峭,但有很好的教程,特别是在BSD程序员的文档中。

根据系统及其工作方式,您可以尝试将选择函数与STDIN一起用作文件句柄。您可以将select语句上的时间设置为零,以轮询是否有数据,或者将其设置为等待时间

您可以查看链接,以获取将select语句与套接字一起使用的示例

我修改了这个示例,使用STDIN作为文件描述符。如果没有挂起的输入,函数将返回0;如果有挂起的输入(即有人按了输入键盘上的键),函数将返回1;如果有某种性质的错误,函数将返回-1

 #include <errno.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/time.h>

 int waitForKBInput(unsigned int seconds)
 {
   /* File descriptor set on which to wait */
   fd_set set;
   /* time structure which indicate the amount of time to
      wait.  0 will perform a poll */
   struct timeval timeout;

   /* Initialize the file descriptor set. */
   FD_ZERO (&set);
   /* Use the Standard Input as the descriptor on which 
      to wait */
   FD_SET (STDIN, &set);

   /* Initialize the timeout data structure. */
   timeout.tv_sec = seconds;
   timeout.tv_usec = 0;

   /* select returns 0 if timeout, 1 if input available, -1 if error. */
   /* and is only waiting on the input selection */
   return select (FD_SETSIZE,
                  &set, NULL, NULL,
                  &timeout));
 }
#包括
#包括
#包括
#包括
#包括
整数waitForKBInput(无符号整数秒)
{
/*要等待的文件描述符集*/
fd_集;
/*时间结构,它指示需要的时间量
等等,0将被删除
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

long globalvar = 0;
int interrupts_before_exit = 3;

void ctrl_c_handler(int x) {
  printf("Value of the variable: %ld\n", globalvar);
  if(--interrupts_before_exit) {
    printf("Press Ctrl-C %d more times to stop\n", interrupts_before_exit);
  } else {
    printf("Computation interrupted!\n");
    exit(0);
  }
}


int main(int argc, char *argv[]) {
  struct sigaction act;

  act.sa_handler = ctrl_c_handler;
  sigemptyset(&act.sa_mask);
  act.sa_flags = 0;

  if(sigaction(SIGINT, &act, NULL) >= 0) {
    while (1) {
      /* The work happens here */
      globalvar++; 
    }
  }
  exit(1);
}
/*  testbrk

  Test breaking an infinite loop with a keystroke.
  Hit the <Enter> key to break this loop.

*/


/* Include block */
#include  <errno.h>
#include  <fcntl.h>
#include  <stdio.h>
#include  <stdlib.h>
#include  <unistd.h>


/*---testbrk main loop---*/

int  main ( int argc , char ** argv )
{

  /* Variables: file flags , return value , buffer */
  int  f ;
  ssize_t  r ;
  char  b ;

  /*
    Switch standard input to non-blocking mode:
    -Get existing flags from the file descriptor
    -Bitwise OR to activate non-blocking bit
    -Apply new flags
  */
  if  ( f = fcntl( STDIN_FILENO , F_GETFL , 0 )  ==  -1 )
  {
    perror ( "fcntl F_GETFL" ) ;
    exit ( EXIT_FAILURE ) ;
  }

  f |= O_NONBLOCK ;

  if  ( f = fcntl( STDIN_FILENO , F_SETFL , f )  ==  -1 )
  {
    perror ( "fcntl F_SETFL" ) ;
    exit ( EXIT_FAILURE ) ;
  }


  /*
    Infinite loop
    -try reading from standard input directly via its file
     descriptor , NOT the standard input stream
    -if the number of bytes returned is > zero then break
    -if bytes returned is -1 then check errno for EAGAIN,
     meaning that read would block but the file is nonblocking
    -if zero is returned then print message immediately
  */
  while  ( (r = read( STDIN_FILENO , &b , sizeof( b ) ))  <  1 )
  { 

    if  ( r == -1  &&  errno != EAGAIN )
    {
      perror ( "read" ) ;
      exit ( EXIT_FAILURE ) ;
    }

    fprintf ( stderr , "\nInfinite loop" ) ;

  } /* inf loop */

  /* Done */
  printf ( "\n\nBroken loop\n\n" ) ;
  exit ( EXIT_SUCCESS ) ;

} /* testbrk */