在阅读下一行之前如何停止?

时间:2016-02-23 09:17:18

标签: c

我必须阅读这样的文件:

0 ->  1:50  2:30  3:10
1 ->
2 ->  0:10  3:20
3 ->  1:20  2:10  3:30

这是我的代码:

graphs = fopen(argv[2],"r");

  if(graphs==NULL){
    printf("File hostgraphs not found\n");
    exit(EXIT_FAILURE);
  }
  while((err=fscanf(graphs,"%d ->",&num))==1){
    row=num;
    while((err1=fscanf(graphs," %d:%d ",&column,&visits))==2){
      hostgraphs[row*n+column]=visits;
    }
    if(err1!=2)
      break;
    if(err==0){
      printf("Hostgraph out of bounds\n");
      exit(EXIT_FAILURE);
    }
  }
  for(i=0;i<n;i++){
    for(j=0;j<n;j++){
      printf("%d ", hostgraphs[i*n+j]);
    }
    printf("\n");
  }

它给了我以下结果:

0 50 30 10 
0 0 0 0 
0 0 0 0 
0 0 0 0 

预期输出必须是:

 0 50 30 10
 0  0  0  0
10  0  0 20
 0 20 10 30

有人可以帮我吗?

4 个答案:

答案 0 :(得分:0)

修复很简单:删除

fscanf格式字符串中的尾随空格
fscanf(graphs," %d:%d ",&column,&visits)

应该简化为

fscanf(graphs,"%d:%d", &column, &visits)

答案 1 :(得分:0)

您可以通过使用getline一次一行地读取文件,然后在每行上分别应用相同的逻辑来实现此目的。

在以下代码中,我首先使用getline方法从buffer中的文件中获取一行。然后我使用fmemopen方法将该行处理为FILE指针fbuffer,该方法用于读取类似文件的字符串:

graphs = fopen(argv[2],"r");

if(graphs==NULL)
{
   printf("File hostgraphs not found\n");
   exit(EXIT_FAILURE);
}

char *buffer = NULL;
size_t len = 0;

while(getline(&buffer, &len, graphs) != -1)
{
 FILE * fbuffer = fmemopen(buffer, len, "r");

 while((err=fscanf(fbuffer,"%d -> ",&num))==1)
 {
   row=num;

   while((err1=fscanf(fbuffer," %d:%d ",&column,&visits))==2)
   {
     hostgraphs[row*n+column]=visits;
   }

   if(err1!=2)
   {
     break;
   }

   if(err==0)
   {
     printf("Hostgraph out of bounds\n");
     exit(EXIT_FAILURE);
   }
  }

  free(buffer);
  buffer = NULL;
  len = 0;
}

for(i=0;i<n;i++)
{
    for(j=0;j<n;j++)
    {
      printf("%d ", hostgraphs[i*n+j]);
    }
    printf("\n");
}

注意:我刚刚添加了代码,可以让现有代码正常运行,而无需对代码进行任何更改。

答案 2 :(得分:0)

fscanf在读取第一行后忽略换行符,然后移至下一行并在5中读取1并生成err1。这是根本原因。您可以添加fseek以向下移动并以下面的代码剪切开始新序列,或者只是将算法更改为另一个有效的算法。

graphs = fopen(argv[2],"r");
if (!graphs) {
        printf("File hostgraphs not found<%s>\n", argv[1]);
        exit(EXIT_FAILURE);
    }

    while((err = fscanf(graphs, "%d ->", &num)) == 1) {
        pos = ftell(graphs); // save position

        while((err1 = fscanf(graphs, " %d:%d", &column, &visits)) == 2 ) {
            hostgraphs[num * n + column] = visits;
            pos = ftell(graphs);  // save position
        }

        // seek back to previous one and start new sequence
        fseek ( graphs , pos, SEEK_SET ); 
    }

    for(i = 0; i< n; i++){
        for(j = 0; j < n; j++){
            printf("%d ", hostgraphs[i * n + j]);
        }

        printf("\n");
    }

答案 3 :(得分:0)

你很接近,但是你需要一种方法来定位每个'\n',而无需从文件中读取下一行值。使用fscanf非常困难,因为输入文件中的每一行都有不同数量的元素。

另一种方法是使用fgets读取整行,然后将初始"row -> "前缀与数据值分开。如果将值移动到单独的值缓冲区(例如vbuf),则可以通过找到space,前进到下一个digit然后使用{{}来重复循环缓冲区。 1}}拆分sscanfcolumn

(您实际上甚至不需要在visits中拆分值,您只需使用指针超过使用整行的vbuf文本。)

以下示例将这些部分放在一起,并将值解析为"row -> "中的正确位置。仔细看看,如果您有疑问,请告诉我:

hostgraphs

输入文件

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

enum { COLS = 4, MAXH = 16, MAXC = 64 };

int main (int argc, char **argv) {

    char buf[MAXC] = "", vbuf[MAXC] = "";
    char *p = NULL, *rfmt = "%d ->  %[^\n]";
    int row, column, visits, hostgraphs[MAXH] = {0};
    size_t i, j, n = 0;
    FILE *graphs = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!graphs) {
        fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
        return 1;
    }

    while (fgets (buf, MAXC, graphs))
    {
        *vbuf = 0;  /* initialize vbuf, split %d:%d pars into vbuf */
        if (sscanf (buf, rfmt, &row, vbuf) < 1)
            break;

        if (!*vbuf) { /* check vbuf contians values */
            n++;
            continue;
        }

        /* read 1st pair */
        if (sscanf (vbuf, "%d:%d", &column, &visits) != 2) {
            fprintf (stderr, "error: invalid line format\n");
            exit (EXIT_FAILURE);
        }
        hostgraphs[row*COLS+column] = visits;

        p = vbuf;   /* assign p, parse remaining pairs */
        while ((p = strchr (p, ' ')))   /* find space  */
        {
            while (*p < '0' || '9' < *p) /* find digit */
                p++;

            if (sscanf (p, "%d:%d", &column, &visits) == 2)
                hostgraphs[row*COLS+column] = visits;
        }
        n++;    /* advance row count */
    }

    for (i = 0; i < n; i++) {   /* output values */
        printf (" row[%2zu] : ", i);
        for(j = 0; j < COLS; j++) {
            printf (" %2d", hostgraphs[i * COLS + j]);
        }
        printf ("\n");
    }

    if (graphs != stdin)
        fclose (graphs);

    return 0;
}

<强>输出

$ cat ../dat/hostgraph.txt
0 ->  1:50  2:30  3:10
1 ->
2 ->  0:10  3:20
3 ->  1:20  2:10  3:30