8

我试图弄清楚究竟是如何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将斜杠与第一个版本中的空格相同。如果用户输入斜杠分隔值,我将如何获得它,我可以将这些值适当地分配给变量?

4

2 回答 2

7

%s匹配非空白字符(这是一个贪婪匹配:它不会回溯以查看是否有其他匹配)要匹配非正斜杠字符,请使用%[^/]

(另外,请注意,scanf 字符串中的空格字符(匹配零个或多个空格字符)与非空格非百分号字符的行为非常不同,例如'/'(完全匹配'/'

于 2013-03-11T01:56:10.387 回答
3

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

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

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

请注意,“出现问题”部分很难连贯地向用户报告错误。这就是为什么包括我自己在内的许多人建议不要使用scanf()或者fscanf()更喜欢使用fgets()或者可能是 POSIXgetline来读取用户的一行,然后使用sscanf()它来分析它。您可以更轻松地报告问题。另请注意,from的返回值scanf()是成功分配的次数;它不计算包含*.

于 2013-03-11T02:19:19.377 回答