• ベストアンサー

for文実行中を途中で中断するには?

質問させてください! 例えば作成したアプリケーションのウインドウ上に、ボタンAとボタンBがあります。 そしてそのボタンAを押した時(イベントAが起きたとき)に、 for文が10000回ループするというプログラムがあるとします。 しかし、その10000回ループしている過程でウインドウ上のBボタンを押した時(イベントBが発生)すぐに、そのループを中断してイベントBが起きたときに起こる別のプログラムを流したいのです。 現実は、10000回ループし終えるまで、ボタンBを押してもイベントBは起きることはありません。 10000回ループし終えてから、ボタンBを押した時に発生するイベントBが発生します。 for文のループをボタンBを押した時実行途中でも終了して、イベントA用に書いたプログラムを中断させ、その直後イベントBが起きた時用に書いたプログラムを流すようにしたいのですが、 プログラム初心者なものでよくわかりません。 どなたかご教授お願いいただけないでしょうか?!

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

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.1

★この場合はメッセージを処理します。 ・for 文のループの中で『ボタンB』を押すと WM_COMMAND などのメッセージがキューに入ります。 ・この情報を PeekMessage 関数で検査すれば for 文のループ途中でも強制終了可能な仕組みを組めます。 ・下に実装例を載せますので読み取って下さい。 ●実装例 static BOOL CALLBACK UserDialogProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) {  static BOOL swPushALoop; ←制御変数    switch ( uMsg ){   case WM_COMMAND:    switch ( LOWORD(wParam) ){     case IDC_PUSH_A: FuncPushA( hDlg, &swPushALoop ); break;     case IDC_PUSH_B: FuncPushB( hDlg, &swPushALoop ); break;     default:return( FALSE );    }    SetFocus( (HWND)lParam );    break;   default:return( FALSE );  }  return( TRUE ); } VOID FuncPushA( HWND hDlg, LPBOOL swLoop ) {  MSG Msg;  INT i;    *swLoop = TRUE; ←初期化    for ( i = 0 ; (i < 10000) && *swLoop ; i++ ){     :   ループ処理     :   while ( PeekMessage(&Msg,hDlg,0,0,PM_REMOVE) ){ ←ここがポイント    if ( !IsDialogMessage(hDlg,&Msg) ){     TranslateMessage( &Msg );     DispatchMessage( &Msg );    }   }  } } VOID FuncPushB( HWND hDlg, LPBOOL swLoop ) {  *swLoop = FALSE; ←強制終了    Sleep( 0 ); ←念のため挿入(なくてもOKかもね)    :  ボタンBの処理    : } 解説: ・『ボタンA』のループ(処理中)に『PeekMessage』で常にメッセージがキューに入っているかを監視します。 ・そして、何かメッセージがあった場合は UserDialogProc プロシージャにそのメッセージを処理する指示を  『DispatchMessage』関数で送ります。 ・こうすると『ボタンB』が押されたときに WM_COMMAND メッセージがキューという場所に格納されますから  『DispatchMessage』関数により UserDialogProc プロシージャが呼び出され、WM_COMMAND メッセージの  『IDC_PUSH_B』を即処理します。 ・すると『FuncPushB』関数が実行されますが、この関数の最初で『swLoop』という変数に FALSE をセットする  ので、ループ処理中の『FuncPushA』関数の『*swLoop』が FALSE になるので for 文を抜けます。 ・『IDC_PUSH_B』の先頭に『Sleep( 1 );』というウェイトを入れたのは『FuncPushB』関数が実行された後に  『FuncPushA』関数の for 文から抜けるまでの時間稼ぎで記述しなくても OK でしょう。 ・もしも、ループ処理を抜ける前に『ボタンBの処理』を開始出来ないのならば、安全の為に入れておきましょう。 ・以上。おわり。

参考URL:
http://www.sm.rim.or.jp/~shishido/mainloop.html
C-Disney
質問者

お礼

お返事が遅れてしまい、大変申し訳ございません! Oh-Orange様が教えていただいたことを、今までずっとあーでもない。こーでもないと私的に悪戦苦闘をしておりました。 そしてたった今・・・・、できることができましたぁ!!! とても感謝しております。 ご丁寧に教えていただき、本当にありがとうございました!!

その他の回答 (1)

  • kargon21
  • ベストアンサー率50% (1/2)
回答No.2

こんばんは。 他の方がC言語(?)で回答されているようなのでVBで回答してみます。 まず、for文の途中で他のイベントを受け取るには、 for文の処理中に一時的にWindowsに一瞬処理を返す必要があります。 これはDoEventsという命令をforループ内に追加することでできます。 次に処理を中断させる方法ですが、 グローバル変数で処理を抜けたかどうかを検査するための変数を用意し、 例えばこの変数がTrueの場合はBボタンがクリックされたとします。 コードは3つ追加する必要があります。 一つはforループ内(できれば最初の行)にこの変数の値をチェックする以下のような文を追加します。 (グローバル変数名をbolBClick(boolean)とします。) If bolBClick Then Exit For 次にBボタンがクリックされたときのイベント処理コードの先頭に次のコードを追加します。 bolBClick = True もうひとつ、同じイベント処理コードの最後に次のコードを追加します。 bolBClick = False 注意点として、各イベント処理のボリュームやタイミングによって若干処理が不安定になることも想定されるので、 シビアなタイミングを要求するような処理を実装されているのであればこの方法が使えないかもしれません。 必要であればループをDo文に変更してカウンタ変数を別途グローバル変数で用意し、 Bボタンクリック時の処理でカウンタを10000にしてしまうなどの工夫が必要かもしれません。

C-Disney
質問者

補足

迅速なご回答ありがとうございます! それなのにお返事が送れてしまい、真に申し訳ございません!!! 私の投稿した質問に書くのを忘れてしまいましたが、私はAPIでのプログラミングをおこなっております(謝) ですのでVBの方は・・・。 ですが、VBをやられている方たちは、kargon21様のご回答、絶対に役にたつとおもいます。 ご丁寧にご回答いただき、本当にありがとうございました!!

関連するQ&A

  • 特殊なfor文について

    SJC-P 問題集 問13の疑問より for文について教えてください。 一般的なfor文だと次の形だと思うのですが for(int i = 0; i < 5; i ++){ //5回ループする } Animal [] animals = { new Animal(), new Cow() }; for( Animal a : オブジェクト配列animals ){ a.saySomething(); } のような場合、このfor文は 「オブジェクト配列の中にanimalsがあるまでの間、ループする」という意味を指しているのでしょうか? for( クラス名 オブジェクト名 : オブジェクト配列) の一文にある「:」← の役割は何なのでしょうか?

    • ベストアンサー
    • Java
  • PHPのfor文とforeach文の使い方

    PHPのfor文とforeach文を使って、 ・果物の名前を4回繰り返す ・繰り返しの2回目と4回目は、"食べてください"という文字列を入れる という出力を返したいと考えています。 完成イメージは次のとおりです。 (1回目のループ) りんご ばなな ぶどう みかん (2回目のループ) 食べてください りんご ばなな ぶどう みかん (3回目のループ) りんご ばなな ぶどう みかん (4回目のループ) 食べてください りんご ばなな ぶどう みかん しかし自分が作成したプログラムでは、 次の2点について問題があります。 ・すべての繰り返しの前に"食べてください"が入ってしまう ・for文のループが止まらない 完成イメージの通りのプログラムにするためには、 どのように修正すればよろしいでしょうか? ご存知の方がいらっしゃいましたら、 ご教示願います。 ○質問の補足 自分が作成したプログラムは以下のとおりです。 for($i = 0; $i < 4; $i++) { if (($i = 1) || ($i = 3)) { echo "食べてください"; echo "</br>"; }; $fruits = array("りんご", "ばなな", "ぶどう", "みかん"); foreach ($fruits as $value) { echo $value; echo "</br>"; } } 以上、よろしくお願い申し上げます

    • ベストアンサー
    • PHP
  • VB For-Next文でのExitではなく中断は可能?

    初歩的な質問で申し訳ありません・・・ ループで処理しているものがあるのですが、ExitForでループを抜けることはできますが、途中で処理を中断して次のカウンタの処理へ移ることはできるのでしょうか? 例えば For i = 1 to 10   if 関数1() = False then     ■ループ処理を終了するのではなく次のカウンタ[i]に移りたい■   else     Call 関数2()   end if Next i という事をしたいと思っています。 今は For i = 1 to 10   ret = 関数1()   if ret = True then     Call 関数2()   end if Next i という方法で記述していますが、上記のような条件文が10や20もあると、IF文の入れ子入れ子でかなりコードが見にくいです・・・。 どなたかよろしくお願いします!

  • 簡単なfor文

    #include <stdio.h> int main(void) { int n; int i; for(n=0 ;n<10;n++){ for(i=0; i<=n ;i++){ printf("*"); } printf("\n"); } return(0); } こういったプログラムを実行すると、以下のように表示されるのですがなんででしょうか? * ** *** 以下略 自分の考えですと、*は毎回一つしか表示されずに改行されると思うのですが・・・ * * * * 以下略 i個分の*を表示するなどという指示をプログラムはなされていないと思うのですがなぜなんでしょうか? 一つ目のfor文では10回ループが繰り返され改行 二つ目のfor文で*を永遠に表示 といった僕の解釈ではおかしいですよね。 当方C言語初心者で、周りに聞く人がいないため教えていただけると非常に助かりますm(__)m

  • C#でスレッド実行中のイベントについて

    メインフォームの「処理開始ボタン」をクリックすると別スレッドが起動して、そのスレッド中で重たい処理をさせ、処理中に「中断ボタン」をクリックすると中断してアイドル状態に戻る様なプログラムについてですが、 先ず、Invokeを使わずに直接スレッドを起動すると期待通りの動作となり、Thread.Sleep()中でもボタンクリックのイベントが発生します。 しかし、Invokeとデリゲートを使ったスレッドを起動させるとスレッドの処理が終了するまでイベントが発生せず、行ったきり状態になってしまいます。 処理ループ内にAplication.DoEvent()を入れるとイベントが発生する様になりますが、Thread.Sleep()中はフリーズ状態となります。 Invokeを使ったスレッドでも、Invokeを使わない場合と同じ動作をさせる方法があれば教えて頂けないでしょうか。 どうぞ宜しくお願いします。

  • forを使わずにforeach文のみでループを回す

    ○質問の主旨 先日、下記の質問をしました。 PHPのfor文とforeach文の使い方 http://okwave.jp/qa/q8812443.html この例では,for文とforeach文を使って、 ・果物の名前を4回繰り返す ・繰り返しの2回目と4回目は、"食べてください"という文字列を入れる というプログラムを実現しています。 今回は同じ出力をするにあたって、 繰り返しはforeachのみで実現したいと考えています。 どのように修正すればよろしいでしょうか? ご存知の方がいらっしゃいましたら、 ご教示を願います。 ○質問の補足 このようなプログラムにしたいと考えています。 $fruits = array("りんご", "ばなな", "ぶどう", "みかん"); foreach ($fruits as $value) { // 果物の名前を4回繰り返して2回目と3回目は"食べてください"を入れる if (($i == 1) || ($i == 3)) { echo "食べてください"; echo "<br/>"; }; echo $value; echo "<br/>"; } 完成イメージはこんな感じです。 (1回目のループ) りんご ばなな ぶどう みかん (2回目のループ) 食べてください りんご ばなな ぶどう みかん (3回目のループ) りんご ばなな ぶどう みかん (4回目のループ) 食べてください りんご ばなな ぶどう みかん ○前回のプログラム for($i = 0; $i < 4; $i++) { if (($i == 1) || ($i == 3)) { echo "食べてください"; echo "<br/>"; }; $fruits = array("りんご", "ばなな", "ぶどう", "みかん"); foreach ($fruits as $value) { echo $value; echo "<br/>"; } }

    • ベストアンサー
    • PHP
  • if文の中にfor文なのか、for文の中にif文なのか

    for文の中に分岐を作って計算するのと、if文を先に書いてからfor文にするのとではどちらが一般的ですか? for ( i = 0; i < n; i++) { if ( a > b ) { y = i; } else { y = i * 2; } printf( "%d", y ); } とするか、 if ( a > b ) { for ( i = 0; i < n; i++) { y = i; } } else { for ( i = 0; i < n; i++) { y = i * 2; } } printf( "%d", y ); とするかという事です。 ちなみにプログラムは適当ですのでちょっとしたミスはご勘弁ください。 個人的には後者の方が分岐が少ない分負担は減ると思うのですが、前者の方がすっきりとしているのでこちらを使いたいのです。 もちろん、微々たる差なので好きな方を使えという意見もあると思いますが、皆さんはどちらを使いますか?

  • プログラムの二重のIF文、FOR文について

    プログラミングを始めたのですが、 クイックソートなどで出て来る、二重になったIF文とかFor文がイメージできなくて困っています。 エクセルでの何重かのIF文は問題なくこなせるのですが、 なぜかプログラムとなると自分でイメージして作り上げる自信はないです。 プログラマになるには、こういった多重ループを使えるようになるべきなのでしょうか? またそうだとしたら、どのような訓練をしたら分かるようになるでしょうか? それともプログラマに向いてないと諦めたほうがいいのでしょうか?

  • Excelでfor文とif文の操作をしたいです

    Excelについての質問です。 Excelで、画像のようにシート1のA列にアルファベットと数字のデータがあり(重複はありません)、B列に1~5の数字が入っているとします。 この時、シート2のB列に、シート2のA列で指定したものと一致する、シートAのB列の値を入力したいです。 (この例の場合、上から順に5、4、1です) プログラミング言語でいう、いわゆるfor文とif文の併用で for(i=1;i<4;i++){ for (j=1;j<8;j++){ if(シート1のセルAj==シート2のセルAi){   シート2のセルBiにシート1のセルBjを値を入れる   ループを抜ける } } } というような感じになると思います。(間違っていたら申し訳ないです。) こういった処理は、Excelのマクロで可能でしょうか? また、できればどうすれば実現できるか、教えていただけると助かります。 よろしくお願いいたします。

  • 入れ子になったfor文の初期化式について

    javascriptを勉強中の初心者です。 以下のスクリプトを見てください。 document.write("<p>"); outloop: for (var i = 1; i < 5; i++){ for (var j = 1; j < 5; j++){ document.write(i + " × " + j + " = " + (i * j) + "<br />"); if (i * j > 10){ break outloop; } } } document.write("</p>"); 5未満の数同士の乗算の結果を順に表示し 乗算の結果が10を超えたら外のループを抜けるというスクリプトです。 for文がこのように入れ子になっている場合、 内側のループが二週になるとjはまた初期化されて1になるのでしょうか? 手持ちの参考書にあるfor文の説明では『初期化式は初めの一回だけ実行される』とあります。 内側のループが二回目以降の時、参考書のいう『初めの一回』になると考えていいのでしょうか。 初歩的な質問で恐縮ですが、ご存知の方どうか教えてください。 よろしくお願いいたします。

専門家に質問してみよう