2013-03-11 42 views
3

我想弄清楚scanf的工作原理。如果我的代码是这样的:了解Scanf - 处理格式化输入

scanf("%s %d %f", name, &age, &wage); 

进入这个作为标准输入:

james 20 34000.25 

,然后分别打印出的姓名,年龄,工资,我得到一个会想到什么,同样的事情因为我将其纳入标准输入。不过,如果我进入这样的事情:

scanf("%s/%d/%f", name, &age, &wage); 

,我进入这个作为标准输入:

james/20/34000.25 

我得到的字符串值,0和0.00000字符串james/20/34000.25分别针对整数和浮点值。我认为scanf会将斜线视为与第一个版本中的空格相同。我如何得到它,所以如果用户输入斜线分隔值,我可以适当地分配值的变量?

+1

在我看到关于scanf的每一个答案中都有一些*关键的*缺失。你如何判断'%s','%d','%f','%[^ /]'或'%[^ /]格式规格是否成功匹配?如果用户只是在Windows中按CTRL + Z,或者在Linux中按CTRL + d以关闭stdin,会发生什么? scanf *返回*,您的程序很乐意使用垃圾值?什么scanf *返回*? * Scanf应该这样做!它为什么这样做,而不是?*因为[手册](http://pubs.opengroup.org/onlinepubs/009695399/functions/scanf.html)这样说。 *您*阅读手册? – Sebivor 2013-03-11 03:03:03

+0

......并且在某些情况下,返回值不被忽略;它与-1进行比较以检查文件错误,但不是针对任何*正数*来检查转换错误! - 为什么在尝试阅读手册之前提出问题?本手册在问题出现之前回答您的问题;你花费一个小时诊断的每一个问题都有一本你可能已经阅读过的手册来解决其他五十个问题(除此之外)。更不要说拖拽其他人工时间......为什么手册书面,如果不是被那些了解相关功能的人阅读? – Sebivor 2013-03-11 03:06:13

+0

当你没有面对实际问题时,从手册中学习是非常困难的。我阅读的内容比大多数程序员都要多,但我仍然很少觉得我知道一些东西,直到我必须调试它并亲自与它搏斗。另外,C手册并不完全是清晰的典范,它有助于让真实的人指出我的代码有什么特别的错误。尽管如此,感谢您的信息! – user1427661 2013-03-11 03:10:26

回答

4

%s匹配非空白字符(这是一个贪婪的比赛:它不会走回头路,看一些其他的比赛是可能的)为配合非正斜杠字符,请使用%[^/]

(另请注意,在scanf的字符串中空格字符(匹配零个或多个空白字符)具有从非空间非百分比字符一个非常不同的行为,如'/'(严丝合缝'/'

2

要匹配两个空间分隔和斜线分隔的输入,您需要一个适度复杂的格式字符串:

if (scanf("%[^ /]%*1[ /]%d%*1[ /]%f", name, &age, &wage) == 3) 
    ...data was read properly... 
else 
    ...something went wrong... 

第一个转换规范是一个扫描集,它接受一系列非空格,非斜杠(因此它会停在第一个空格或斜线处)。最好指定接受多少个字符的上限,以避免stack overflow;例如,如果char name[32];,然后%31[^ /](注意一个接一个)。第二个转换规范%*1[ /]接受空白或斜杠[ /]的单个字符(1),并且不将其分配给任何变量(*)。第三个转换规范是标准数字输入,跳过前导空格,允许输入负数等。第四个转换规范与第二个转换规范相同,第五个是float的标准格式(这意味着34000.25 7位有效数字位于可表示值范围的外端)。

请注意,“出错了”部分难以一致地向用户报告错误。这就是为什么包括我自己在内的许多人建议不要使用scanf()fscanf(),而更愿意使用fgets()或POSIX getline来读取用户的一行文字,然后使用sscanf()来分析它。您可以更轻松地报告问题。另请注意,scanf()的返回值是成功分配的数量;它不包括包含*的转换规格。