• ベストアンサー

whileの途中で手続きを変化するプログラム

表題の件について質問させていただきます。 while(1)を含むプログラムを走らせている途中で何かしら入力するとそれに伴って処理を変更するプログラムを作成したいと思います。 具体的には ・qを押せばCtrl+cとは違い、正常な手続きを持ってプログラムを終了する。 ・押したキーに従い、while(1)文の中で呼び出される関数を変更する。 といったことを行いたいです。 このようなことは可能なのでしょうか? ご指導をお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • Interest
  • ベストアンサー率31% (207/659)
回答No.3

関数へのポインタを使って、 /////////////////////////////////////////// typedef void ( * mfunc ) ( void ) ; void func1(); void func2(); void func3(); mfunc pfunc = func1; /* デフォルト func1 */ int fin = 0; /* 1なら終了処理を行う */ while(1){  /* 押されたキーに応じて実行する関数を切り替える */  if( kbhit() ){   c = getch();   switch(c){   case 'p':    pfunc = func2; /* 関数へのポインタを付け替える */    break;   case 'q':    fin = 1; /* while を抜けて終了処理にすすむ */    break;   case 'r':    pfunc = func3; /* 関数へのポインタを付け替える */    break;   default:    pfunc = func1; /* 関数へのポインタを付け替える */    break;   }  }  if( fin ){   break;   /* 終了処理に進む */  }  else{   pfunc();  /* 関数を実行する */  } } /* 終了処理 */ ほげほげ; //////////////////////////////////////// こんなつくりなら、 > ・qを押せばCtrl+cとは違い、正常な手続きを持ってプログラムを終了する。 > ・押したキーに従い、while(1)文の中で呼び出される関数を変更する。 を満足できますよね。

runjump
質問者

お礼

ありがとうございます! うまく実装することができました。 kbhitは自作しないとだめなのですね。。。 下記のサイトを参考にして作りました。 http://www.ie.u-ryukyu.ac.jp/viewvc/y05/j05058/exercise7.4/kbhit.c?revision=1.1.1.1&view=markup 大変勉強になりました。ご回答してくださった皆さま本当にありがとうございました!

その他の回答 (2)

  • eroermine
  • ベストアンサー率18% (83/444)
回答No.2

OSはなんでしょうか。 unix系の場合 1. ioctlを使ってgetchar等を入力待ちにさせない。 2. select を使って入力文字を確認してからgetcharする。 1 だとMSDOSでもできたような。 PC98時代は当然ハードスキャン、Windowsだと WndProcがキー等の 割り込みエントリーなのでそもそもwhile(1)で回す必要がない(回せない)

runjump
質問者

お礼

ご回答ありがとうございます。 私の環境はUNIXです。 キー入力を自動感知する標準関数がよういされていればいいのですが・・・

  • hisa1972
  • ベストアンサー率53% (268/500)
回答No.1

この手の処理はよくやりますので、私の場合ですが・・・ while(1)でなく、 int loopflag; loopflag=0; while(!loopflag){ if(/* q が押されたことを検出する処理*/){ loopflag=1; } } などのように、無条件ループでなく、ループの終了条件を設定する方法は如何でしょうか? ループ後に、loopflag の値によって、どの条件でループを抜けたかが判別できると思います。

runjump
質問者

お礼

素早いご回答ありがとうございます。 非常に参考になります。 なるほど教えていただいた方法で多彩な条件分岐ができそうです。 ところでqが押されたことを検出する処理というのはたとえばどのようなものがあるのでしょうか? scanf等を使うとそこで止まってしまいます。 今調べていると、WindowsやJava等ではそのような関数が用意されているようなのですが、Linuxの標準関数でキー入力検出ができるの関数は用意されているのでしょうか? TimeOut等を設定するのでしょうか?

関連するQ&A

  • ループを途中で抜けたいのですが。

    無限ループさせているwhileやfor文などで、 何かのキーを押すとループを抜けるように設定したいのですが可能でしょうか? (scanfやcinなどをループの中に組み込まずに。ctrl+Cも無しで。) (あと、フォーム上ではなくコンソール上で。) 多分説明不足なのでもうちょっと詳しく。 たとえば、 while ( i != 1 ){ j += 1; } の様な無限ループを設定したとして、 本来なら if (j > 100 ){ break; } とか、 while文の中に scanf ( "%d" , &i ); 等を入れて終了条件を満たさせるべきですが、 そうではなく、ひたすら無限ループを続けているところにEscキーを押すとループから脱出するようなプログラムを作ってみたいのです。 そういうプログラムは可能でしょうか? どうかご教授下さい。 使用コンパイラ:Visual C++ 2008 Express Edition

  • 線形探索(番兵法)のプログラムについて。

    線形探索(番兵法)のプログラムについて考えています。 メイン関数からsearch関数に値を渡してそこで探索させるのですが、 int search(int a[], int n, int key) { int i = 0; a[n] = key; while (1) { if (a[i] == key) break; i++; } return (i == n ? -1 : i); } のwhileを使ったやり方からfor文を使ったやり方に変更したいと思っています。 色々な方法でプログラムを考えてみたいので。 そうすると、なんかうまくいきません。 for文だとどのように考えたらいいのでしょうか?

  • MATLABでのwhile文の条件について

    MATLABでのwhile文の条件について いつもお世話になっております。 MATLABでwhile文を用いる際、その条件として行列中の特定の次元の値が存在するかどうかという条件を用いたいと考えています。 例えばsize(a)=(10 10 50)のaという画像データを読む際に、a(:,:,1)から順番に読み込んでいって a(:,:,50)で自動に止まるようなwhile文を作りたいと考えています。 つまりこの場合は順番に読み込んでいって、a(:,:,51)が存在しないならばwhile文が終了するようなプログラムを行いたいと考えております。 for文を用いればすぐだとは思いますが、どのようなデータにも入力引数なしで応用が出来ないかと思いましてご質問させていただきました。 もし以上の条件を満たす適当な関数などございましたら、ご一報いただけたらと存じます。

  • pingを行うプログラム

    Windows2000,VB6.0(sp5)の環境下でpingを行うプログラムの開発をしています。 API関数のIcmpSendEchoを使っているのですが、エラー時の処理がうまく制御できません。 この関数の返り値が"0"なら、エラー。"0"以外なら正常終了というようなことが HELPに書いてあったのですが、結果を"正常終了","タイムアウト","異常終了" の3つで判別するにはどのようにしたらいいのでしょうか? ご存知の方がいましたら教えてください。 よろしくお願いします。

  • C言語のプログラムについて

    C言語のプログラムについて 3桁の自然数の中で、自分自身を含めた約数が奇数になるものがいくつあるかを求めるプログラムを作りたいのですが、swich文を使って、6通りの方法で出そうとしていまして、 while 文、 for文、 do while文に加え、 for文のを、1つの関数として独立させたもの、 さらに、for文のを重ループ部分のそれぞれのループに対応して、2つの関数として独立させたもの、 そして、この2つの関数のどちらともをループを用いずに再帰呼び出しを用いたもの の6通りで出したいのですが、swich文を使うところは自力でできたのですが、あとの6つそれぞれのプログラムの組み方がわかりません。 教えていただけないでしょうか?ややこしい書き方をしてすいません・・・。

  • 流れ図からプログラムに直してください!【C言語】

    その流れ図をC言語のプログラムに直してくれませんか? 処理2はscanf(..);って感じの内容です。 入口 処理1 for(処理2; 判断; 処理4){ 処理3 } 出口 って感じかなって思ったんですが、for文の中にscanfの文を入れてもいいのかわからずに悩んでます。 ループ文なのでwhile文、for文、do..while文のどれかかな?って思ったんですが違う気もして、わかるかたいらっしゃいませんか?

  • Perlで配列に設定した値が関数に引き継がれない。

    レンタルサーバ上でPerlのプログラムを作成しているの ですが、動作でよくわからないことがあるので、教えてください。 Perlのプログラムがあるサーバで動作していて、それを 他のサーバに移したのですが、正しく動作しなくなりました。 調べてみると、関数を呼んでいるところで配列の値がうまく 引き継がれていませんでした。 呼び出しの処理は次の通りです。 ●呼び出し元 ret= &SubModule(*DATA1); ●呼び出し先 sub SubModule { local(*DATA1) = @_ if @_; while(($key, $value) = each(%DATA1)) { #配列に対する処理 } #以下省略 このような処理の時に呼び出し元では配列DATA1に 値が入っているのに呼び出し先のSubModuleでは 空になりwhile文を素通りして「#配列に対する処理」 を実行しません。 いろいろ試しているうちに、呼び出し先に1つ余計な whileを入れると配列DATA1に値が入ってきました。 つまり次のように変更すると、うまくいきました。 呼び出し先 sub SubModule { local(*DATA1) = @_ if @_; while(($key, $value) = each(%DATA1)) { } while(($key, $value) = each(%DATA1)) { #配列に対する処理 } #以下省略 こうすると 「#配列に対する処理」が実行されました。 教えていただきたいのは以下の2点です。 (1)元のサーバでは問題なく動作していたのですが、  別のサーバでは、配列の引数がうまく引き継がれ  なくなりました。どういう原因が考えられるでしょうか。  処理上何かまずいところがあるのでしょうか。 (2)呼び出し先でwhile文を一つ入れることで、配列の  値が参照できるようになったのですが、これは  なぜでしょうか。 よろしくお願いします。

    • ベストアンサー
    • Perl
  • C言語 kEYの空読み

    C言語でプログラムを組んでいます。 あるひとつの処理を連続で行い、何かKEYボタンをおすとプログラムが終了するというプログラム なのですが? while(kbhit()) getch(); while(1) { ~~~~~~      if(kbhit()) { getch(); return(1); } }while(c==0); という内容ですが、     if(kbhit())のあとの文面は、KEYが押されると(1)が返されエラーになり処理が中断される     ということはわかりますが、 冒頭でのこの部分while(kbhit())                getch(); は、どういった意図の分なのでしょうか?

  • whileとscanfの関係について

    while文中のscanf関数が意図しない動作をして困っています 簡略化したコードがこちらになります while(1){ // view printf("view\n"); // input char key; scanf("%c", &key); // update printf("update\n"); } 行いたい動作というのは単純で view -> input -> update ->を繰り返したいだけなのですが 上記プログラムでは下記のような動作になってしまいます view -> input -> update -> view -> update -> view -> input -> 偶数回目のループでは、inputが飛ばされてしまうのですが、何が原因なのかかがわかりません。 言語仕様に詳しい方、どなたかご教示ください。 環境 WindowsXP Visual C++ 2008 ExpressEdition

  • while文について

    while文について教えてください。 重複値をチェックして値が同じであれば繰り返し処理をするいうものなのですが以下であってますでしょうか? 大体は問題と思うのですがwhile内がいまいち自信がありません・・・ class Test { private $sisid = ''; //SISID生成 private function create_sisid() { return session_id(); } //SISID重複チェック private function check_sisid() { // SISID生成(変数にセット) $this->sisid = $this->create_sisid(); // SQL発行 $sql = "SELECT key FROM table"; //上記sqlで取得した値を$tmpに値を格納 //$tmp[0] = 1番目のkey //$tmp[1] = 2番目のkey //$tmp[2] = 3番目のkey・・・のように最後まで配列で取得 //ここで重複チェックしてSISIDが同じ値であれば再度SISIDを生成 //生成されたSISIDと$valが同じ値な場合は繰り返し処理を行いたい。 while (list($val) = $tmp) { if ($val == $this->sisid) { // 値が同じ場合SISIDを再度生成し再度重複チェック(変数にセット) $this->sisid = $this->create_sisid(); } else { break; } } } return $this->sisid; } } またこのような処理を行うにあたり多数のデータが存在する場合DBに掛かる負荷は大きくなりますか?

    • ベストアンサー
    • PHP

専門家に質問してみよう