3

特定のインターフェイスを調整しているときに、多くの#defines.

私が持っているのは次のようなものです:

#define STATUS_OK      0x00
#define STATUS_FAIL    0x01
#define STATUS_WAIT    0x02
#define STATUS_ILLEGAL 0x03
#define STATUS_FULL    0x04
...

このような定義はたくさんありますが、すべてを書く必要がなかったので、とても満足しています。

ただし、や などの代わりに他のステートメントをうまく使用できますがswitch、今は逆の方向にしたいと考えています。if0x00

そこで、0x00識別子「STATUS_OK」を出力したいと思います。

私の知る限り、これは不可能ですが、可能にするための良い回避策は何ですか?! 次のような配列をセットアップすることは可能でしょうか。

arrayNames[STATUS_OK] = _STATUS_OK_

どこで解決され、「 STATUS_OK 」に解決されますSTATUS_OK0x00?_STATUS_OK_

さらに、これを行うために可能な限り少ないメモリを使用するソリューションを探しています。

これは私ができるようにしたいことです:

prinf("%s",resolve(0x00));
-> "STATUS_OK"

私が探しているものを明確にしたことを願っています。

編集:

迅速で有用な回答をありがとうございました。私は Larsmans のソリューションを使用し、それを qrdl のソリューションと組み合わせようとするかもしれません。しばらく時間がかかる場合があります。完了したら、この編集を置き換えます。

4

6 に答える 6

3

小さなマクロウィザードとプリプロセッサの文字列化演算子を使用てそれを行うことができます。見てください:

#include <stdio.h>
#define STATUS_OK 0x05
#define STATUS_BAD 0x09
#define LOOKUP_CASE(x) case x: return #x

const char *lookup_name(int val) {
    switch(val) {
        LOOKUP_CASE(STATUS_OK);
        LOOKUP_CASE(STATUS_BAD);
        default: return "<UNDEFINED>";
    }
    return NULL;
}

int main(void) {
    printf("%s\n", lookup_name(STATUS_OK));
    printf("%s\n", lookup_name(STATUS_BAD));
    return 0;
}

LOOKUP_CASEこの例は、マクロを除いて自明です。演算子を使用して、そのオペランドに対応する文字列定数を生成し、 -d定数#の名前を2回繰り返さないようにします。#define

これは、この実例を使用したideoneへのリンクです。

于 2012-11-22T17:36:44.833 に答える
2

X-Macrosを使用しますが、元のヘッダーファイルを変更する必要があります

于 2012-11-22T17:00:18.270 に答える
1

あなたはこのようなことをすることができます:

const char *status_str(int s)
{
    switch(s)
    {
        case STATUS_OK:
            return "STATUS_OK";
        /* And so on and so forth */
    }
}
于 2012-11-22T16:59:25.497 に答える
1

その値から識別子の名前を取得することはできません。識別子は前処理後に使用できなくなり、コンパイラはそれらについての知識を持たないためです。

ただし、それらの名前を配列またはそれに類似した他のトリックに格納することを試みることができます。

于 2012-11-22T16:59:44.010 に答える
1

簡単な解決策の1つは、2つの非常に単純なコードジェネレーターを作成することです。識別子を単純な形式のテキストファイルに保存する場合

identifier value

例えば

STATUS_OK      0x00
STATUS_FAIL    0x01

次に、2つの単純なAwkスクリプトで、とのヘッダーと、#definesそこからの文字列を含むCモジュールを生成できます。ヘッダーの場合:

BEGIN {
   print("#ifndef _STATUSCODES_H");
   print("#define _STATUSCODES_H");
}

{ printf("#define %s %s\n", $1, $2) }

END { print("#endif"); }

文字列にマッピングする場合:

BEGIN {
    print("#include \"statuscodes.h\"");
    print("char const *status_string(int status)");
    print("{");
    print("    switch (status) {");
}

{ printf("      case %s: \"%s\"\n", $2, $1); }

END {
    print("    }");
    print("}");
}

次にMakefile、識別子のテーブルが変更されたときにモジュールとヘッダーを生成します。

于 2012-11-22T17:00:12.703 に答える
1

switchすべての値をチェックしたり、名前の完全なリストを作成したりしないと、問題の解決策はないと思います。

char *s_names[] = {
    "STATUS_OK",
    "STATUS_FAIL",
    ...
}

これで、インデックス (エラー コード) で簡単に文字列にアクセスできるようになりました。

printf("%s", s_names[0x00]);      // prints "STATUS_OK"
printf("%s", s_names[STATUS_OK]); // prints "STATUS_OK" too

これは、値 (またはマクロ) がある場合に機能しますが、リスト全体のために多くのスペースを無駄にしたくない場合は、次のマクロを使用できます。

#define MACRO_TO_STRING(x) #x

これで、マクロを文字列に変換できますが、値を文字列に変換することはできません。

printf("%s", MACRO_TO_STRING(STATUS_OK)); // prints "STATUS_OK"
printf("%s", MACRO_TO_STRING(0x00));      // but this doesn't work: prints "0x00"
于 2012-11-22T17:30:48.050 に答える