这样做的一个问题:
result = fscanf(fp, "%[^\n]s", ap->name);
是s
您的格式说明符末尾有一个额外的内容。整个格式说明符应该只是%[^\n]
,它表示“读取由非换行符组成的字符串”。extras
不是格式说明符的一部分,因此它被解释为文字:“从输入中读取下一个字符;如果是“s”,则继续,否则失败。”
不过,额外的东西s
实际上并没有伤害到你。您确切地知道输入的下一个字符是什么:换行符。它不匹配,输入处理在那里停止,但这并不重要,因为它是格式说明符的结尾。但是,如果在同一格式字符串中此格式说明符之后还有其他格式说明符,这将导致问题。
真正的问题是您没有使用换行符:您只是在读取换行符之前的所有字符,而不是换行符本身。要解决这个问题,你应该这样做:
result = fscanf(fp, "%[^\n]%*c", ap->name);
说明%*c
符表示要读入一个字符 ( c
),但不要将它分配给任何变量 ( *
)。如果省略*
,则必须传递fscanf()
另一个包含指向字符 (a char*
) 的指针的参数,然后它将存储读取的结果字符。
您也可以使用%[^\n]\n
, 但这也会读取换行符后面的任何空格,这可能不是您想要的。当fscanf
在其格式说明符(空格、换行符或制表符)中找到空格时,它会消耗尽可能多的空格(即您可以认为它消耗与正则表达式匹配的最长字符串[ \t\n]*
)。
最后,您还应该指定最大长度以避免缓冲区溢出。您可以通过将缓冲区长度放在%
和之间来做到这一点[
。例如,如果ap->name
是 256 个字符的缓冲区,您应该这样做:
result = fscanf(fp, "%255[^\n]%*c", ap->name);
这对于静态分配的数组非常有用;不幸的是,如果数组在运行时动态调整大小,则没有简单的方法将缓冲区大小传递给fscanf
. 您必须使用创建格式字符串sprintf
,例如:
char format[256];
snprintf(format, sizeof(format), "%%%d[^\n]%%*c", buffer_size - 1);
result = fscanf(fp, format, ap->name);