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中更好?