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

How to pad strings using preprocessor macros

是否可以仅使用预处理器宏用空格(或任何字符)填充字符串?如果可以,怎么做?

示例:

#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      "

我知道在运行时有简单的解决方案,但我的问题是如何在编译时.

填充字符串

首先,预处理器可以将标记转换为字符串,但它根本不能修改现有的字符串。它 可以 做的是将字符串文字并排放置 ("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] = '[=11=]';

您无法通过这种方式获得所需的字符串作为文字,但您确实获得了它,代价是分配的字节比您需要的最多多 10 个字节,如果原始字符串实际上比实际长,则将其截断10 个字符。

很有意思的问题!在 strlen 都未知的一般情况下,以及当 str 单独未知时,这似乎是不可能的。如果 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 "    ")