【问题标题】:How to use a define inside a format string?如何在格式字符串中使用定义?
【发布时间】:2018-04-30 23:08:06
【问题描述】:

假设我有一个字符数组:

#define LEN 10
char arr[LEN + 1];

让我们对其进行一些scanf操作:

scanf("Name: %s", arr);

如果有人输入的名称超过 10 个字符,这可能会很危险。所以最好用这个:

scanf("Name: %10s", arr);

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

scanf("Name: %LENs", arr);

但这不起作用。LEN 没有被预处理器解析,因为它在字符串中使用。

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

【问题讨论】:

  • 您不要在格式字符串中使用定义。您使用 sprintf() 构建格式字符串并将其传递给 scanf。
  • @jwdonahue 不好的建议。
  • @iBug,你有更好的建议吗?
  • @jwdonahue总的来说不是一个坏建议,但如果你可以使用预处理器,它总是更好(没有运行时开销)。跨度>
  • @iBug 这个讨论毫无意义。你抄袭了一切,在我的回答之后的许多步骤中,mods 可以看到。你显然只是在寻找代表和徽章。这不是游戏,绝不容忍抄袭。

标签: c c-preprocessor format-specifiers


【解决方案1】:

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() 格式字符串将要求用户按字面输入

Name: xyz

实际匹配。我怀疑这是你想要的。你可能想要这样的东西:

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

同时考虑完全不使用scanf()。与例如fgets(),这整个预处理器魔法已经过时了。关于不应该使用scanf() 的原因,请参阅我的beginners' guide away from scanf()

【讨论】:

  • @eDeviser 这些宏可能出现在标准标题中,但我对此表示怀疑。它们不是由 C 标准指定的,因此请自行定义。
  • @FelixPalmen.: 顺便说一句..scanf 包含Name is..etc..我会说这是一种罕见的用途。
  • @eDeviser 我添加了一些您可能会觉得有用的信息。
  • 如果有人坚持使用scanf,这绝对是正确的答案。明智的做法是在 #define LEN 之前添加明确的注释,指出它必须是一个简单的十进制整数而不是表达式等。
  • 为什么使用这个解决方案比把#X 放在scanf 中更好?
猜你喜欢
  • 2013-07-29
  • 1970-01-01
  • 1970-01-01
  • 2019-07-19
  • 2019-12-25
  • 1970-01-01
  • 2012-08-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多