【问题标题】:Why "%d" is not equivalent to " %d" as a format string in scanf为什么“%d”不等同于“%d”作为scanf中的格式字符串
【发布时间】:2017-04-07 11:14:00
【问题描述】:

我正在看书并解决一些问题。问题是

对于以下每对scanf 格式字符串,请指明 两个字符串是否等价。如果不是,请显示 如何区分它们。

(a)"%d"" %d"

(b) "%d-%d-%d""%d -%d -%d"

(c) "%f""%f "

(d) "%f,%f""%f, %f"

我的解决方案是 (a) 它们是等价的,因为 scanf 丢弃了空格。对于 (b) 它们不等价,因为 scanf 匹配 - 和空格 。对于 (c),它们不等价,因为 scanf 将放回缓冲区中的空白。对于 (d),它们是等价的,因为 scanf 丢弃了空白。根据 Chegg 解决方案,所有前面的问题都不等价。我错了吗?在这篇文章中,我想确保我的答案与 Chegg 解决方案相比是正确的。我已经读过这本书,并且对scanf 有相当的了解。

【问题讨论】:

  • @rsp,不完全是。我已经提供了答案。另外,我将我的解决方案与 Chegg 解决方案进行比较。而且,这不是作业题。
  • @CroCo 有什么理由将列表格式恢复为一大块难以阅读的文本?
  • @CroCo "根据 Chegg 解决方案" --> 根据 Cheng 的书,"%d"" %d" 有什么区别?

标签: c scanf


【解决方案1】:

"%d"" %d" 根据 OP 的推理是相同的。

它们与 "123"" 456" 等预期的数字输入肯定相同。剩下的一个考虑是FILE"abc"" xyz" 相比,失败的指针在哪里? "%d" 本身,first 消耗前导空白。所以没有区别。

...转换规范按以下步骤执行:C11dr §7.21.6.2 7

输入空白字符 ... 被跳过,除非规范包含 [cn 说明符。 §7.21.6.2 8

然后将文本转换为数字输入(对于"%d")。

下面的代码演示了等价性。

void next_testi(const char *s, const char *fmt, const char *pad) {
  rewind(stdin);
  int i = 0;
  int count = scanf(fmt, &i);
  int next = fgetc(stdin);
  printf("format:\"%s\",%s count:%2d, i:%2d, next:%2d, text:\"%s\"\n", //
      fmt, pad, count, i, next, s);
}

void next_test(const char *s) {
  FILE *fout = fopen("test.txt", "w");
  fputs(s, fout);
  fclose(fout);

  freopen("test.txt", "r", stdin);
  next_testi(s, "%d", " ");
  next_testi(s, " %d", "");
  puts("");
}

int main() {
  next_test("3");
  next_test(" 4");
  next_test("");
  next_test(" ");
  next_test("+");
  next_test(" -");
  next_test("X");
  next_test(" Y");
}

输出

format:"%d",  count: 1, i: 3, next:-1, text:"3"  // scanf() return value 1:success
format:" %d", count: 1, i: 3, next:-1, text:"3"

format:"%d",  count: 1, i: 4, next:-1, text:" 4"
format:" %d", count: 1, i: 4, next:-1, text:" 4"

format:"%d",  count:-1, i: 0, next:-1, text:""  // scanf() return value EOF, next is EOF
format:" %d", count:-1, i: 0, next:-1, text:""

format:"%d",  count:-1, i: 0, next:-1, text:" "
format:" %d", count:-1, i: 0, next:-1, text:" "

format:"%d",  count: 0, i: 0, next:43, text:"+" // scanf() return value 0
format:" %d", count: 0, i: 0, next:43, text:"+"

format:"%d",  count: 0, i: 0, next:45, text:" -"
format:" %d", count: 0, i: 0, next:45, text:" -"

format:"%d",  count: 0, i: 0, next:88, text:"X"
format:" %d", count: 0, i: 0, next:88, text:"X"

format:"%d",  count: 0, i: 0, next:89, text:" Y"
format:" %d", count: 0, i: 0, next:89, text:" Y"

【讨论】:

    【解决方案2】:

    你是对的,对选项(c)的推理稍作修改。

    “scanf 将把缓冲区中的空白放回。”

    我不太了解您的版本,但实际上,scanf() 将输入与提供的格式字符串进行字面匹配,并且在 %f 转换说明符旁边,一个非前导空格需要匹配 包含任意数量的空格,直到读取到非空格。

    引用C11,第 7.21.6.2 章

    由空白字符组成的指令通过读取输入执行到 第一个非空白字符(未读),或者直到没有更多字符可以 被阅读。该指令永远不会失败。

    【讨论】:

    • 在 (c) 中,scanf 将等到用户输入非空白字符,正如我从书中理解的那样,所以我对选项不等效的说法是正确的。
    • "%d-%d-%d""%d -%d -%d" 不一样。 "1- 2 -3"的输入字符串不会被前者解析,但会被后者解析
    • @nos 啊,我好像错过了,应该是对的。
    猜你喜欢
    • 2011-01-10
    • 2021-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-27
    • 2014-05-30
    • 2021-03-09
    • 2012-06-03
    相关资源
    最近更新 更多