c - 如何使用 SCANF 只允许特定格式的输入?

标签 c formatting scanf

我希望我的用户将 3 个不同的年龄放入括号中并用逗号分隔。所以它看起来像这样 {int,int,int}。

我尝试过:

int a,b,c;
if(scanf("{ %d , %d , %d }", &a,&b,&c)!=3){
printf("Bad format");
}

但它没有正确拒绝像 { 1, 2, 3,

这样的输入

我想允许:

{1,2,3}
{ 1 , 2 ,3 }
{ 1 ,    2 ,       3}

并拒绝:

{1,2,3,4}
{1 2 3 4}
1234
1 2 3 4

等等

谢谢。

最佳答案

(这个答案有些是固执己见的。抱歉。我有意见。)

scanf确实不是精确验证输入的理想工具。特别是,它通常不区分换行符和其他空格,这一事实使得验证严格面向行的输入确实非常困难。

另一方面,如果您已经拥有所有标点符号,也许您应该准备好接受更多自由格式的输入。为什么用户不应该在两行甚至五行上输入数据:

{
  1,
  2,
  3
}

(或者Pythonesquely:

{ 1
, 2
, 3
}

:-) )

除非您竭尽全力禁止它们,或者使用此处通常建议的 fgets/sscanf 解决方法,否则以上所有内容都将被接受。这可能会让某些用户高兴,你永远不知道。

但是,还有另一个问题可能值得尝试解决。在这里,您希望确保三元组以右大括号 } 正确终止,而仅将 } 放入模式中是无法做到这一点的。如果您需要验证最后一次转换之后出现的字符,则需要将该字符设置为转换(以便它成为最后一次转换)。否则,scanf 将简单地将不匹配的输入字符保留在输入流中,并报告所有数据转换均成功。

所以你可以使用这样的东西:

int a,b,c;
char brace;
if (scanf("{ %d , %d , %d %c", &a, &b, &c, &brace) != 4
    || brace != '}') {
  printf("Bad format");
}

这保证有一个},前面可能有空格。然而,它 不保证 } 是该行的最后一个内容。由于它小心翼翼地不会跳过模式后的空格,因此您可以通过使用 fgets 读取该行(它将读取并包括尾随换行符)来检查该行的其余部分是否为空,然后检查读取的字符以确保它们都满足 isspace()

或者您可以让用户将换行符放在他们想要的任何位置。

关于c - 如何使用 SCANF 只允许特定格式的输入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53053414/

相关文章:

c - 为什么当我在 Linux 内核中执行递归自旋锁时系统卡住

c - C中双向链表的内存问题

c - 默认情况下 sleep 做什么?它会在实际时间进入休眠状态吗

dictionary - .dic线格式定义

使用 print 命令在表中简化 Python 输出

c++ - sscanf 保存到 vector

c - sscanf - 读取十六进制值不适用于逗号

c++ - 在ubuntu上用不同版本的gcc编译会产生不同的结果

c++ - 如何使用boost将日期时间格式化为字符串?

c - 关于在c中使用fgets和scanf读取输入的问题