您的主要问题是您没有为要读取的字符串分配空间。您可以通过多种方式做到这一点:
char title[256];
或:
char *title = malloc(256);
if (title == NULL)
{
fprintf(stderr, "Out of memory\n");
exit(1);
}
其中任何一个都应该用于:
if (fscanf(fp, " <%255[^>]>", title) != 1)
{
fprintf(stderr, "Oops: format error\n");
exit(1);
}
或者,如果您的系统具有符合 POSIX 2008 的 fscanf() 实现,则可以将 m 修饰符用于 %s(或使用 %c,或者在本例中为扫描集%[...] — 更多内容见下文):
char *title = 0;
if (fscanf(fp, " <%m[^>]>", &title) != 1) // Note the crucial &
{
fprintf(stderr, "Oops: format error\n");
exit(1);
}
这样,如果fscanf() 全部成功,该函数将为标题分配内存。如果失败,内存将被释放(或从未分配)。
请注意,我将 %s 更改为 %m[^>]。这是必要的,因为原始转换永远不会匹配>。如果输入中有>,它将被合并到结果字符串中,因为它最多读取空格,而> 不是空格。此外,您将无法判断尾随上下文是否曾经匹配过——即原始格式中的 >,在我建议的修改后的代码中它仍然是一个问题(或不是)。
我还在字符串的开头添加了一个空格来匹配可选的空格。否则,字符串开头的< 必须与第二个数字之后的> 在同一行,假设> 完全存在。您还应该检查第一个fscanf()的返回:
if (fscanf(fp, "<%d>\n<%d>", &m, &b) != 2)
{
fprintf(stderr, "Oops: format error\n");
exit(1);
}
请注意,嵌入的换行符只是在> 和< 之间查找空格——即零个或多个空格、制表符或换行符。另请注意,您永远不会知道第二个 > 是否匹配。
您可以使用exit(EXIT_FAILURE); 代替exit(1); — 或者,由于此代码在main() 中,您可以使用return 1; 或return(EXIT_FAILURE);,其中括号在任何一种情况下都是可选的,但它们的存在会唤起对某些人来说毫无根据的愤怒。
您还可以改进错误消息。您应该考虑使用fgets() 或POSIX 的getline(),后跟sscanf(),因为它使(到目前为止)更容易进行良好的错误报告,而且如果第一次尝试转换数据失败,您可以轻松地重新扫描数据。