fscanf / fscanf_s覆盖数组

时间:2015-04-08 01:07:31

标签: c scanf

我试图使用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在最后引发了一个例外,称该列表已损坏。调试显示,在阅读上面示例文本的前四行后,&#34; map&#34; struct的一部分包含以下

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正在尝试&#34; null-terminate&#34;我的整数或某些数组,并覆盖后续行的第一个元素。我之所以发现它只是因为VS在退出时抛出异常 - 否则数据会被完全读取(下一个fscanf调用会覆盖额外的0&#39;)

这是fscanf的副产品吗?或者我有一个错误,我可以忽略?

(在VS2012上编译/测试)

2 个答案:

答案 0 :(得分:2)

我认为fscanf正在试图填补整数,而你却指向短路指针。 fscanf不知道它填充的字段的实际类型;它依赖于格式说明符。我不知道任何&#34;短&#34;格式说明符。因此,我要么将数据字段更改为整数,要么扫描到整数,然后复制到数据结构中的短路

答案 1 :(得分:2)

使用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();