2014-02-20 10 views
5

아래 코드 섹션을 찾으십시오. 루프의 변수의 현재 값을 계속 인쇄하고 싶습니다. 그리고 일단 회피 키를 누르면 루프가 종료되어야합니다. 여기서 문제는 getchar 함수에서 실행이 중지된다는 것입니다. 하지만 나는 escape 버튼을 누르기 전까지 계속 변수의 값을 출력하고 싶습니다.루프에서 변수를 연속적으로 출력하고 Linux에서 C의 이스케이프 키를 눌러 종료하는 방법은 무엇입니까?

do 
{ 
    vUpdateVariable();  // routine to update the current value of variable 
    printf("Value is %f\r", fVariable); 
    ucKey = getchar(); 
    usleep(1000); 
}while (ucKey != 0x1B); 
+1

getchar는 차단 호출입니다. 이것은 Linux 또는 Windows 또는 다른 OS에 있습니까? Windows에서는 _kbhit을 사용하십시오. Linux에서는 ioctl로 설정하거나 터미널 속성을 수정해야합니다. – cup

+0

Linux의 경우 [여기] (http://stackoverflow.com/questions/448944/c-non-blocking-keyboard-input)를 참조하십시오. Windows의 경우 [여기] (http://stackoverflow.com/questions/3643738/how-to-read-available-input-without-blocking-on-windows?rq=1)를 참조하십시오. – herohuyongtao

+1

@starsplusplus 잘못된 중복입니다. OP가 C를 지정할 때 C++에서 중복되는 것을 좋아하지 마십시오. – Lundin

답변

0

아래 코드를 사용해 보았습니다. 변수를 연속적으로 인쇄합니다. stderr를 사용해야했습니다. stdout은 프로그래머가 명시 적으로 요청할 때 또는 가장 편리한 경우 stderr가 메시지를 즉시 기록 할 때 v 퍼를 플러시합니다. 터미널의 표준 모드로 인해 사용자 입력을 확인하려면 enter 키를 눌러야합니다. 정식 모드는 코드의 비 블로킹 실행에 대해 비활성화되어야합니다. 정식 모드는 항상 사용자 입력을 확인하기 위해 입력을 기다리는 것을 의미합니다. 그게 당신의 경우가 아니라면, nonblock 그 기능을 제공합니다. 나는 그것을 나 자신으로 이해하지 못한다. 다른 포럼의 코드와 설명을 얻었습니다.

#include<stdio.h> 
#include<curses.h> 
#include<unistd.h> 
#include <termios.h> 
#include <sys/time.h> 

#define NB_ENABLE 0x01 
#define NB_DISABLE 0x00 

int kbhit() 
{ 
    struct timeval tv; 
    fd_set fds; 
    tv.tv_sec = 0; 
    tv.tv_usec = 0; 
    FD_ZERO(&fds); 
    FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0 
    select(STDIN_FILENO+1, &fds, NULL, NULL, &tv); 
    return FD_ISSET(STDIN_FILENO, &fds); 
} 

void nonblock(int state) 
{ 
    struct termios ttystate; 
    tcgetattr(STDIN_FILENO, &ttystate); //get the terminal state 

    if (state==NB_ENABLE) 
    { 
      //turn off canonical mode 
      ttystate.c_lflag &= ~ICANON; 
      //minimum of number input read. 
      ttystate.c_cc[VMIN] = 1; 
    } 
    else if (state==NB_DISABLE) 
    { 
      //turn on canonical mode 
      ttystate.c_lflag |= ICANON; 
    } 
    //set the terminal attributes. 
    tcsetattr(STDIN_FILENO, TCSANOW, &ttystate); 
} 
int main() 
{ 
     char c,i; 
     while(c != 27) 
     { 
      usleep(10000); 
      vUpdateVariable();  // routine to update the current value of variable 
      printf(stderr,"Value is %f\r", fVariable);    
      i=kbhit(); 
      c=fgetc(stdin); 
     } 
     nonblock(NB_DISABLE); 
     return 0; 
} 
2

이 내 개인 좋아하는 포크와 신호를 사용하는 것입니다 그러나 그 here 언급을 포함 할 수있는 방법의 넓은 범위가 있습니다. 이것은 모든 루프 반복에서 비 블로킹 운영 체제보다 효율적입니다 (시스템 호출과 컨텍스트 스위치를 낭비하지 않습니다).

효과적으로 작업자 프로세스를 포크하여 루프를 수행하고 USR1에 대한 신호 처리기를 설치 한 다음 부모 프로세스가 키 누르기 차단을 기다리게 한 다음 원하는 키를 받으면 다른 프로세스에 USR1 신호를 보낼 수 있습니다 프로세스가 신호 처리기를 정리하고 종료하게합니다.

대한 추가 정보를 원하시면 다음을 참조하십시오 :

가 나는 또한이 솔루션을 사용하면 비 차단 IO를 사용하여 해결할 수있는 효과적으로 어떤 블로킹 상황에 작동하는 것을 유의하여야한다 포크를 만들 때 약간의 메모리와 CPU 비용이 들기는하지만 보통 CPU 시간을 절약 할 수 있습니다.

+1

새 프로세스를 포크하는 것이 필요합니다. 스레드는 어떨까요? 스레드를 작성하려면 fVariable 및 vUpdateVariable 함수를 인쇄하십시오. 그리고 메인은 이스케이프 키가 눌러지기를 기다립니다. 키를 누르면 주요 기능에서 스레드가 종료 될 수 있습니다. 좋은 해결책입니까? 쓰레드가 훨씬 가볍기 때문에. – SilentCat

+1

실제로 사실, 당신은 스레드에 대해 정확합니다. 왜냐하면 이처럼 간단한 상황에서 IMO를 설정하기가 더 복잡하기 때문에 나는 그것을 피했습니다.그러나 그들이 더 잘 작동 할 것이라고 생각한다면 (사실 일 가능성이 높습니다) 또는 더 빨라집니다. 응답에 메모를 추가하게되어 기쁘게 생각합니다. 또는 원한다면 직접 만들 수도 있습니다. 사실 두 가지 접근 방식의 벤치 마크를보고 싶습니다. 시간이 있다면 시도해 볼 수 있습니다. – Vality

+0

오케이. 그 좋은 소리. 나는 두 방법으로 시도하고 게시 유지합니다. – SilentCat