循环结构错误;您不应该那样使用feof()
,您必须始终检查 和 的fgets()
状态sscanf()
。此代码也避免了输入数组的溢出。
enum { MAX_ENTRIES = 10 };
int i;
int intarray[MAX_ENTRIES];
float floatarray[MAX_ENTRIES];
char chararray[MAX_ENTRIES][50];
for (i = 0; i < MAX_ENTRIES && fgets(name, sizeof(name), foo) != 0; i++)
{
if (sscanf(name,"%d. %49s %f", &intarray[i], chararray[i], &floatarray[i]) != 3)
...process format error...
}
注意主要变化:
- 整数后面的点必须由格式字符串扫描。
chararray
必须是二维数组才有意义。如果您使用 读取单个字符%c
,它将在第一个数字之后包含空格,并且后续转换规范(对于浮点值)将失败,因为字符串名称不是浮点值。
- 当它是二维数组时,不需要
&
前面的。chararray[i]
如果您真的要读取一维字符数组中的单个字符,而不是示例数据中的“First”或“Second”等整个字符串,则需要使用它。
- 该测试检查三个值是否已成功转换。任何较小的值都表示存在问题。使用
sscanf()
时,只有在字符串中没有任何内容可供第一个转换规范处理时才会返回 EOF(空字符串,所有空格);如果第一个非空白是字母或除+
or以外的标点符号等,则返回 0 -
。
如果您真的想要一个字符而不是名称,那么您必须安排阅读单词中的额外字符,也许使用:
if (sscanf(name,"%d %c%*s %f", &intarray[i], chararray[i], &floatarray[i]) != 3)
在关键之前有一个空格%c
;它将跳过输入中的空格,然后%c
将拾取第一个非空白字符。将%*s
读取更多字符,跳过任何空格(不会有任何空格),然后扫描一串字符直到下一个空格。*
抑制分配;扫描的数据不会存储在任何地方。
fgets()
plus范式的主要优点之一sscanf()
是,当您报告格式错误时,您可以向用户报告导致问题的完整输入行。如果您使用 raw fscanf()
or scanf()
,您只能报告导致问题的第一个字符,通常直到行尾,并且仅当您编写代码来读取该数据时。它更复杂(因此报告通常不是很小心),并且在报告试图小心的极少数情况下,可用信息对用户没有帮助。