我正在试图找出scanf
的确切工作原理。如果我编写这样的代码:
scanf("%s %d %f", name, &age, &wage);
输入此作为标准输入:
james 20 34000.25
然后分别打印出姓名,年龄和工资,我得到了人们所期望的,就像我投入标准输入一样。但是,如果我输入这样的内容:
scanf("%s/%d/%f", name, &age, &wage);
我将其作为标准输入输入:
james/20/34000.25
我得到字符串james/20/34000.25
作为字符串值,0和0.00000分别表示整数和浮点值。我认为scanf
会像处理第一个版本中的空格一样处理斜杠。如果用户输入斜杠分隔值,我怎么能得到它,我可以适当地将值分配给变量?
答案 0 :(得分:4)
%s
匹配非空格字符(并且它是一个贪婪的匹配:它不会回溯以查看是否可以进行其他匹配)要匹配非正斜杠字符,请使用%[^/]
(另请注意,scanf字符串中的空格字符(匹配零个或多个空格字符)与非空格非百分号字符的行为非常不同,例如'/'
(完全匹配{{ 1}})
答案 1 :(得分: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
的标准格式(这意味着具有7位有效数字的34000.25
位于可表示值范围的外端。)
请注意,“出错了”部分很难将错误报告给用户。这就是为什么许多人(包括我自己)建议不要使用scanf()
或fscanf()
,而是更喜欢使用fgets()
或者POSIX getline
来读取用户的一行,然后使用sscanf()
进行分析。您可以更轻松地报告问题。另请注意,scanf()
的返回值是成功分配的数量;它不计算包含*
的转换规范。