[英]Multiple fscanf
我已经编写了以下程序,旨在将文件中的字符串读取到变量“ title”中:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int m, b;
char *title;
FILE *fp;
fp = fopen("input2.txt", "r");
if (fp == NULL)
{
printf ("Error: file cannot be found\n");
return 1;
}
fscanf(fp, "<%d>\n<%d>", &m, &b);
printf("%d\n%d", m, b);
fscanf(fp, "<%s>", title);
fclose(fp);
return 0;
}
上面的程序在第二次调用fscanf
崩溃。 为什么会这样?
您的主要问题是您尚未为读取的字符串分配空间。 您可以通过多种方式执行此操作:
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()
因为(到目前为止)这样做可以更轻松地进行良好的错误报告,而且,如果首次尝试转换数据失败,则可以轻松地重新扫描数据。
这个:
char *title;
只是一个字符的指针。 如果fscanf向其中写入了多个字符,则在运行完之后,您将破坏存储器中的任何内容
您需要执行以下两项操作之一:
char title[50]; // Holds up to 49 characters, plus termination
要么:
#include <stdlib.h>
// ...
char *title = malloc(50 * sizeof(char)); // Same capacity as above
if (title == NULL) {
// handle out of mem error
}
// ...
free (title);
第一个选项显然要简单得多,但是需要您在编译时知道数组大小。
如果您不熟悉编程,还没有遇到指针和动态内存分配,请暂时坚持使用第一个选项。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.