2016-02-23 41 views
2

我要读这样的文件:在阅读下一行之前,我该如何停止?

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 

任何人都可以帮助我吗?

+0

什么是您预期的输出? – Nitish

+5

使用'fgets'来读取整行,然后自行解析该行。 –

+0

你在'n'和'num'之间混淆了吗? –

回答

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"); 
} 

注:我刚才添加的代码,使现有代码的工作,未做您的代码的任何更改。

+0

非常感谢您的帮助! :) –

+0

@AntoniaAntoniou很高兴帮助!欢迎来到SO。如果这个或者其他答案在任何意义上帮助了你,你可以[upvote](https://meta.stackexchange.com/questions/173399/how-to-upvote-on-stack-overflow)来表示感谢和表明答案是有帮助的。 –

0

修复的方法是简单的:除去在fscanf格式字符串后间隔

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

应该通过读取文件,一条线在被简化为

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

文件的第二行总是会因为fscanf不会返回而中断... – LPs

+0

这不是它不起作用的问题我试过了 –

0

fscanf忽略然后换行读第一行后,它移动到下一行和阅读5err1结果1。这是根本原因。您可以添加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"); 
    } 
0

您已经关闭,但您需要找到每个'\n'而不读取文件中下一行值的方法。对于fscanf这是非常困难的,您的输入文件中每行都有不同数量的元素。

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

(你实际上甚至不需要在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 

输出

$ ./bin/hostgraph < ../dat/hostgraph.txt 
row[ 0] : 0 50 30 10 
row[ 1] : 0 0 0 0 
row[ 2] : 10 0 0 20 
row[ 3] : 0 20 10 30 
相关问题