質問
C で typedef 列挙型の追加データを定義する最善の方法は何ですか?
例:
typedef enum {
kVizsla = 0,
kTerrier = 3,
kYellowLab = 10
} DogType;
次に、それぞれの名前を定義したいと思います。たとえば、 kVizsla
「ヴィズラ」である必要があります。現在、大きなスイッチブロックを使用して文字列を返す関数を使用しています。
解決
@dmckee:提案された解決策は良いと思いますが、単純なデータ(例:名前のみが必要な場合は、自動生成されたコードで拡張できます。コードを自動生成する方法はたくさんありますが、これと同じくらい単純なものであれば、列挙型の XML 表現を取り込んでコード ファイルを出力する単純な XSLT を作成できると思います。
XML は次の形式になります。
<EnumsDefinition>
<Enum name="DogType">
<Value name="Vizsla" value="0" />
<Value name="Terrier" value="3" />
<Value name="YellowLab" value="10" />
</Enum>
</EnumsDefinition>
結果のコードは、dmckee がソリューションで提案したものと似たものになります。
このような XSLT の記述方法については、試してみてください。 ここ または、Google で検索して、適切なチュートリアルを見つけてください。XSLT を書くのは私の個人的な意見ではそれほど楽しいものではありませんが、少なくともこのような比較的単純なタスクの場合は、それほど悪くありません。
他のヒント
にぴったりフィット X() マクロ. 。これらのタイプのマクロは、C プリプロセッサを使用して、同じソースから列挙型と配列を構築できます。X() マクロを含む #define に新しいデータを追加するだけです。
例は次のように記述できます。
// All dog data goes in this list
#define XDOGTYPE \
X(kVizsla,0,"vizsla") \
X(kTerrier,3,"terrier") \
X(kYellowLab,10,"yellowlab")
// Dog info
typedef struct {
int val; // Defined value
char * desc; // Text description
} DogType;
// Build an array index using the Names
typedef enum {
#define X(Name,Val,Text) Name,
XDOGTYPE
#undef X
MAXDOGS
} DogIndex;
// Build a lookup table of values
DogType Dog[] = {
#define X(Name,Val,Text) {Val,Text},
XDOGTYPE
#undef X
};
// Access the values
for (i=0; i < MAXDOGS; i++)
printf("%d: %s\n",Dog[i].val,Dog[i].desc);
列挙値が十分に密である場合は、文字列を保持する配列を定義し、それらを検索するだけです (スキップされた値には NULL を使用し、検索ルーチンに特別なケース ハンドラーを追加します)。
char *DogList[] = {
"vizsla", /* element 0 */
NULL,
NULL,
NULL,
"terrier", /* element 3 */
...
};
これは、疎な列挙の場合は非効率的です。
列挙が密でない場合でも、構造体の配列を使用してマッピングを保持できます。
typedef struct DogMaps {
DogType index;
char * name;
} DogMapt;
DogMapt DogMap[] = {
{kVizsla, "vizsla"},
{kTerrier, "terrier"},
{kYellowLab, "yellow lab"},
NULL
};
2 番目のアプローチは非常に柔軟ですが、データを使用する必要があるたびにマッピングを検索する必要があります。大きなデータ セットの場合は、配列の代わりに B ツリーまたはハッシュを検討してください。
どちらの方法も一般化して、より多くのデータを接続できます。1 つ目では構造体の配列を使用し、2 つ目では構造体にメンバーを追加するだけです。
もちろん、これらのデータ構造とのやり取りを簡素化するために、さまざまなハンドラーを作成することもできます。
@Hershi ぜひ、コードとデータを分離してください。上記の例は、機能的なものではなく、明確にすることを目的としています。
恥ずかしながら、私はその目的のために、あなたが示したような構造化された入力ではなく、空白で区切られたフラット ファイルをまだ使用していますが、私の運用コードは外部ソースから可能な限り多くのデータを読み取るつもりです。
ちょっと待って、コード生成のことを言っているのですね。
もちろん。それは何の問題もありません。
ただし、OP は生成されたコードがどのように見えるかに興味があったのではないかと思います...
これは自由回答の質問のようなものですが、1 つの提案は、キー タイプとして列挙型を使用し、値に追加情報を含むマップを使用することです。(例とは異なり、インデックスが連続的な場合は、マップの代わりにシーケンス コンテナーを使用できます)。