0

我有一个函数试图读取文件的每一行,然后使用 sscanf 将值传递到结构数组中,为文件的每一行创建一个新结构,而不是包含字符“#”的注释行。这是我的代码:

typedef struct { 
    int row, col, C, D;
    char program[80];
} agentDetails;

我的结构在头文件中定义,#included 在主文件中。

char currentLine[80];
char** agents;
int n=0;

agents = malloc(sizeof(char*)*4); 

while (fgets(currentLine, sizeof currentLine, file) != NULL) {
    if(!strchr(currentLine, '#')) {
        agentDetails agents[n];    /*create new struct in array agents*/
        sscanf(currentLine, "%d %d %c %s %s", &agents[n].row, &agents[n].col, &agents[n].C, agents[n].program, agents[n].D); 
        n++; 
    }
}

这可行,但是当它到达文件末尾时它不会退出循环,它会坐在那里等待输入。我尝试过使用 gdb 单步执行,在最后一行之后,它会跳转到 while(fgets...) 行,然后等待输入。

我知道如果我尝试将值扫描到函数内初始化的变量中,则此代码有效,它似乎仅在我使用结构数组时出现故障。这里发生了什么?


我已经更改了代码,所以它可以工作,见下文:

int n = 0; 
int i = 0;

while (fgets(currentLine, sizeof currentLine, file) != NULL) {
    if(!strchr(currentLine, '#')) {
        n++;
    }
}

rewind(file);
agentDetails agents[n];

while (fgets(currentLine, sizeof currentLine, file) != NULL) {
    if(!strchr(currentLine, '#')) {
        sscanf("same as above"); 
        i++; 
    }
}

但是,我不使用 malloc。这是一个问题吗?这会导致问题吗?

4

5 回答 5

0

这在几个方面都是错误的。

  1. 您声明并分配char** agents,然后使用agentDetails agents[n]
  2. agents您正在阅读数组的末尾。有效索引为 0 到 (n-1)。
  3. 您的格式规范错误。

GCC 发出以下警告:

 warning: format ‘%c’ expects argument of type ‘char *’, 
 but argument 5 has type ‘int *’ [-Wformat]

 warning: format ‘%s’ expects argument of type ‘char *’, 
 but argument 7 has type ‘int’ [-Wformat]
于 2013-09-18T10:55:03.547 回答
0

仔细看看这个:

agentDetails agents[n];    /*create new struct in array agents*/
sscanf(currentLine, "%d %d %c %s %s", &agents[n].row, &agents[n].col, &agents[n].C, agents[n].program, agents[n].D); 
n++;

您正在大小的 while 循环(错误 1)内创建一个数组n(假设n具有非零值)。然后,您将sscanf进入 index 处的数组,该数组n始终通过数组的限制(错误 2)。在循环结束时,您将数组丢弃,因为它的范围已完成(错误 3)。

你的代码应该是这样的:

agentDetails agents[n];    /* make sure to get the correct `n` from somewhere, for example the file itself */
                           /* better yet, use `malloc`, since `n` could be really large */
i = 0;
while (fgets(currentLine, sizeof currentLine, file) != NULL) {
    if(!strchr(currentLine, '#')) {
        sscanf(currentLine, "%d %d %c %s %s", &agents[i].row, &agents[i].col, &agents[i].C, agents[i].program, agents[i].D); 
        i++; 
    }
}
于 2013-09-18T10:43:17.770 回答
0

只需显示您代码的一部分。哪个工作得很好。

#include<stdio.h>
int main()
{
    FILE *file;
    int agent1, agent2;
    char c, s1[10],s2[10],currentline[100];
    char currentLine [100];
    file = fopen ("test.txt" , "r");
    while (fgets(currentline, 100, file) != NULL) {
            printf("currentline = %s\n", currentline);
            fflush(stdout);
                sscanf(currentLine, "%d %d %c %s %s", &agent1, &agent1, &c, s1, s2); 
    }
    fclose(file);
    return 0;
}

文件 test.txt

32 10 a megharaj india

输出

currentline = 32 10 a megharaj india
于 2013-09-18T11:04:01.000 回答
0

你的代码看起来有点奇怪

while (fgets(currentLine, sizeof currentLine, file) != NULL) 
{
  if(!strchr(currentLine, '#')) 
  {
    agentDetails agents[n];    /*create new struct in array agents*/
    sscanf(currentLine, "%d %d %c %s %s", &agents[n].row, &agents[n].col, &agents[n].C, agents[n].program, agents[n].D); 
    n++; 
  }
}

对于每个循环,您创建一个大小为 n 的 agentDetails 数组,然后 n 递增并创建一个新数组。您还可以在参数中使用 n 以使 sscanf 可能超出数组。我认为这样的事情会更符合你想要的:

int i = 0; // assuming n is defined somewhere else
agentDetails agents[n];    /*create new struct in array agents*/
while (fgets(currentLine, sizeof currentLine, file) != NULL && i < n) 
{
  if(!strchr(currentLine, '#')) 
  {
    sscanf(currentLine, "%d %d %c %s %s", &agents[i].row, &agents[i].col, &agents[i].C, agents[i].program, agents[i].D); 
    i++; 
  }
}

检查返回值也是一个好习惯,例如 sscanf 返回的内容以查看预期参数的数量是否与 sscanf 找到的相同。

于 2013-09-18T10:42:41.723 回答
0

据我从您提供的代码中可以看出...在这一行中:

agentDetails agents[n];    /*create new struct in array agents*/

您创建 n 大小的结构数组 agentDetails。
在 sscanf 中,您尝试将一些细节写入结构 agent[n],它不在数组中,因为数组大小是从 0-(n-1)。如果我错了,请提供有关您的代码的更多详细信息。

您尝试声明一个未知大小的数组,但它不起作用。
您可以遍历文件一次,计算文件中有多少代理,然后使用 malloc 分配所需的内存。或者您可以在每次迭代中进行 malloc 和 realloc(这可能是个坏主意)。

第一个。从循环中删除数组声明。
第二。阅读一下 malloc 的工作原理。
第三。在这些步骤之后,您将能够轻松地自己修复代码。

于 2013-09-18T10:42:48.453 回答