我希望用户将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
等
谢谢。
答案 0 :(得分:0)
读取输入的行并测试其是否包含诸如" }"
之类的尾随字符的格式的一种简单方法是将fgets()
和sscanf()
与" %n"
。
"%n"
记录到目前为止的扫描偏移量-如果它偏移了那么远。
// Sample code
#define INT_TEXT_SIZE 11
#define FMT3 "{ %d , %d , %d }"
#define LINE_EXPECTED_MAX_SIZE (sizeof FMT3 + 3*INT_TEXT_SIZE);
// Use 2x expected max size to allow for extra spaces, leading 0, etc.
char buf[LINE_EXPECTED_MAX_SIZE * 2 + 1];
if (fgets(buf, sizeof buf, stdin)) {
int n = 0;
sscanf(buf, FMT3 " %n", &a, &b, &c, &n);
// if scanning was incomplete or extra junk at the end...
if (n == 0 || buf[n]) {
printf("Bad format <%s>", buf);
} else {
printf("Succcess %d %d %d\n", a,b,c);
}
}
上面的缺点。
int
未检测到溢出。
#define INT_TEXT_SIZE 11
假定为32位或更小的int
。 int
的文本需求大约为log2(整数位大小),因此可以从here中提取INT_DEC_TEXT
的代码。
答案 1 :(得分:0)
(有些答案是有根据的。对不起。我有意见。)
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()
。
或者您可以让用户将换行符放置在他们想要的任何地方。