解析C文件的问题



我试图解析一组具有相同格式的文件。下面是一个例子:

NAME:  br17
TYPE: ATSP
COMMENT: 17 city problem (Repetto)
DIMENSION:  17
EDGE_WEIGHT_TYPE: EXPLICIT
EDGE_WEIGHT_FORMAT: FULL_MATRIX 
EDGE_WEIGHT_SECTION
 9999    3    5   48   48    8    8    5    5    3    3    0    3    5    8    8
    5
    3 9999    3   48   48    8    8    5    5    0    0    3    0    3    8    8
    5
    5    3 9999   72   72   48   48   24   24    3    3    5    3    0   48   48
   24
   48   48   74 9999    0    6    6   12   12   48   48   48   48   74    6    6
   12
   48   48   74    0 9999    6    6   12   12   48   48   48   48   74    6    6
   12
    8    8   50    6    6 9999    0    8    8    8    8    8    8   50    0    0
    8
    8    8   50    6    6    0 9999    8    8    8    8    8    8   50    0    0
    8
    5    5   26   12   12    8    8 9999    0    5    5    5    5   26    8    8
    0
    5    5   26   12   12    8    8    0 9999    5    5    5    5   26    8    8
    0
    3    0    3   48   48    8    8    5    5 9999    0    3    0    3    8    8
    5
    3    0    3   48   48    8    8    5    5    0 9999    3    0    3    8    8
    5
    0    3    5   48   48    8    8    5    5    3    3 9999    3    5    8    8
    5
    3    0    3   48   48    8    8    5    5    0    0    3 9999    3    8    8
    5
    5    3    0   72   72   48   48   24   24    3    3    5    3 9999   48   48
   24
    8    8   50    6    6    0    0    8    8    8    8    8    8   50 9999    0
    8
    8    8   50    6    6    0    0    8    8    8    8    8    8   50    0 9999
    8
    5    5   26   12   12    8    8    0    0    5    5    5    5   26    8    8
 9999
EOF

我想把矩阵和矩阵本身的维数提出来,其他的都可以被丢弃。这是我目前用来尝试和解析它的代码:

fp = fopen(argv[1] , "r");
for (i = 0; i < 3; ++i)
{
    fscanf(fp, "n");
}
fscanf(fp, "%d", &size);
for (i = 0; i < 3; ++i)
{
    fscanf(fp, "n");
}
cost = (double**) calloc(size, sizeof(double*));
for(i = 0 ; i < size; ++i){
    cost[i] = (double*) calloc(size, sizeof(double));
}
for(i = 0 ; i < size; ++i)
{
    for(j = 0 ; j < size; ++j)
    {
        fscanf(fp, "%lf", &(cost[i][j]));
    }
    cost[i][i] = 0;
}
fclose(fp);

(文件似乎有换行,当我打开它在一个文本编辑器-虽然不是在记事本-我不知道为什么他们在这里消失了。NAME、TYPE、COMMENT、DIMENSION、EDGE_WEIGHT_TYPE、EDGE_WEIGHT_FORMAT和EDGE_WEIGHT_SECTION都以新行开头。编辑:啊,谢谢,约塞连。我是Stack Overflow新手!)

不管怎样,我的代码不工作。具体来说,我通过使用调试器注意到它没有提升矩阵的维度,这意味着正确读取矩阵的尝试从一开始就注定要失败。所有变量都声明了,这不是问题。它只是没有在维度之后读取数字并将其赋值给size。我做错了什么?

编辑:我已经尝试了Vicky对fscanf(fp, "%sn", buf);的建议-它也有让我通过观察buf的值来查看它在文件中的位置的优点-并发现它一次取一个词,而不是一行。这种方法的问题在于COMMENT:行所包含的字数不一致。使用"%*s""%*sn"没有写任何东西,但是

编辑2:while((c = getchar()) != 'n' && c != 'EOF') ;只是挂起程序。不知道它在干什么。

编辑3:while((c = getc(fp)) != 'n' && c != 'EOF') ;正在逐行浏览文件,但fscanf(fp, "%d", &size);仍然没有拾取数字。

编辑4:啊哈!用 让它工作
char c; 
for (i = 0; i < 3; ++i)
{
    while((c = getc(fp)) != 'n' && c != 'EOF') ;
}
fscanf(fp, "%*s");
fscanf(fp, "%i", &size);
for (i = 0; i < 4; ++i)
{
    while((c = getc(fp)) != 'n' && c != 'EOF') ;
}

谢谢大家的帮助!

我总是发现scanf函数带来的问题比它们解决的问题要多。

我个人更喜欢使用fgets:-

char buffer [1024];
file = fopen (filename);
while (fgets (buffer, 1024, file))
{
  ParseState state = FindingLineType;
  for (char *token = strtok (buffer, " ") ; token ; token = strtok (0, " "))
  {
    // parse the token!
    switch (state)
    {
    case FindingLineType:
      if (stricmp (token, "DIMENSION:") == 0)
      {
        state = GettingDimension;
      }
      else
      {
        if (isdigit (*token))
        {
          if matrix has been created
          {
            state = ParsingMatrix;
          }
          else
          {
            error - got matrix row before dimension
          }
        }
      }
      break;
    case GettingDimension:
      dimension = atoi (token);
      create matrix
      break;
    }
  }
}

这应该会给你一些想法,你当然可以添加更多的错误检查

仅计算n来确定行结束是不可靠的,如果您的文件有r作为行结束字符怎么办?事实上,您需要考虑n, rrn作为行结束序列。

Windows记事本是一种"Hello World"编辑器。它是非常基本和有限的,只能处理rn作为行结束,这就是为什么如果行以rn结束,它会显示单行。

C中的行读取不是一项微不足道的任务,如果您知道一行的最大长度,则可以使用fgets,这样您就可以传递适当分配的缓冲区。否则,您将不得不处理未知的行长度,例如COMMENT行。我个人更喜欢巫婆可以处理所有这些,并且在一次调用中只返回文件中的一行,参见这样的read_line函数的示例。

在文件格式中,矩阵的大小出现在第4行。因此必须转义到前三行,只需执行以下三次

read_line(pf);

在第4个read_line上,您有包含大小的行。您需要提取并保存它以供以后使用。

// DIMENSION:  17
line = read_line(pf);
printf("%sn", line);
// extact the size of the matrix
tmp = strtok(line, " ");
tmp = strtok(NULL, " ");
size = atoi(tmp);
printf("Parsed size = %dn", size);
free(line);
line_number++;

现在你还有另外三行来组成你的矩阵。像第一个一样转义它们。

现在你的矩阵开始了,这里你可以使用fscanf,你可以在你分配一个矩阵行之后开始从文件中读取,这样你可以节省一些不必要的迭代。

下面是构建循环的方法:

if(size > 0) {
    printf("Start reaading matrix of size %dx%dnn", size, size);
    matrix = malloc(sizeof(double*) * size);
    for(i = 0; i < size; i++) {
        matrix[i] = malloc(sizeof(double) * size);
        n_read = 0;
        for(j = 0; j < size; j++) {
            n_read += fscanf(pf, "%lf", &matrix[i][j]);
            printf("%.2lft", matrix[i][j]);
        }
        printf("n");
        line_number++;
        if(n_read != size) {
            printf("invalid data at line %d, expected to read %d but got %dn", line_number, size, n_read);
        }
    }
}

相关内容

  • 没有找到相关文章

最新更新