内容
enumで処理を分岐するようなロジックが何度も出てくる場合、一つのswitch文で処理を行う方法
前提
方法としてポリモーフィズムやクラスを使用する方法もあるがC言語なのでそれを行わず変更する。
変更前
変更前のコード
#include <stdio.h>
// 列挙型の定義
enum Fruits {
RINGO, // 0
ORANGE, // 1
ICHIGO // 2
};
// 果物の名前を出力する関数
void printFruitName(enum Fruits fruit) {
switch (fruit) {
case RINGO:
printf("りんご");
break;
case ORANGE:
printf("オレンジ");
break;
case ICHIGO:
printf("イチゴ");
break;
default:
printf("不明な果物");
break;
}
}
// 「は」か「が」を出力する関数
void printParticle(enum Fruits fruit) {
switch (fruit) {
case RINGO:
case ORANGE:
printf("は");
break;
case ICHIGO:
printf("が");
break;
default:
printf("は");
break;
}
}
// 「うまい」か「まずい」を出力する関数
void printTaste(enum Fruits fruit) {
switch (fruit) {
case RINGO:
case ICHIGO:
printf("うまい\n");
break;
case ORANGE:
printf("まずい\n");
break;
default:
printf("不明な味\n");
break;
}
}
int main() {
// 各果物ごとに関数を呼び出して文字列を出力
printFruitName(RINGO);
printParticle(RINGO);
printTaste(RINGO);
return 0;
}
このプログラムは列挙体を元にさせたいロジックが異なるような場合を合している。具体的には
りんごはうまい」「オレンジはまずい」「イチゴがうまい」
という文字列を作り出すものになる。
列挙体を元にしたswitch文が3つも並んでいることになる。
これはたとえなので、全てにおいて別の処理を行なっていることを表現している。
変更後
#include <stdio.h>
// 名前を受け取って出力する関数
void printFruitName(char* name) {
printf("%s", name);
}
// 助詞を受け取って出力する関数
void printParticle(char* particle) {
printf("%s", particle);
}
// 味を受け取って出力する関数
void printTaste(char* taste) {
printf("%s\n", taste);
}
// りんごを処理する関数
void handleRingo(char* name, char* particle, char* taste) {
printFruitName(name);
printParticle(particle);
printTaste(taste);
}
// オレンジを処理する関数
void handleOrange(char* name, char* particle, char* taste) {
printFruitName(name);
printParticle(particle);
printTaste(taste);
}
// イチゴを処理する関数
void handleIchigo(char* name, char* particle, char* taste) {
printFruitName(name);
printParticle(particle);
printTaste(taste);
}
int main() {
enum Fruits fruit = RINGO; // ここで果物を指定
// switch文で果物を判定し、専用の処理関数を呼び出す
switch (fruit) {
case RINGO:
handleRingo("りんご", "は", "うまい");
break;
case ORANGE:
handleOrange("オレンジ", "は", "まずい");
break;
case ICHIGO:
handleIchigo("イチゴ", "が", "うまい");
break;
default:
printf("不明な果物です。\n");
break;
}
return 0;
}
ケースをmainに書き、それぞれリンゴの処理、オレンジの処理用の関数を作成。処理に必要な引数を持ちその中で処理を実行する。実行する処理については起こりうる条件を整理し、戻り値で選択できるようにする。
具体的には
void printFruitName(enum Fruits fruit) {
switch (fruit) {
case RINGO:
printf("りんご");
break;
case ORANGE:
printf("オレンジ");
break;
case ICHIGO:
printf("イチゴ");
break;
default:
printf("不明な果物");
break;
}
}
この場合りんごとオレンジとイチゴが起こりう条件であるため引数でそれを切り替えるようにする。
つまりこの場合は文字列を入力することなる。
void printFruitName(char* name) {
printf("%s", name);
}
他2つも同様に行う。
また、この部分は共通化し関数かできるが、ここでの文脈から言うとたまたま文字列の操作であるため共通できるだけです。本来であればリンゴの処理、オレンジの処理、それぞれで行いたい作業が異なることを想定していいます。
// りんごを処理する関数
void handleRingo(char* name, char* particle, char* taste) {
printFruitName(name);
printParticle(particle);
printTaste(taste);
}
// オレンジを処理する関数
void handleOrange(char* name, char* particle, char* taste) {
printFruitName(name);
printParticle(particle);
printTaste(taste);
}
// イチゴを処理する関数
void handleIchigo(char* name, char* particle, char* taste) {
printFruitName(name);
printParticle(particle);
printTaste(taste);
}
これによりmainでswitchを行い、果物ごとの独自のロジックを実行でき、ロジック自体は関数かしているため変更点も一つとなる。
// switch文で果物を判定し、専用の処理関数を呼び出す
switch (fruit) {
case RINGO:
handleRingo("りんご", "は", "うまい");
break;
case ORANGE:
handleOrange("オレンジ", "は", "まずい");
break;
case ICHIGO:
handleIchigo("イチゴ", "が", "うまい");
break;
default:
printf("不明な果物です。\n");
break;
}
以上、さよならswitch