C 预处理器:动态 const char

C Preprocessor: dynamic const char

我想在编译时动态创建一个 const char,如下所示:

const char reprx[] = "repr1[=10=]repr2[=10=]repr3[=10=]repr4[=10=]";

并使用 #define 指定字符串 reprX[=13=] 在字符串中重复的次数(通过将 X 替换为增量值)。例如 5:

const char reprx[] = "repr1[=11=]repr2[=11=]repr3[=11=]repr4[=11=]repr5[=11=]";

有简单的方法吗? (没有额外的库)

这可以给你一个线索:

#include <stdio.h>

#define repeat1(s) s"1[=10=]"
#define repeat2(s) repeat1(s)s"2[=10=]" 
#define repeat3(s) repeat2(s)s"3[=10=]" 
#define repeat4(s) repeat3(s)s"4[=10=]" 
#define repeat5(s) repeat4(s)s"5[=10=]"
#define repeat6(s) repeat5(s)s"6[=10=]" 
#define repeat7(s) repeat6(s)s"7[=10=]" 
#define repeat8(s) repeat7(s)s"8[=10=]" 
#define repeat9(s) repeat8(s)s"9[=10=]" 

#define repeat(s, n) repeat##n(s)

int main(void)
{
    printf("%s\n", repeat("repr", 5));
    return 0;
}

输出:

printf("%s\n", "repr""1[=11=]""repr""2[=11=]""repr""3[=11=]""repr""4[=11=]""repr""5[=11=]");

请注意,此版本限制为 9 个字符串。

执行此操作的最简单方法是使用自定义预处理脚本,您可以将其集成到构建过程中。

我不知道你有什么工具可用,但你可以轻松地使用 awk 作为预处理器。如果您正在使用 make,您可以从框架自动构建 c 文件:(请参阅下面的原始 awk 脚本。)

file.c: file.c.in
        awk '                                          \
        /^#define X / {                                \
           for (i = 1; i <= $; ++i)                  \
             s = s "\"repr"i"\0\""                    \
           }                                           \
        match($[=10=], / *const char \*reprx\[\] = /)  {   \
           $[=10=] = substr($[=10=], 1, RLENGTH) s ";"         \
        }                                              \
        1' $^ > $@

示例:

$ cat file.c.in
/* The beginning of the program */
#define X 7
/* Some part of the program */
const char *reprx[] = "Will be replaced";
/* The rest of the program */

$ make -s file.c
$ cat file.c
/* The beginning of the program */
#define X 7
/* Some part of the program */
const char *reprx[] = "repr1[=11=]""repr2[=11=]""repr3[=11=]""repr4[=11=]""repr5[=11=]""repr6[=11=]""repr7[=11=]";
/* The rest of the program */

由于需要转义美元符号和行尾,所以有点模糊,这里是原始的 awk 程序:

awk '/^#define X / {
        for (i = 1; i <= ; ++i)
            s = s "\"repr"i"\0\""
        }
     match([=12=], / *const char \*reprx\[\] = /)  {
        [=12=] = substr([=12=], 1, RLENGTH) s ";"
     }
     1'