如何使用预处理宏填充字符串

4

是否可能仅使用预处理器宏在字符串中填充空格(或任何字符)?如果是,该如何实现?

示例:

#define SOME_STR               "v1.1"
#define STR_PAD(str, len)      // <-- padding defined string

#define SOME_STR_PADDED        STR_PAD(SOME_STR, 10)        // evaluates to "v1.1      "

我知道运行时有简单的解决方案,但我的问题是如何在编译时填充字符串。


你可以重新表达一下你的问题吗?引用你的话:“...我的问题是是否有可能填充...”,我的回答是 - 是的,这是可能的。 - SergeyA
我问了是否可能(a),如果可能的话,如何做到(b)。英语不是我的母语,但我认为它已经传达出去了。我会重新措辞问题,让每个人都能理解。谢谢。 - MemAllox
非常有趣的问题!在strlen都未知的一般情况下,似乎不可能实现,而且仅在str未知的情况下也是如此。如果已知str的长度并且len受到某些合理固定值的限制,则可以生成一个复合三元表达式,编译为单个字符串常量。 - chqrlie
虽然已经有人回答了类似的问题,但我想进行一些区分以清楚地说明一些事情。预处理程序无法确定字符串常量的长度,因此无法执行所要求的操作。但在编译期间会发生很多其他事情;询问预处理器是否能够填充与在编译时能否填充是两个不同的问题(具有不同的答案)。 - H Walters
2个回答

6
非常有趣的问题!在 strlen 都未知的情况下,一般情况下似乎不可能。如果已知 str 的长度并且 len 受到某个合理固定值的限制,可以生成一个复合三元表达式,编译成单个字符串常量。
以下是一个示例:
// compile time padding: str must be a string constant and len <= 4 + strlen(str)
#define STR_PAD(str, len)  (((len) + 1 <= sizeof str) ? str :        \
                            ((len) == sizeof str) ? str " " :        \
                            ((len) == sizeof str + 1) ? str "  " :   \
                            ((len) == sizeof str + 2) ? str "   " :  \
                            str "    ")

我认为你在评论中的意思是“len小于4 + str的大小”。 - Ctx
1
@Ctx:很好的发现。由于 sizeof(str) == strlen(str) + 1),还存在一个偏移一位的错误。 - chqrlie
这是个好主意!我没想到三元表达式。 - MemAllox

1
首先,预处理器可以将标记转换为字符串,但它完全不能修改现有的字符串。 它可以将字符串文字放在一起("foo" "bar"),这在编译时被翻译 - 尽管不是由预处理器正式翻译 - 相当于连接的字符串("foobar")。
因此,您可以像这样做:
#define VERSION "v1.1"
#define APPEND_10_SPACES(s) s "          "

printf("%s", APPEND_10_SPACES(VERSION));

您可以通过宏参数来指定添加多个空格,但这样做会比较困难。在网络搜索中,您可能会找到一些与模拟迭代有关的结果。

然而,预处理器绝对无法确定或使用字符串文字的长度,以便让您执行类似于将文字填充到特定长度的操作。如果您需要这样做,那么您可以潜在地依赖以下解决方法:

char padded[] = APPEND_10_SPACES(VERSION);
padded[10] = '\0';

你不能直接获取所需的字符串,但是你可以获取它,代价是分配比所需多10个字节的空间,并且如果原始字符串实际上超过10个字符,则会截断。

感谢您的澄清。当然,您是正确的,在编译时有比预处理器更多的操作。实际上,我想要根据@chqrlie的回答附加若干个空格。正如您所提到的,您可以编写一个包装器来模拟一个循环。 - MemAllox

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接