【问题标题】:Concatenate string literal with char literal将字符串文字与 char 文字连接起来
【发布时间】:2012-04-12 07:44:59
【问题描述】:

我想连接字符串文字和字符文字。由于语法不正确,"abc" 'd' "efg" 会导致编译器错误:

x.c:4:24: 错误:预期为 ',' 或 ';'在'd'之前

现在我必须使用 snprift(不必要地),尽管在编译时知道字符串文字和字符文字的值。

我试过了

#define CONCAT(S,C) ({ \
    static const char *_r = { (S), (C) }; \
    _r; \
})

但它不起作用,因为 S 的空终止符没有被剥离。 (除了给出编译器警告。)

有没有办法写一个宏来使用

  • "abc" MACRO('d') "efg"
  • MACRO1(MACRO2("abc", 'd'), "efg")
  • MACRO("abc", 'd', "efg") ?

如果有人问我为什么要这样:char 文字来自库,我需要将字符串作为状态消息打印出来。

【问题讨论】:

  • 我不想想要使用 sprintf 或任何运行时函数。请不要提出任何使用运行时方法调用的答案。
  • 如果文字来自库,您如何访问它?是库头文件提供的宏吗?
  • 是的,它来自一个头文件。

标签: c string macros char concatenation


【解决方案1】:

我想出了一个我不太喜欢的特定于 GCC 的解决方案,因为不能嵌套使用 CONCAT

#include <stdio.h>

#define CONCAT(S1,C,S2) ({                        \
    static const struct __attribute__((packed)) { \
        char s1[sizeof(S1) - 1];                  \
        char c;                                   \
        char s2[sizeof(S2)];                      \
    } _r = { (S1), (C), (S2) };                   \
    (const char *) &_r;                           \
})

int main(void) {
    puts(CONCAT ("abc", 'd', "efg"));
    return 0;
}

http://ideone.com/lzEAn

【讨论】:

  • 好主意,但是使用带有-pedantic 选项的 gcc 编译会给出警告“从括号中的字符串常量初始化的数组”和“ISO C 禁止表达式中的大括号组”。
【解决方案2】:

试试这个。它使用双宏的 C 宏技巧,因此宏参数在字符串化之前有机会扩展。

#include <stdio.h>

#define C d
#define S "This is a string that contains the character "
#define STR(s) #s
#define XSTR(s) STR(s)

const char* str = S XSTR(C);

int main()
{
    puts(str);
    return 0;
}

【讨论】:

    【解决方案3】:

    如果您可以接受包含在其中的单引号,则可以使用字符串化:

    #define SOME_DEF 'x'
    
    #define STR1(z) #z
    #define STR(z) STR1(z)
    #define JOIN(a,b,c) a STR(b) c
    
    int main(void)
    {
      const char *msg = JOIN("Something to do with ", SOME_DEF, "...");
    
      puts(msg);
    
      return 0;
    }
    

    取决于可能合适或不合适的上下文,但就以这种方式说服它实际上是一个字符串文字而言,这是在运行时无需格式化的唯一方法。

    【讨论】:

    • 为什么不在连接中直接使用 STR1,比如 JOIN(a,b,c) a STR1(b) c ?而不是使用子宏 STR() ?
    • @Luciano 因为那样它会显示为 "Something to do with SOME_DEF..."
    【解决方案4】:

    C 只会让你连接字符串文字。其实snprintf()也没什么问题。你也可以使用strcpy():

    strcpy(dest, str1);
    dest[strlen(dest)] = c;
    strcpy(dest + strlen(dest) + 1, str2);
    

    您还可以使用巨大的switch 语句来克服此限制:

    switch(c) {
        case 'a':
            puts("part1" "a" "part2");
            break;
        case 'b':
            puts("part1" "b" "part2");
            break;
    
        /* ... */
    
        case 'z':
            puts("part1" "z" "part2");
            break;
    }
    

    ...但我拒绝声明任何作者身份。

    简而言之,坚持使用snprintf()

    【讨论】:

    • 问题是我不想使用 snprintf 或 strcpy。这更像是一个哲学问题,而不是初学者问题……
    • kay:啊,我明白了……祝你好运! ;) 顺便说一句,printf("part1 %c part2\n", c); 有什么问题?
    • printf 没有任何“错误”。我只是想知道是否有可能在没有任何运行时活动的情况下在编译时获取整个字符串。有没有这样的宏没有什么关系。你看……这是一个哲学问题。 ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-01-24
    • 2019-07-13
    • 2013-10-20
    • 1970-01-01
    • 2014-03-14
    • 2019-12-15
    相关资源
    最近更新 更多