switch 構文はケース ラベルの変数を受け入れませんが、単純な古い if-else 比較の代わりに同様の操作を実行する回避策はありますか?
4 に答える
通常、これを回避するには、if を 1 つだけ指定して、構造体と関数のポインターを使用します。
私が話していることを理解するためだけに、テストされていない例:
#include "cases_functions.h"
typedef struct s_switch
{
char* value;
void (*do)(void);
} t_switch;
t_switch cases[] =
{
{"add", add},
{"sub", sub},
{"divide", div},
{0, 0}
};
void personal_switch(char *what)
{
int i = 0;
while (cases[i].value)
{
if (strcmp(cases[i].value, what) == 0)
cases[i].do();
i++;
}
}
これにより、実行時にさまざまなケースを変更したり、新しいケースを追加したりできます...もちろん、選択方法は無料で、たとえばint
and でテストし==
たり、より複雑なものを使用したりできます。
列挙型を使用できます。
enum my_enum {
element1,
element2
};
my_enum var;
switch(var)
{
case element1:
case element2:
}
たとえば、曜日ごとに便利です
私の経験では、これを行う最善の方法はルックアップ テーブルを使用することです。
単純にすることができます。これは、インデックス ルックアップ テーブルになります。これは int でのみ機能し、隣接する int 0 -> n のみで機能します。
または、複雑な実装である汎用にすることもできますが、任意の形式の「ケース」を使用することができます。それらは隣接する整数である必要はなく、整数である必要さえありません (浮動小数点数、文字列、何でもかまいません)。
一般的なバージョンの例を示します (テストされていません)。この例では二分探索を使用しているため、アクセス時間は決定論的であり、ケース数が多い場合に最適です。
// declare a custom search key for the foo object, could be any type
typedef int foo_key_t;
// declare the actual data object:
typedef void(*foo_func_t)(void);
typedef enum
{
const foo_key_t key;
foo_func_t foo_func; // things to do when this "case" is found
} foo_t;
// a comparison function for objects of type foo_t
int foo_comp (const void* obj1, const void* obj2)
{
const foo_t* f1 = obj1;
const foo_t* f2 = obj2;
return f1->key - f2->key;
}
---
// declare a "good to have" enum with a list of indices
// indices are guaranteed to be adjacent numbers 0 -> n
typedef enum
{
FOO_FOO,
FOO_BAR
FOO_N // number of items in this enum
} foo_index_t;
// define a list of variables corresponding to the above enum
const foo_t foo [FOO_N] = // a list sorted in adjacent search key order:
{
{ 123, &foo_func },
{ 456, &bar_func }
};
---
const foo_t* result;
result = bsearch(456, // search for this "case"
foo, // in the table foo
FOO_N, // with this many objects
sizeof(foo_t), // with this object size
foo_comp); // use this comparison function
if(result != NULL)
{
result.foo_func();
}
else
{
// this equals "default" in a switch-case.
}
「ラベル」が定数の場合、マクロを定義できます...
#define FOO 1
#define BAR(x) (2*x)
switch (var)
{
case FOO: // foo
case BAR(3): // bar
}
たぶん、あなたが望むものを得るためにいくつかの奇妙なマクロを定義することができますが、単純な if-else-if チェーンを書く方が簡単です.本当に必要でなければ、複雑なマクロを書いて使うのは良い考えではないと思います.彼ら。