fscanf / fscanf_s 覆盖数组
fscanf / fscanf_s overwriting arrays
我正在尝试使用 fscanf 加载结构数组的一些默认值,它看起来像
#define NUMPIECES 21
typedef struct{
short map[5][5];
short rotation;
short reflection;
} mytype_t;
typedef struct{
mytype_t p[NUMPIECES];
} mytypelist_t;
数据存储在如下文本文件中(用不同的值重复多次):
0 0 0 0 0
0 0 0 0 0
0 0 1 0 0
0 0 0 0 0
0 0 0 0 0
1 2
[...]
我正在使用 fscanf / fscanf_s(都尝试过)读取值,如下所示:
mytypelist_t list;
FILE * f;
[...]
for (i=0; i<NUMPIECES; i++){
for (j=0; j<5; j++){
fscanf(f,"%d%d%d%d%d", &(list->p[i].map[j][0]),
&(list->p[i].map[j][1]),
&(list->p[i].map[j][2]),
&(list->p[i].map[j][3]),
&(list->p[i].map[j][4]));
}
fscanf(f,"%d %d", &(list->p[i].rotations), &(list->p[i].reflection));
}
然而,VS2012 最后抛出异常,说列表已损坏。调试显示,在阅读上面示例文本的前四行后,结构的 "map" 部分包含以下内容
map = [ 0 0 0 0 0 ]
[ 0 0 0 0 0 ]
[ 0 0 1 0 0 ]
[ 0 0 0 0 0 ]
[ 0 X X X X ]
其中 X 是未初始化的值。
似乎 fscanf 正试图 "null-terminate" 我的整数数组或类似的数组,并且正在覆盖后续行的第一个元素。我只是发现它是因为 VS 在退出时抛出异常 - 否则数据将被完美读取(额外的 0 将被下一个 fscanf 调用覆盖)。
这是 fscanf 的副产品吗?还是我忽略了一个错误?
(VS2012 上的Compiling/Testing)
我认为 fscanf 试图在您向它提供指向短裤的指针时填充整数。 fscanf 不知道它填充的字段的实际类型 int;它依赖于格式说明符。我不知道任何 "short" 格式说明符。所以我要么将您的数据字段更改为整数,要么扫描为整数,然后复制到您的数据结构中的短裤
使用 short
格式说明符 "%hd"
并检查 fscanf()
的结果
int cnt = fscanf(f,"%hd%hd%hd%hd%hd", &(list->p[i].map[j][0]),
&(list->p[i].map[j][1]), &(list->p[i].map[j][2]),
&(list->p[i].map[j][3]), &(list->p[i].map[j][4]));
if (cnt != 5) Handle_MissingData();
由于数据每行5个数字,建议阅读行,然后扫描。
char buf[5*22];
if (fgets(buf, sizeof buf, f) == NULL) Handle_EOF();
int cnt = sscanf(buf,"%hd%hd%hd%hd%hd", &(list->p[i].map[j][0]),
&(list->p[i].map[j][1]), &(list->p[i].map[j][2]),
&(list->p[i].map[j][3]), &(list->p[i].map[j][4]));
if (cnt != 5) Handle_MissingData();
如果系统上没有 short
的格式说明符 ...
char buf[5*22];
if (fgets(buf, sizeof buf, f) == NULL) Handle_EOF();
int tmp[5];
int cnt = sscanf(buf,"%d%d%d%d%d",
&tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4]);
for (i=0; i<cnt; i++)) {
list->p[i].map[j][i] = tmp[i];
}
if (cnt != 5) Handle_MissingData();
我正在尝试使用 fscanf 加载结构数组的一些默认值,它看起来像
#define NUMPIECES 21
typedef struct{
short map[5][5];
short rotation;
short reflection;
} mytype_t;
typedef struct{
mytype_t p[NUMPIECES];
} mytypelist_t;
数据存储在如下文本文件中(用不同的值重复多次):
0 0 0 0 0
0 0 0 0 0
0 0 1 0 0
0 0 0 0 0
0 0 0 0 0
1 2
[...]
我正在使用 fscanf / fscanf_s(都尝试过)读取值,如下所示:
mytypelist_t list;
FILE * f;
[...]
for (i=0; i<NUMPIECES; i++){
for (j=0; j<5; j++){
fscanf(f,"%d%d%d%d%d", &(list->p[i].map[j][0]),
&(list->p[i].map[j][1]),
&(list->p[i].map[j][2]),
&(list->p[i].map[j][3]),
&(list->p[i].map[j][4]));
}
fscanf(f,"%d %d", &(list->p[i].rotations), &(list->p[i].reflection));
}
然而,VS2012 最后抛出异常,说列表已损坏。调试显示,在阅读上面示例文本的前四行后,结构的 "map" 部分包含以下内容
map = [ 0 0 0 0 0 ]
[ 0 0 0 0 0 ]
[ 0 0 1 0 0 ]
[ 0 0 0 0 0 ]
[ 0 X X X X ]
其中 X 是未初始化的值。
似乎 fscanf 正试图 "null-terminate" 我的整数数组或类似的数组,并且正在覆盖后续行的第一个元素。我只是发现它是因为 VS 在退出时抛出异常 - 否则数据将被完美读取(额外的 0 将被下一个 fscanf 调用覆盖)。
这是 fscanf 的副产品吗?还是我忽略了一个错误?
(VS2012 上的Compiling/Testing)
我认为 fscanf 试图在您向它提供指向短裤的指针时填充整数。 fscanf 不知道它填充的字段的实际类型 int;它依赖于格式说明符。我不知道任何 "short" 格式说明符。所以我要么将您的数据字段更改为整数,要么扫描为整数,然后复制到您的数据结构中的短裤
使用 short
格式说明符 "%hd"
并检查 fscanf()
int cnt = fscanf(f,"%hd%hd%hd%hd%hd", &(list->p[i].map[j][0]),
&(list->p[i].map[j][1]), &(list->p[i].map[j][2]),
&(list->p[i].map[j][3]), &(list->p[i].map[j][4]));
if (cnt != 5) Handle_MissingData();
由于数据每行5个数字,建议阅读行,然后扫描。
char buf[5*22];
if (fgets(buf, sizeof buf, f) == NULL) Handle_EOF();
int cnt = sscanf(buf,"%hd%hd%hd%hd%hd", &(list->p[i].map[j][0]),
&(list->p[i].map[j][1]), &(list->p[i].map[j][2]),
&(list->p[i].map[j][3]), &(list->p[i].map[j][4]));
if (cnt != 5) Handle_MissingData();
如果系统上没有 short
的格式说明符 ...
char buf[5*22];
if (fgets(buf, sizeof buf, f) == NULL) Handle_EOF();
int tmp[5];
int cnt = sscanf(buf,"%d%d%d%d%d",
&tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4]);
for (i=0; i<cnt; i++)) {
list->p[i].map[j][i] = tmp[i];
}
if (cnt != 5) Handle_MissingData();