4-3 switch文

この記事は約6分で読めます。

3通り以上の処理

if文を使うと条件が真の時と偽の時の二通りに処理を分けることができます。if文は入れ子にすることができるので、if文を組み合わせて3通り以上に分岐することができます。

//サンプルコード1
#include <stdio.h>
int main(void){
	int a;
	puts("正の整数を入力してください。");
	scanf("%d",&a);
	if (a<10){
		puts("a:1桁");
	}else{
		if (a<100){
			puts("a:2桁");
		}else{
			if (a<1000){
				puts("a:3桁");
			}else{
				if (a<10000){
					puts("a:4桁");
				}else{
					puts("a:5桁以上");
				}
			}
		}
	}
	return 0;
}
//サンプルコード2
#include <stdio.h>
int main(void){
	int a;
	puts("正の整数を入力してください。");
	scanf("%d",&a);
	if (a<10) puts("a:1桁");
	else if (a<100) puts("a:2桁");
	else if (a<1000) puts("a:3桁");
	else if (a<10000) puts("a:4桁");
	else puts("a:5桁以上");
	return 0;
}

実行結果

正の整数を入力してください。
550
a:3桁

サンプルコード1ではif文のelseブロックにif文を入れ子にして、合計5通りに分岐しています。サンプルコード1を中カッコを使わず書き直したものがサンプルコード2です。以下にサンプルコード1のif文の構造をフローチャートにして示します。

switch文

if文を何重にも使って複数に分岐することも可能ですが、switch文を利用すると簡潔に書くことができます。

switch (式){
	case 値1:{
		処理;
		break;
	}
	case 値2:{
		処理;
		break;
	}
	dedault:{
		処理;
		break;
	}
}

switch文では式を評価して、その値が一致するラベルにジャンプします。ラベルとは、caseの後に書いてある値1:や値2:のことです。もちろんcase文とラベルは3つ以上書くこともできます。式の値がどのラベルとも一致しない場合はdefaultラベルにジャンプします。defaultラベルはなくても構いません。case文およびdefault文の処理の最後にはbreak;をつけます。breakはここではswitch文全体から抜け出し、次の処理に移るという意味です。

#include <stdio.h>
int main(void){
	int a;
	puts("1:グー 2:チョキ 3:パー");
	puts("1から3までの数字を入力してください。");
	scanf("%d",&a);
	switch (a){
		case 1:{
			puts("あなたはグーを選びました。");
			break;
		}
		case 2:{
			puts("あなたはチョキを選びました。");
			break;
		}
		case 3:{
			puts("あなたはパーを選びました。");
			break;
		}
		default:{
			puts("1から3までの数字ではありません。");

			break;
		}
	}
	return 0;
}

実行結果1

1:グー 2:チョキ 3:パー
1から3までの数字を入力してください。
2
あなたはチョキを選びました。

実行結果2

1:グー 2:チョキ 3:パー
1から3までの数字を入力してください。
5
1から3までの数字ではありません。

breakを省略する

case文の最後にbreak;をつけると書きましたが、実は書かないことも可能です。breakはswitch文から抜け出すという意味でしたが、break;がないと何が起こるのか見てみましょう。

#include <stdio.h>
int main(void){
	int a;
	puts("1:グー 2:チョキ 3:パー");
	puts("1から3までの数字を入力してください。");
	scanf("%d",&a);
	switch (a){
		case 1:{
			puts("あなたはグーを選びました。");
		}
		case 2:{
			puts("あなたはチョキを選びました。");
		}
		case 3:{
			puts("あなたはパーを選びました。");
		}
		default:{
			puts("1から3までの数字ではありません。");
		}
	}
	return 0;
}

実行結果1

1:グー 2:チョキ 3:パー
1から3までの数字を入力してください。
2
あなたはチョキを選びました。
あなたはパーを選びました。
1から3までの数字ではありません。

実行結果2

1:グー 2:チョキ 3:パー
1から3までの数字を入力してください。
0
1から3までの数字ではありません。

どのcaseラベルにも一致しない値を入力するとdefaultブロックの文が実行されます。しかし2を入力するとcase2の文が実行された後、case3及びdefault文も実行されます。これは、switch文は式の値と等しいラベルにジャンプするという機能しかないからです。この例ではcase2のラベルへジャンプした後そのままcase2の次のラベルのプログラムも実行されます。これを防ぐためにbreak;を書きます。

複数のラベルをまとめる

各ラベルの後に必ずしも文を書く必要はありません。具体的には、case 値1:のあとにcase 値2:を書くことができます。こうすると、条件式の値が値1のとき、値2のときの処理を共通化できます。

#include <stdio.h>
int main(void){
	int a;
	puts("1から9までの数字を入力してください。");
	scanf("%d",&a);
	printf("%dは",a);
	switch (a){
		case 2:
		case 3:
		case 5:
		case 7{
			puts("素数");
			break;
		}
		case 1:
		case 4:
		case 9:{
			puts("平方数");
		}
		case 6:
		case 8:{
			puts("素数ではない");
			break;
		}
		default:{
			puts("1から9までの数字ではありません。");
		}
	}
	return 0;
}

実行結果1

1から9までの数字を入力してください。
3
3は素数

実行結果2

1から9までの数字を入力してください。
4
4は平方数
素数ではない

このプログラムではaの値が2,3,5,7のとき、1,4,9のとき、6,8のときそれぞれ同じ処理になります。1,4,9のときputs(“平方数”);が実行された後puts(“素数ではない”);も実行されます。

まとめ

いくつもの値と比較したい場合は、if文を入れ子にするよりswitch文を使用すると便利である。

ただし、switch文は値の比較しかできず、<や>などの値の大小を比較する演算子は使用できない。

switch文では、複数のラベルにおいて処理をまとめることができる。

switch文を使用するときは、break文の書き忘れに注意。

コメント