2013-06-05 2 views
5

내가 짓고있는 프로그램은 스위치 케이스가있는 무한 while 루프에서 실행됩니다. 각 경우마다 while 루프를 삽입하고 루프에서 몇 가지 작업을 수행하려고하지만 키보드 입력이 제공되는 즉시 루프가 종료되어야합니다. 키보드에서 입력을 받으면 중첩 된 while 루프가있는 다른 케이스가 실행되고 프로세스가 계속됩니다.키보드에서 C 값을 가져 와서 C에서 리눅스의 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; 
     } 
    } 

있습니까 ???

+2

키보드 입력을 얻는 방법이나 중첩 루프를 해제하는 방법을 묻는 중입니까? – ugoren

+0

원시 입력을 수행하는 방법을 묻는 중입니까? 문자 또는 제어 코드를 생성하는 _any_ 키가 눌러지면 대기가 끝나기 때문에 Enter 키를 눌러야합니다 (선택적으로 텍스트를 입력 한 후). – blubberdiblub

+0

키보드 문제의 해결책에 관계없이이 함수는 리팩토링되어야합니다. – unwind

답변

0

도 내 대답은하지만 .... 당신에게 사람을 감사 상자 밖으로 조금있다, 나는 ring0의 접근 방식이 훨씬 좋다고 생각해. 내가 한 일은 다음과 같습니다.

    는 외부 내부
  • 추가 된 코드는 컴파일러가 파일, 말에서 스위치 케이스에 대한 인수를 할 수 있습니다 루프, 중첩의 각은 data.dat
  • 추가 유사한 코드가 루프 변수 경우 계속하면서 동시에 data.dat에서 검색하면 루프를 실행하는 데 필요한 것이고, 그렇지 않으면 break가됩니다.
  • 리눅스에서 배경으로 프로세스를 실행할 수 있으므로 백그라운드에서 주 프로그램을 실행하고 이에 따라 data.dat를 편집했습니다.

이 방법은 저에게는 효과적이지만 꼭 ring0의 방법을 시도 할 것입니다.

6

리눅스 키보드 입력이 버퍼링되므로, 즉시 맞았던 키를 잡으려면 TERM IO를 구성해야합니다. 주요 (위쪽에

)에 대한 호출을 추가 (캐리지 리턴을 기다리지 않고, CR을

term_nonblocking(); 

즉석에서 누른 키를 읽을 수있는 ( 다음 코드를 참조)).

코드 :

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()가 자동으로 호출됩니다.

당신은 호출 할 수 있습니다

지금 키를 누르는에게

int i = getchar(); 

을 감지하고 키를 누를 경우 확인하는 프로그램 어디에서든 getchar() 비 - 블로킹 (non-blocking) :

if (i > 0) { 
    // key was pressed, code in `i` 
} 

를 프로그램에서 예를 들면 :

int key = 0; 

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

참고 : outpu t는, 버퍼링 될 setbuf(stdout, NULL);

전화 (@stacey에서 코멘트 : getchar가()를 0 반환하거나 수 -1 키를 사용할 수 없을 때)

+1

외부 루프가 다시 처리 할 수 ​​있도록 문자를 읽는다면'ungetc (i, stdin)'을 원할 수 있습니다. –

+0

@JonathanLeffler 감사합니다. 이것은 참으로 귀중한 정보입니다. –

+1

getchar()는 키를 누르지 않은 경우 -1 또는 0을 반환합니다. 내 while 조건에서'(key <= 0)'를 사용하여이 문제를 해결했습니다. 그 자체로, 아무 것도 누르지 않으면 while 루프가 즉시 끝납니다. – stanri

0

나는 유지해야하는 오래된 시스템에 대한 비슷한 욕망을 가지고있었습니다. 나는 타이밍을 제공 할뿐만 아니라 "종료"를 추가하고 싶었다. 나는 모든 독점 코드를 제거하고이 사이트에서 배운 것의 껍질을 남겼습니다. 고맙습니다.

위의 예를 사용하여 ring0으로 끝났습니다. 나는 논평하고 싶었다. 그러나 나는 아직 그 수준에 있지 않다.

또한 Ulf에 의해 here에서 몇 가지 정보를 가지고 가고 Walter

나는 때문에 fcntl을 내 뭔가 갈등 우리의 코드에 사용 된 전역 변수의 fcntl을 사용하지 수 있고 나는 방법을 알아낼 싶지 않았다 그 충돌을 피하십시오.

어쨌든, 여기 예가 있습니다. 데비안에서는 저에게 도움이되었습니다 (이전 버전). 귀하의 마일리지가 다를 수 있습니다.

#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; 
} 
관련 문제