当前位置: 首页 > 知识库问答 >
问题:

fscanf/fscafs覆盖数组

濮景龙
2023-03-14

我正在尝试使用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上编译/测试)

共有2个答案

陈宜修
2023-03-14

使用< code>short格式说明符< code>"%hd"并检查< code>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();

如果在没有格式说明符的系统上…

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();
罗渝
2023-03-14

我认为fscanf是在试图填充int,而你给它指向short。fscanf不知道它填充int的字段的实际类型;它依赖于格式说明符。我不知道有什么“短”格式说明符。所以我要么将您的数据字段更改为int,要么扫描为int,然后复制到数据结构中的short

 类似资料:
  • 问题内容: 是否有可能覆盖 全局 功能,从而在一定程度上影响 全局 功能? 据我所知,该函数在包装NodeJS脚本的函数中作为参数提供: 有什么方法可以修改功能吗? 这可能只会影响脚本所在的脚本。 我们如何在流程级别进行修改? 问题答案:

  • 问题内容: 我们很少有扩展基本类的类。我们注意到我们使用了“退出一些睡眠”方法,并且希望在发生睡眠时进行记录。有没有一种方法可以覆盖Thread.sleep方法,在其中我可以添加一些自定义逻辑(即记录),然后仅调用实际的Thread.sleep()?这样,我就不必更改在我的基类中使用Thread.sleep的所有位置。我也愿意接受其他选择。 问题答案: 您不能重写方法,因为它是本机方法,所以无法对

  • 我正在开发一个Spring集成/引导应用程序。我正在使用一个多文档(src/main/Resources/application.yml)来设置几个配置类的默认值(用@ConfigurationProperties注释)。pplicaiton.yml带有默认值,其中一些需要被覆盖,具体取决于环境。 我可以在目录中使用Java系统属性(-D...=...)、Spring“属性”(--...=...)

  • 问题内容: 我试图在php中覆盖我的位置,但是我仍然在php.ini文件中获得了2 mb的值。 问题答案: 通过进行设置时,这些设置不会有任何效果。 原因是PHP 在 执行脚本 之前 需要这些值。上载时,将在完成上载后执行目标脚本,因此PHP需要事先知道最大大小。 在,虚拟主机配置或文件中进行设置。一个典型的文件如下所示:

  • 问题内容: 我的Java应用程序引用了一个使用log4j日志记录的第三方jar文件。问题是该jar包含自己的log4j.properties文件,这会导致我的机器上的访问被拒绝的异常,但是我无法控制jar文件来更改其内容。 我尝试在应用程序的类路径中添加自己的log4j.properties文件,但似乎没有效果。如果我尝试使用PropertyConfigurator以编程方式导入自己的设置,则lo

  • 在上一章中,我们讨论了超类和子类。 如果一个类从其超类继承一个方法,那么只要它没有标记为final,就有可能覆盖该方法。 覆盖的好处是:能够定义特定于子类类型的行为,这意味着子类可以根据其需求实现父类方法。 在面向对象的术语中,覆盖意味着覆盖现有方法的功能。 例子 (Example) 我们来看一个例子。 class Animal { public void move() { Sy