C 如何在格式字符串中使用define?

C 如何在格式字符串中使用define?,c,c-preprocessor,format-specifiers,C,C Preprocessor,Format Specifiers,假设我有一个字符数组: #define LEN 10 char arr[LEN + 1]; 让我们对其执行一些scanf操作: scanf("Name: %s", arr); 如果有人键入的名称超过10个字符,这可能会很危险。所以最好用这个: scanf("Name: %10s", arr); 现在,如果LEN被更改,我会遇到麻烦。在arr上下文中使用10的每一行代码,我都必须通读整个代码来更正。所以我想到了这样的事情: scanf("Name: %LENs", arr); fputs(

假设我有一个字符数组:

#define LEN 10
char arr[LEN + 1];
让我们对其执行一些scanf操作:

scanf("Name: %s", arr);
如果有人键入的名称超过10个字符,这可能会很危险。所以最好用这个:

scanf("Name: %10s", arr);
现在,如果
LEN
被更改,我会遇到麻烦。在
arr
上下文中使用
10
的每一行代码,我都必须通读整个代码来更正。所以我想到了这样的事情:

scanf("Name: %LENs", arr);
fputs("Name: ", stdout);
fflush(stdout);
scanf("%" STR(LEN) "s", arr);
但这不会起作用。
LEN
不会被预处理器解析,因为它是在字符串中使用的


如何在格式字符串中使用define?

C连接相邻的字符串文本,您可以使用
#
将预处理器参数字符串化,因此以下操作应该可以完成:

#define LEN 10

// this converts to string
#define STR_(X) #X

// this makes sure the argument is expanded before converting to string
#define STR(X) STR_(X)

[...]

scanf("Name: %" STR(LEN) "s", arr);
之所以需要这些宏,是因为只要使用
#LEN
,就会将
LEN
扩展到10,并且只有一个宏将
#
应用到它的参数,结果将是
“LEN”
(参数不会被扩展)

预处理器/编译器将通过以下步骤对此进行转换:

1. scanf("Name: %" STR_(10) "s", arr);
2. scanf("Name: %" "10" "s", arr);
3. scanf("Name: %10s", arr);
在最后一步中,字符串文本被合并成一个字符串


另一方面,您的
scanf()
格式字符串需要用户按字面意思输入

名称:xyz
真正匹配。我怀疑这是你想要的。你可能想要这样的东西:

scanf("Name: %LENs", arr);
fputs("Name: ", stdout);
fflush(stdout);
scanf("%" STR(LEN) "s", arr);

也不要考虑使用<代码> SCAFF()/<代码>。例如,

fgets()
,整个预处理器的魔力已经过时了。有关不应使用
scanf()
的原因,请参阅我的。

您不应在格式字符串中使用define。使用sprintf()生成格式字符串并将其传递给scanf。@jwdonahue错误建议。@iBug,您有更好的建议吗?@jwdonahue通常不是一个错误建议,但如果您可以使用预处理器,它总是更好(没有运行时开销)。@iBug此讨论毫无意义。你剽窃了所有东西,在我的答案后面的许多步骤中,mods可以看到。很明显,你只是在寻找代表和徽章。这不是游戏,剽窃是不能容忍的。@eDeviser这些宏可能出现在标准标题中,但我对此表示怀疑。它们不是由C标准指定的,所以请自己定义。@FelixPalmen:顺便说一句,
scanf
包含
Name
。等等。我想说这是一个罕见的用法。@eDeviser我添加了一些信息,你可能会发现它们很有用。如果有人坚持使用
scanf
,答案肯定是正确的。明智的做法是在
#define LEN
之前添加一条清晰的注释,说明它必须是一个简单的十进制整数,而不是表达式等。为什么使用此解决方案比将#X放在scanf中更好?