【问题标题】:c: scanf reading integersc: scanf 读取整数
【发布时间】:2018-01-17 05:04:16
【问题描述】:

此 scanf 语句将从10ss 之类的输入中读取数字为 10 - 我如何重写它以忽略后面跟着其他字符的 int?如果10ss被读取,它应该忽略它并停止for循环。

for (int i = 0; scanf("%d", &val)==1; i++)

【问题讨论】:

  • scanf 不适合 bad 输入。它总是只向前看一个字符。当它遇到s 时已经太晚了。当然,您可以尝试使用扫描集捕获以下字符(如果它是非空白字符)并检查返回值,但我建议您查看无数重复项,了解如何确保字符串仅使用strtol的整数。
  • 使用getchar() 读取有问题的非数字,然后再次尝试scanf("%d", &val)==1
  • @chux 你将如何在 for 循环中使用 getchar()?
  • 阅读scanf的文档。
  • "123 456""123-456" 这样的输入会发生什么?

标签: c scanf


【解决方案1】:

您可以尝试阅读下一个字符并对其进行分析。类似于

int n;
char c;
for (int i = 0; 
     (n = scanf("%d%c", &val, &c)) == 1 || (n == 2 && isspace(c)); 
     i++)
  ...

// Include into the test whatever characters you see as acceptable after a number 

或者,试图创造一些“更高级”的东西

for (int i = 0; 
     scanf("%d%1[^ \n\t]", &val, (char[2]) { 0 }) == 1; 
     i++)
  ...

// Include into the `[^...]` set whatever characters you see as acceptable after a number 

但总的来说,您可能很快就会遇到scanf 的限制。最好将您的输入读取为字符串,然后对其进行解析/分析。

【讨论】:

  • @chux:我最初尝试过,但是scanf 返回的计数中不包含被抑制的分配。因此,带有* 的版本即使是10ss 输入也会返回1,这不是本例所需要的。
【解决方案2】:

如何重写它以忽略后面跟着其他字符的 int

稳健的方法是使用fgets() 读取,然后对其进行解析。

// Returns
//   1 on success
//   0 on a line that fails
//   EOF when end-of-file or input error occurs.
int read_int(int *val) {
  char buf[80];
  if (fgets(buf, sizeof buf, stdin) == NULL) {
    return EOF;
  }
  // Use sscanf or strtol to parse.
  // sscanf is simpler, yet strtol has well defined overflow funcitonaitly
  char sentinel;  // Place to store trailing junk
  return sscanf(buf, "%d %c", val, &sentinel) == 1;
}


for (int i = 0; read_int(&val) == 1; i++)

检测过长的行需要额外的代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多