2013-06-05 1 views
5

私が構築しているプログラムは、無限ループ中にスイッチケースを入れて実行されます。それぞれのケースの下にwhileループを挿入して、ループ内でいくつかの操作を実行したいが、キーボード入力が行われるとすぐにループが終了するはずである。キーボードからの入力を受けた後、別のケースがネストされたwhileループで実行され、プロセスは続行されます。キーボードから任意の値を取ってlinuxの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

生入力を行う方法を尋ねていますので、(任意選択でテキストを入力した後に)Enterキーを押すよう強制されるのではなく、charまたは制御コードを生成する_any_キーが押されるとすぐに待機が終了するようにしますか? – blubberdiblub

+0

キーボードの問題の解決法に関係なく、この関数をリファクタリングする必要があります。 – unwind

答えて

0

も私の答えかかわらず....あなたの人々に感謝します私はring0のアプローチがはるかに優れていると思います。 ここに私がしたことがあります。

    外側内部
  • 追加されたコードDATA.DAT
  • は、ネストされた一方の各々に同様のコードを追加し、たとえば、コンパイラはファイルからスイッチケースの引数を取ることを可能にするループ変数続行するwhileループdata.datから取得されたものは、ループを実行するために必要なものです。
  • 私はバックグラウンドでプロセスを実行できるので、バックグラウンドでメインプログラムを実行し、それに応じてdata.datを編集しました。

このメソッドは私のために働いていますが、間違いなくring0のメソッドも試してみます。

6

Linuxキーボード入力がバッファされています。オンザフライでヒットしたキーをキャッチするには、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()は(端末パラメータをリセットする)、自動的に呼び出されます。

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

例えば、あなたのプログラムでは:

あなたは今どこにでもキーを押して

int i = getchar(); 

を検出し、キーが押されたかどうかを確認するためにあなたのプログラムでgetchar()を非ブロック呼び出すことができます。

int key = 0; 

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

注:outpuトンは、バッファリングされていないことsetbuf(stdout, NULL);

呼び出すために(@staceyからのコメント:getchar関数を()は0を返すかも-1はキーが利用できない場合)

+1

文字を読み込んでもう一度外側のループで処理できるようにするには、 'ungetc(i、stdin)'したいかもしれません。 –

+0

@JonathanLefflerありがとうございました。これは本当に貴重な情報です。 –

+1

キーが押されていない場合、getchar()は-1または0を返します。これを回避するために私のwhile条件で '(key <= 0)'を使用しました。そのままで、何も押されなければ、whileループはすぐに終了します。 – stanri

0

私は、維持しなければならない古いシステムに似た欲望を持っていました。私はいくつかのタイミングを提供するだけでなく、「終了」を追加したかったのです。私はすべての専有コードを取り除き、このサイトから学んだことの殻を残しました。ありがとうございました。

上記の例をring0で終了しました。私はコメントしたかったが、まだそのレベルにはいない。

また、私は理由のfcntl内の何かと競合我々のコードで使用されたグローバル変数ののfcntlを使用することができなかったと、私はどのように把握したくなかった

Ulfによりhereからいくつかの情報を取り、Walterその競合を回避する。

とにかく、ここに例があります。 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; 
} 
関連する問題