2013-10-12 3 views
1

Так что есть файлы в формате следующим образом:Чтения пробелов файл с переменным числом столбцов в C

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]; 
    } 
} 

Мне нужно, чтобы выяснить, как сделать часть comented внутри первого для цикла, чтобы получить количество жетонов, и каждый из них, как маркер simgle для asign. Есть идеи?

EDIT: чтобы все было ясно, каждая строка будет иметь первое целое число, а затем переменное количество пар. Я хочу, чтобы хранить данные следующим образом:

если файл читает

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

[strtok] (http://en.cppreference.com/w/c/string/byte/strtok) – P0W

+0

Так на самом деле вы не знаете, как прочитать файл в C **? ** потому что этот код отсутствует. –

+0

Вы хотели разделить строки, Gunb нужно искать '\ n' в файле для чтения строк. И, конечно же, после этого синтаксиса с использованием 'strtok()' –

ответ

2

Этот код дает результаты, которые вы описали, он инициализирует свой гнездовой STRUCT член edge и использует strtok , С strtok(), я включил \ п как часть разделителя в дополнение к пространству " \n" для предотвращения новой строки давать нам проблемы (см другие комментарии об этом ниже)

Примечание: вы должны освободить память где я указал, но прежде чем вы это сделаете, сохраните промежуточные результаты (в структурах) или они будут потеряны.

#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); 
} 
+0

Хорошо , плохо отредактируйте это. Для чего используются члены «start» и «end»? – ryyker

+0

'start' и' end' представляют начальный и конечный узлы ребра в графе. Я не очень хорошо знаком с синтаксисом '++ i'. Он использует старое значение 'i', а затем увеличивает его значение? – gunbl4d3

+0

@ryyker \ n не требуется в strtok; это даже смутило меня :) –

Смежные вопросы