switchでループを抜ける方法

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Lawliet
記事: 12
登録日時: 10年前

switchでループを抜ける方法

#1

投稿記事 by Lawliet » 10年前

例えばwhile文で無限ループをしている時にif文でbreakすれば抜けられますが、
switch文をつかったときはbreakでも抜けられないですよね。

そんな時はフラグを使うなんていう手も思いつきますが
みなさんはこういう時には他にどういう手段を持って乗り越えていますか?

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: switchでループを抜ける方法

#2

投稿記事 by みけCAT » 10年前

言語が指定されていませんね。
Javaなら抜けたいwhile文の前に"ラベル名:"と書いておき、その中で"break さっきのラベル名;"と書くと、
「抜けたいwhile文」を抜けられます。

コード:

import java.util.*;
import java.lang.*;

class Main
{
    public static void main (String[] args) throws java.lang.Exception
    {
        int i=0;
        hoge: while(true) {
            switch(i) {
                case 0:
                    System.out.println("Ishida Akira");
                    break;
                case 1:
                    System.out.println("Miyata Koki");
                    break;
                case 2:
                    System.out.println("Yamaguchi Kape");
                    break;
                case 3:
                    System.out.println("Toriumi Kosuke");
                    break;
                case 4:
                    System.out.println("Sawashiro Miyuki");
                    break;
                case 5:
                    System.out.println("Ogata Megumi");
                    break;
                default:
                    break hoge;
            }
            i++;
        }
    }
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Lawliet
記事: 12
登録日時: 10年前

Re: switchでループを抜ける方法

#3

投稿記事 by Lawliet » 10年前

すいません。C言語です。このサイトも一応「C言語なんでも質問掲示板」でしたので
言語指定がない場合はデフォルトでC言語みたいなものだと勝手に思いこんでいました。

ソースで書くとこんなイメージです。

コード:

while( 1 ){
	if( ... ){
		break;	//脱出できるよ(^O^)/
	}
}

コード:

while( 1 ){
	switch( ... ){
		case /*終了したい値*/:
			break;	//脱出できない(TдT)
	}
} 

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: switchでループを抜ける方法

#4

投稿記事 by h2so5 » 10年前

僕はあまり使わないですけどgotoを使うとか...

コード:

    while( 1 ){
        switch( ... ){
            case /*終了したい値*/:
                goto endloop;
        }
    }
    endloop:

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: switchでループを抜ける方法

#5

投稿記事 by みけCAT » 10年前

ただ、

コード:

endloop:
}
のようにラベルのあと即ブロックを終了するとエラーを吐かれるので、

コード:

endloop: ;
}
として回避します。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Lawliet
記事: 12
登録日時: 10年前

Re: switchでループを抜ける方法

#6

投稿記事 by Lawliet » 10年前

やっぱりC言語ではフラグを使ったりgotoを使ったりするしかないのでしょうか

何か他に裏技的な何かみたいなものはないものでしょうか?

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: switchでループを抜ける方法

#7

投稿記事 by みけCAT » 10年前

関数にしてreturnとかでしょうか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Lawliet
記事: 12
登録日時: 10年前

Re: switchでループを抜ける方法

#8

投稿記事 by Lawliet » 10年前

関数ですか、その発想はなかったです。

C言語にもさっきあげてくださったJAVAのような機能はないですよね・・・
と言うかそのJAVAもgotoと似たような機能ですが

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: switchでループを抜ける方法

#9

投稿記事 by softya(ソフト屋) » 10年前

分かりやすくないと意味が無いので、gotoで抜けるかreturnで抜けた方が素直で追いかけやすいと思います。フラグは、ややこしくなったり関数が長くなりがちです。
裏技的なのは大体トリッキーなので避けないとひどい目に合いそうです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Lawliet
記事: 12
登録日時: 10年前

Re: switchでループを抜ける方法

#10

投稿記事 by Lawliet » 10年前

確かに裏ワザにこだわって可読性が低下したら本末転倒ですもんね。

今まではフラグしか使って来なかったのでreturnというのは新鮮でした。

しかしどうにもgotoはつかってはいけないというイメージが僕の中では強いんですが
みなさんはどういう状況に陥った時にgotoを使いますか?
それとも、意地でもgotoは使いませんか?

アバター
usao
記事: 1887
登録日時: 11年前

Re: switchでループを抜ける方法

#11

投稿記事 by usao » 10年前

無限ループ+switch という状況が割とレアな気もしますが
そういったものを書くとしたら大抵関数化していると思うので普通にreturnです.
 ↓ どうしても関数化したくない場合
gotoは,一人で趣味で書いていてそのコードを読むのも触るのも自分だけ ということがわかっていて
且つ,今回のようなループ抜けのために限って ならば使うかもしれません.
そうでないならば たとえ見栄えが少々悪くなっても フラグを用意します.

コード:

//面倒だからifとswitchのハイブリッドで解決だ!…なんちゃって.
while(1)
{
    if( XXX )
    {//wihleを抜ける処理はこっち
        break;
    }
    else
    {//それ以外はこっち
        switch( ... )
        {
        }
    }
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: switchでループを抜ける方法

#12

投稿記事 by softya(ソフト屋) » 10年前

flagがない方式の方が最終的には経験上バグにはなりづらいと思うので、私は分かりやすい抜け出しgotoなら仕事でも絶対拒否とは言いません。
ただ、私なら大抵はreturnに成る組み方にするか、処理テーブル方式にしているみたいで、error処理goto以外は無意識には避けている様です。なので、まずそういう状況にならないんですよね。つまり、switchでループ抜けするコードを書く状況が発生しないんです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Lawliet
記事: 12
登録日時: 10年前

Re: switchでループを抜ける方法

#13

投稿記事 by Lawliet » 10年前

ただ、私なら大抵はreturnに成る組み方にするか、処理テーブル方式にしているみたいで、error処理goto以外は無意識には避けている様です。
あの、すいません。returnは分かるんですが処理テーブル方式ってどういうことでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: switchでループを抜ける方法

#14

投稿記事 by softya(ソフト屋) » 10年前

処理テーブル方式は、わざわざフラグを立てなくてもテーブル自体がフラグやら状態のような役目を持つのでループを抜けるという状態をテーブルが持っていれば良いという話です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Lawliet
記事: 12
登録日時: 10年前

Re: switchでループを抜ける方法

#15

投稿記事 by Lawliet » 10年前

softya(ソフト屋) さんが書きました:処理テーブル方式は、わざわざフラグを立てなくてもテーブル自体がフラグやら状態のような役目を持つのでループを抜けるという状態をテーブルが持っていれば良いという話です。
すみません。少し難しくてよくわからないです。
例えばコードでしたらどういった書き方が処理テーブル方式に当たるのでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: switchでループを抜ける方法

#16

投稿記事 by softya(ソフト屋) » 10年前

switchで数値でcase分岐しますが、その数値をインデックスに使い構造体配列にアクセスして動作を決めるということです。

そうですね。こんな感じなら、そもそもswitchの出番がないと言った感じでしょう。

コード:

typedef struct {
	int bEnd;
	int ofsx;
	int ofsy;
} sw_t;

#define MAX_PATTERN 3
sw_t sw_array[MAX_PATTERN] = {
	{0,10,0}
	{0,-10,0}
	{1}
};

	while( 1 ) {
		if( sw_array[xx].bEnd ) {
			break;//ループ抜け
		}
		
		int bx= ax + sw_array[xx].ofsx;
		int by= ay + sw_array[xx].ofsy;
		
	}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: switchでループを抜ける方法

#17

投稿記事 by softya(ソフト屋) » 10年前

そうですね。
後思いついたのは、条件が多くない前提なら下記のように書くのも手ですよね。

コード:

	while( 1 ) {
		if( sw==1 ) {
			
		} else if( sw==2 ) {
			
		} else if( sw==3 ) {
			break; //ループを抜ける。
		}
	}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Lawliet
記事: 12
登録日時: 10年前

Re: switchでループを抜ける方法

#18

投稿記事 by Lawliet » 10年前

なるほど、こういうことだったのですね。

状況によってだとは思いますがこの処理テーブル方式ではコードが大きくなってくると見難くなりますよね。(パターンの数とか)
そうなってくるとやはりコードを書く頻度というのは
return方式 >  処理テーブル方式
となるのでしょうか?

それともコードが醜くなるといったことはないのでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: switchでループを抜ける方法

#19

投稿記事 by softya(ソフト屋) » 10年前

>状況によってだとは思いますがこの処理テーブル方式ではコードが大きくなってくると見難くなりますよね。(パターンの数とか)

そうですか? 制御文で条件分けしなくて良いので大抵はコードがスッキリします。
テーブルの定義は表形式に近くなるので、Excelの表が見やすいのと同じです。

>そうなってくるとやはりコードを書く頻度というのは
>return方式 >  処理テーブル方式
>となるのでしょうか?

ケースバイケースなので何とも言えません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
usao
記事: 1887
登録日時: 11年前

Re: switchでループを抜ける方法

#20

投稿記事 by usao » 10年前

そのswitchによる分岐がどれだけのことをやっているのか,次第だと思います.

swtichでやってることが「ちょっとしたこと」であって,
少数のパターンしかなく,分岐後の処理も2~3行程度のコードで済む程度……とかであればif~elseで良いわけだし,
テーブルで済ませられるならそうすればいいし.

例えばswitchがやってることが
プログラムの状態に関わる大きな流れの制御だったりする場合,
Cなら関数ポインタ,C++ならStateパターンみたいなのを使うような場面かもしれませんし.

コード:

//関数ポインタで処理分岐
int (*pCurrStateFunc)() = InitStateFunc;

int InitStateFunc()
{
    ...
    //状態遷移
    if( XXX ){  pCurrStateFunc = StateFunc1;  }
    else if( YYY ){  pCurrStateFunc = StateFunc2;  }
    ...
    return 1;
}
int StateFunc1(){ ... }
int StateFunc2(){ ... }

//---while の部分
int main()
{
    while( 1 )  //メインループ
    {
        ...
        //アプリの現状態に合わせた処理を行う
        if( pCurrStateFunc() == 0 )break;  //※例えば戻り値でループを抜ける判断ができる決まりにしておく
    }
    ...

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: switchでループを抜ける方法

#21

投稿記事 by ISLe » 10年前

ある程度大きいものなら、関数ポインタで関数呼び出したり、基底クラスのポインタから仮想関数呼び出したりしますから、そもそもswicth使いませんね。
メインループでswitch使って状態による分岐、なんてのは初心者向けのコードなわけで。

switchからループを抜ける状況というのは、十分小さいコードであるはずなのでgoto使っても問題ない気もします。


データテーブルはそもそも手で書かないことも多いですが、マクロ使って読みやすくすることも多いと思います。

コード:

#define MOVE(x, y) { 0, x, y }
#define END { 1 }
sw_t sw_array[MAX_PATTERN] = {
    MOVE(10,0),
    MOVE(-10,0),
    END
};

Lawliet
記事: 12
登録日時: 10年前

Re: switchでループを抜ける方法

#22

投稿記事 by Lawliet » 10年前

すいません。関数ポインタやクラスはまだ全然知らないのでぼくは何も言えません。

なのでこのへんでまとめにさせてもらいます。
*C言語で 無限ループ+switch を脱出する方法*
  1. フラグ
  2. goto文
  3. 関数化してreturn
  4. 処理テーブル方式
  5. 連続でif else
と教えて頂きました。
(僕の知識が足りない部分は不適切になると思い書きませんでした)

そもそも 無限ループ+switch文 というのがアレ とのご指摘も頂きました。

皆様、数多くの内容の濃い回答をありがとうございました。
最後に編集したユーザー Lawliet on 2013年7月29日(月) 17:53 [ 編集 1 回目 ]

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: switchでループを抜ける方法

#23

投稿記事 by softya(ソフト屋) » 10年前

連続if else が抜けてますよ。 → No: 17
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Lawliet
記事: 12
登録日時: 10年前

Re: switchでループを抜ける方法

#24

投稿記事 by Lawliet » 10年前

すいません。編集しときました。

閉鎖

“C言語何でも質問掲示板” へ戻る