【问题标题】:C (Preprocessor): How to concatenate/append substitution stringC(预处理器):如何连接/附加替换字符串
【发布时间】:2015-07-08 13:12:08
【问题描述】:

我在命令行上定义我的例外:

-DEXCEPTION_1=\"first\" -DEXCEPTION_2=\"second\" -DEXCEPTION_3=\"third\"

我检查一个字符串:

except = 0;
#ifdef EXCEPTION_1
if (! strcmp(EXCEPTION_1, mystring))
{  except = 1;
}
#endif
#ifdef EXCEPTION_2
if (! strcmp(EXCEPTION_2, mystring))
{  except = 1;
}
#endif
#ifdef EXCEPTION_3
if (! strcmp(EXCEPTION_3, mystring))
{  except = 1;
}
#endif
if (except == 1)
{  // do something
}
else
{  // do something else
}

不用说,虽然这可行,但它也很丑陋、不灵活,并导致我的代码冗余。

有没有办法将字符串附加到预处理器宏变量?

我想得到这样的东西(问题当然是#append不存在):

#ifdef EXCEPTION_1 #append EXCEPTIONS if (! strcmp(EXCEPTION_1, mystring)) {  except = 1; }
#ifdef EXCEPTION_2 #append EXCEPTIONS if (! strcmp(EXCEPTION_2, mystring)) {  except = 1; }
#ifdef EXCEPTION_3 #append EXCEPTIONS if (! strcmp(EXCEPTION_3, mystring)) {  except = 1; }

然后我可以在代码中使用EXCEPTIONS,它可以处理所有可能的异常排列。

换句话说,我想将一个字符串附加到一个宏变量 - 有可能吗?

【问题讨论】:

    标签: c c-preprocessor


    【解决方案1】:

    你可以有定义链,但看起来不会好很多:

    #ifdef EXCEPTION_1 
    #define EXCEPTIONS1 if (! strcmp(EXCEPTION_1, mystring)) {  except = 1; }
    #else
    #define EXCEPTIONS1
    #endif
    
    #ifdef EXCEPTION_2
    #define EXCEPTIONS2 EXCEPTIONS1 if (! strcmp(EXCEPTION_2, mystring)) {  except = 1; }
    #else
    #define EXCEPTIONS2 EXCEPTIONS1 
    #endif
    
    // etc
    

    同样,也好不到哪里去。

    而且你真的不应该用开放的if 定义宏。它允许像if(cond) EXCEPTIONS1 else cout<<"error"; 这样的奇怪交互——这不会达到你的预期,因为EXCEPTIONS1 是一个普通的if,并且会吞噬else 分支。

    使用代码块编写宏的典型方法是将整个内容包装在 do{...}while(0) 中(注意没有结尾 ;)。

    【讨论】:

      【解决方案2】:

      查看令牌字符串化和连接部分here 它可能会帮助一些人。一般来说,使用命令行宏来填充表似乎更容易,并有一个宏简单地扩展为一个循环,检查该表的连续条目以设置异常标志。

      例如,将以下内容另存为 silly.c 并使用 cc -DEX1=\"hello\" 进行编译

      #include <stdlib.h>
      #include <stdio.h>
      #include <string.h>
      
      struct Except {
         const char* key;
         int flag;
      };
      
      struct Except table[] = {
      #if defined(EX1)
         {EX1,1},
      #endif
         {NULL,0}
      };
      
      #define CHECKEX(mys,rv)  { rv = 0;for(int i=0;table[i].key!=0;i++)      \
               if (strcmp(table[i].key,(mys))==0) \
                  rv = 1; \
         }
      
      int main()
      {
         int rv;
         CHECKEX("hello",rv);
         if (rv)
            printf("Got an hello\n");
         else printf("Got nothing\n");
         return 0;
      }
      

      只需根据需要向表中添加更多“块”。当然只是一个建议。

      【讨论】:

        【解决方案3】:

        您可以将宏参数转换为字符串:

        #define STR(x)    #x
        
        STR(hello)  -->  "hello"
        

        您可以将 字符串字面量 连接在一起,只需将它们写在一起即可:

        "123" "abc"  -->  "123abc"
        

        或者创建一个宏:

        #define CONCAT(a, b) a b
        
        CONCAT("hello", " world!")  --> "hello world!"
        

        【讨论】:

        • 我不想连接字符串,我想连接编译器的输入
        • @RolandSeuhs:“如何连接/附加替换字符串”。你应该学习how to ask。你的问题还远没有说清楚。并且:字符串编译器的输入。平等!
        • 那是什么,您甚至都懒得看问题标题,而是在嘲笑 OP?也许你应该学习如何阅读和行为。将此标记为版主注意。
        • @Blindy:我确实进一步阅读了:“有没有办法将字符串附加到预处理器宏变量”
        【解决方案4】:

        您可以使用## 将字符串连接到宏。使用索引并仅使用条件来设置索引。然后最后您可以将索引与您的宏EXCEPTION 连接起来。喜欢,

        定义像#define append(name) name ## counter这样的宏

        如果counter 为 1,这将反过来给你name name1

        现在您可以定义不同的 append 宏以将结果放在单个变量 name

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-06-14
          • 1970-01-01
          • 2014-07-30
          • 2011-01-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多