2009-04-03 4 views
35

Cでは、列挙型の要素の数を追跡する良い方法はありますか?私は見た列挙型の要素の数

enum blah { 
    FIRST, 
    SECOND, 
    THIRD, 
    LAST 
}; 

しかし、これは、項目が連続しており、ゼロから始まる場合にのみ動作します。

+0

Adaの 'enum'のようなC++の[' enum']の質問を参照してください(http:// stackoverflow。com/questions/300592/enum-in-c-like-enum-in-ada) –

答えて

32

私はそこにいるとは思わない。しかし、あなたがシーケンシャルでない場合、あなたはそのような番号で何をしますか?あなたはまだそれらのリストをどこかに持っていませんか?彼らはシーケンシャルであるが、異なる数で開始した場合と、あなたは常に行うことができます:

enum blah { 
    FIRST = 128, 
    SECOND, 
    THIRD, 
    END 
}; 
const int blah_count = END - FIRST; 
+0

は、列挙型が負である可能性がありますか?もしそうなら、これで気をつけてください。 – ojblass

+0

FIRST = -2でも正しく計算されると思います:1 - (-2)= 3 – paxdiablo

+2

注意する必要はありません。減算は負の数では問題ありません。パックスはそれが正しいです。 –

6

残念ながら、存在しない。

3

列挙型は、実行時に変更することはできませんので、まあ、あなたができる最善のことは、次のとおりです。

enum blah { 
    FIRST = 7, 
    SECOND = 15, 
    THIRD = 9, 
    LAST = 12 
}; 
#define blahcount 4 /* counted manually, keep these in sync */ 

しかし、その情報が役立つ状況を想定するのは難しいと思います。あなたは正確に何をしようとしていますか?

+1

はい、なぜそれをしたいと思いますか? – ojblass

+2

私は、列挙型の値を配列にランダムに割り当てたいという状況があります。どれくらいの異なる値があるかを知る必要があるので、適切な範囲を得ることができます。 – anthropomorphic

2
int enaumVals[] = 
{ 
FIRST, 
SECOND, 
THIRD, 
LAST 
}; 

#define NUM_ENUMS sizeof(enaumVals)/sizeof (int); 
+7

これは純粋のsizeofの使用を許可するために、配列全体のenumを繰り返す必要のようです - Cサイズで4 –

+1

は、コンパイル時に計算だけの#define COUNTよりも、私には多くの努力のように見えます。 C言語はインタプリタ言語ではないため、この方法は修正定義を使用するのと同じくらい効率的であり、メンテナンスが簡単です。 – Fulup

55

あなたが列挙型を割り当てない場合は、このような代を行うことができます。

enum MyType { 
    Type1, 
    Type2, 
    Type3, 
    NumberOfTypes 
} 

NumberOfTypesは本当の種類の数である3と評価されます。

+2

良いトリック!シーケンシャルエニュームのための最も簡単なものです。 –

+1

いつでもすべてのC実装で、常にenumが0から始まることを確認できますか?私はそう思うが、それは本当に本当ですか? – JohnyTex

17

古い質問、私は知っています。これは同じ質問のgooglerのためのものです。

あなたはX-Macros

例を使用することができます。

//The values are defined via a map which calls a given macro which is defined later 
#define ENUM_MAP(X) \ 
     X(VALA, 0) \ 
     X(VALB, 10) \ 
     X(VALC, 20) 

//Using the map for the enum decl 
#define X(n, v) [n] = v, 
typedef enum val_list { 
    ENUM_MAP(X) //results in [VALA] = 0, etc... 
} val_list; 
#undef X 

//For the count of values 
#define X(n, v) + 1 
int val_list_count = 0 + ENUM_MAP(X); //evaluates to 0 + 1 + 1 + 1 
#undef X 

これはまた、IDEに透明であるので、(そのすべてが事前にプロセッサに行われるように)自動完了が正常に動作します。

+1

X_MACROの要素の数を判断する良い方法を探していたので、実際にここに来ました。これは良い方法です。また、単に ' – BeeOnRope

+0

THIRD')があり、最後は常にリストの最後を指定するプレースホルダーであるため、追加アイテムが追加された場合、アイテム数の計算式を変更する必要はありません。 –

5

私はこれが非常に古い質問であることを知っていますが、受け入れられた答えが間違っているので、私は自分自身を投稿するように強制されます。私は受け入れられた答えの例を若干修正して再利用します。 (列挙型がシーケンシャルであるという仮定を作る。)

// Incorrect code, do not use! 
enum blah { 
    FIRST = 0, 
    SECOND, // 1 
    THIRD, // 2 
    END  // 3 
}; 
const int blah_count = END - FIRST; 
// And this above would be 3 - 0 = 3, although there actually are 4 items. 

どれ開発者はその理由を知っている:count = last - first + 1を。 これは記号(両端が負、両方とも正、または最初の最後が負である)の任意の組み合わせで機能します。あなたが試すことができます。

// Now, the correct version. 
enum blah { 
    FIRST = 0, 
    SECOND, // 1 
    THIRD, // 2 
    END  // 3 
}; 
const int blah_count = END - FIRST + 1; // 4 

編集:もう一度テキストを読むと、疑問があります。そのENDは提供されたアイテムの一部ではないという意味ですか?それは私には奇妙に見えますが、よく、私はそれが意味をなすことができると思います...

+1

意図が列挙3つの要素(' FIRST、SECOND&があることである([0]はsizeof val_list /はsizeof val_list) 'イディオムを使用して' val_list'配列内の要素の数を取ることができる –

+0

ええ、それは私が数時間後に再び読んだときに思ったことです。確認していただきありがとうございます。 「使用されることを意味しない」と言われる「END」の隣には、コードを理解するのに役立つコメントがあります。 –

+0

私は "blah_end_marker"のようなものを使うのが好きです。 "end_marker"は目的を識別し、接頭辞は最後のマーカーを区別します。カウントを定義するか、0から始まる "逐次"列挙型の場合は、マーカー値を直接使用します(たとえば、 "blah all_blahs [blah_end_marker];") - しかし、const int blah_countがより意味をなさないと思っています... – Bob

-2

はこれを試してみてください:

enter image description here

それは醜いですし、それを好きではないいくつかのコンパイラがあるかもしれません、しかし、通常は効果的です。すべての列挙型で使用できます。

+3

あなたのコードをイメージではなく書式付きのテキストとして含めるようにしてください。コピー、貼り付け、検索が便利です。 –

0
#include <stdio.h> 

// M_CONC and M_CONC_ come from https://stackoverflow.com/a/14804003/7067195 
#define M_CONC(A, B) M_CONC_(A, B) 
#define M_CONC_(A, B) A##B 

#define enum_count_suffix _count 
#define count(tag) M_CONC(tag, enum_count_suffix) 
#define countable_enum(tag, ...) \ 
    enum tag {__VA_ARGS__}; \ 
    const size_t count(tag) = sizeof((int []) {__VA_ARGS__})/sizeof(int) 

// The following declares an enum with tag `color` and 3 constants: `red`, 
// `green`, and `blue`. 
countable_enum(color, red, green, blue); 

int main(int argc, char **argv) { 
    // The following prints 3, as expected. 
    printf("number of elements in enum: %d\n", count(color)); 
}