0

次のコードがあります

#define SWITCH(S) char *_S = S; if (0)
#define CASE(S) } else if (strcmp(_S, S) == 0) {switch(1) { case 1
#define BREAK }
#define DEFAULT } else {switch(1) { case 1

int main()
{
    char buf[256];

    printf("\nString - Enter your string: ");
    scanf ("%s", buf);

    SWITCH (buf) {
        CASE ("abcdef"):
            printf ("B1!\n");
            BREAK;
        CASE ("ghijkl"):
            printf ("C1!\n");
            BREAK;
        DEFAULT:
            printf ("D1!\n");
            BREAK;
    }
}

でプリプロセッサ コードを生成するとgcc -E、次のコードが得られます。

int main()
{
    char buf[256];

    printf("\nString - Enter your string: ");
    scanf ("%s", buf);

    char *_S = buf;
    if (0) {
    } else if (strcmp(_S, "abcdef") == 0) {switch(1) { case 1:
        printf ("B1!\n");
        };
    } else if (strcmp(_S, "ghijkl") == 0) {switch(1) { case 1:
        printf ("C1!\n");
        };
    } else {switch(1) { case 1:
        printf ("D1!\n");
        };
    }
}

しかし、一部の gccchar *_S = buf;では、コードの途中で定義するのはうまくいかず、コンパイル エラーが発生する可能性があります。

私のマクロでそれを修正する方法は?

char *_Sグローバルとして定義することを提案しないでください(外main)

4

3 に答える 3

8

マクロを完全に削除し、宣言を先頭に移動して「展開」した方法で記述します。これらのマクロは恐ろしいものです。

それができない場合は、微調整SWITCHして新しいスコープを導入します (a second {)。もちろん、これにより 2 つのスコープを閉じる必要があるためSWITCH_END、最後に使用する abomination を追加して、それをカプセル化します。なんでもいい。

于 2013-01-08T16:10:30.113 に答える
8

大野!!!

冗談でこの記事に書きました

使用しないでください。これは非常に恐ろしいことです。if-else を回避したい場合は、コンパイラを苦しめることなく実行できます。文字列のペアを使用することを検討してください。

#include <stdio.h>
#include <string.h>

int main(void)
{
    char buf[256];
    const char *ap[] = {
        "abcdef", "B1!\n",
        "ghijkl", "C1!\n",
        NULL    , "D1!\n",
    }, **p = ap;

    printf("\nString - Enter your string: ");
    scanf ("%s", buf);
    while (*p) {
        if (strcmp(buf, *p) == 0) break;
        p += 2;
    }
    printf("%s", *(++p));
    return 0;
}
于 2013-01-09T09:38:37.367 に答える
1

コードが C99 以降としてコンパイルされていることを確認してください。そうでない場合は、別の制御構造を使用する必要があります。

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L

  SWITCH(buf)
  {
    ...
  }

#else

  if (strcmp(buf, "abcdef") == 0)
  {
    ...
  }
  else if (strcmp (buf, "ghijkl") == 0)
  {
    ...
  }
  else
  {
    ...
  }

#endif

一般に、プリプロセッサを使用して C 構文を「変更」または拡張することはお勧めできません (それを証明するための傷跡があります)。switch理由により、文字列式では定義されていません。

この状況で本当にa を使用したい場合はswitch、各文字列のキーを返すハッシュ関数をコード化し、結果をオンにする方がよい場合があります。

#define ABCDEF ... // hash key generated for "abcdef"
#define GHIJKL ... // hash key generated for "ghijkl"
...
switch(hash(buf))
{
  case ABCDEF :
     ...
     break;

  case GHIJKL :
     ...
     break;

  default:
     ...
     break;
}
于 2013-01-08T16:30:32.027 に答える