在C中读取具有可变列数的空格分隔文件

时间:2013-10-12 17:17:07

标签: c file variables structure

所以我的文件格式如下:

2
4 8 4 10 6
9 6 74 

第一行实际上是文件后面的行数。我想逐行读取文件(注意每行中有不同数量的标记,但都有格式:1个标记,然后是未指定数量的标记对)并为每一行做两件事:

1)知道这一行中有多少令牌。

2)将每个标记分配给变量。使用类似于以下的结构:

typedef struct {
  unsigned start; //start node of a graph 
  unsigned end;   // end node of a graph
  double weight;  //weight of the edge going from start to end
} edge ;

typedef struct {
  unsigned id;   // id of the node
  unsigned ne;   // number of edges adjacent to node
  edge *edges;   // array of edge to store adjacent edges of this node
} node;

一些代码:

FILE *fin;
unsigned nn;
node *nodes;

fin = fopen ("input.txt", "r");
fscanf(fin,"%u\n", &nn);

nodes = malloc(nn*sizeof(node));

for(i=0; i < nn; i++) { //loop through all the rows
/*grab the row and split in parts, let's say they are part[0], part[1]... */
/*and there are N tokens in the row*/
  nodes[i].id=part[0];
  nodes[i].ne=(N-1)/2; //number of pairs excluding first element
  nodes[i].edges=malloc( (N-1)/2)*sizeof(edge) );
  for(j=0; j< (N-1)/2; j++){
    nodes[i].edges[j].start=part[0];
    nodes[i].edges[j].end=part[2*j+1];
    nodes[i].edges[j].weight=part[2*j+2];
  }
}

我需要弄清楚如何在第一个for循环中进行部分注释,以获取标记的数量,并将每个标记作为一个标记符号进行标记。有什么想法吗?

编辑:为了清楚起见,每一行将有第一个整数,然后是可变数量的对。我想按如下方式存储数据:

如果文件读取

2
4 8 4 10 6 //(2 pairs)
9 6 74 //(1 pair)   

然后

nn=2;

node[0].id=4;
node[0].ne=2; //(2 pairs)
node[0].(*edges) //should be a vector of dimension ne=2 containing elements of type edge

node[0].edges[0].start=4; //same as node[0].id
node[0].edges[0].end=8;
node[0].edges[0].weight=4;

node[0].edges[1].start=4; //same as node[0].id
node[0].edges[1].end=10;
node[0].edges[1].weight=6;

node[1].id=9;
node[1].ne=1; //(1 pair)
node[1].(*edges) //should be a vector of dimension ne=1 containing elements of type edge

node[1].edges[0].start=9; //same as node[1].id
node[1].edges[0].end=6;
node[1].edges[0].weight=74;

1 个答案:

答案 0 :(得分:2)

此代码生成您描述的结果,它初始化您的嵌套结构成员edge,并使用strtok。使用strtok(),除了空格" \n"之外,我还将\ n作为分隔符的一部分,以防止换行符给我们带来麻烦(请参阅下面的其他评论)

注意: 你必须在我指示的位置释放内存,但在此之前,保留中间结果(在结构中)或者它将丢失。< / p>

#include <ansi_c.h>

typedef struct {
  unsigned start;
  unsigned end;
  double weight;
} edge ;

typedef struct {
  unsigned id;
  unsigned ne;
  edge *edges;
} node;

int GetNumPairs(char *buf);

int main(void)
{
    FILE *fp;
    char *tok;
    char lineBuf[260];
    int i=0, j=0;
    int nn; //number of nodes
    char countPairsBuf[260];

    fp = fopen("C:\\dev\\play\\numbers.txt", "r");
    //get first line of file for nn:
    fgets (lineBuf, sizeof(lineBuf), fp);
    nn = atoi(lineBuf);
    //create array of node with [nn] elements
    node n[nn], *pN;
    pN = &n[0];

    //read rest of lines, (2 through end)
    i = -1;
    while(fgets (lineBuf, sizeof(lineBuf), fp))
    {
        i++;
        //get number of items in a line
        strcpy(countPairsBuf, lineBuf);
        pN[i].ne = GetNumPairs(countPairsBuf); //number of edges (pairs)
        if(pN[i].ne > 0)
        {   //allocate *edges struct element
            pN[i].edges = malloc((pN[i].ne)*sizeof(edge));
            //get first item in new line as "line token" and "start"
            tok = strtok(lineBuf, " \n");
            while(tok)
            {
                pN[i].id = atoi(tok);
                //now get rest of pairs
                for(j=0;j<pN[i].ne;j++)
                {
                    pN[i].edges[j].start = pN[i].id;
                    tok = strtok(NULL, " \n");
                    pN[i].edges[j].end = atoi(tok);
                    tok = strtok(NULL, " \n");
                    pN[i].edges[j].weight = atoi(tok);
                }
                tok = strtok(NULL, " \n"); //should be NULL if file formatted right
            }
        }
        else  //pN[i].ne = -1
        {
            //error, file line did not contain odd number of elements   
        }

    }
    //you have to free memory here
    //but I will leave that to you
    fclose(fp);

}


//GetNumPairs
int GetNumPairs(char *buf)
{
    int len = strlen(buf);
    int numWords=0, i, cnt=0;

    for(i=0;i<len;i++)
    {
        if ( isalpha ( buf[i] ) ) cnt++;
        else if ( ( ispunct ( buf[i] ) ) || ( isspace ( buf[i] ) ) )
        {
            numWords++;
            cnt = 0;
        }
    }//if odd number of "words", return number of pairs, else error
    return (((numWords-1)%2) == 0) ? ((numWords-1)/2) : (-1);
}