2013-04-27 82 views
-1

我正在嘗試從文件讀取保存的數據。我試圖將緩衝區中的信息從字符串轉換爲字符,並將其值分配給結構的成員。 似乎沒有正確訪問數據,當我打印出節點值時,它與文件中存儲的內容不同。我不知道我哪裏出錯了。從文件讀入結構

文件格式:

3 2 43 4 
    2 4 5 6 
    $Node 
    4 
    1 0 -1 0 
    2 0 1 0 
    3 10 -1 0 
    4 10 1 0 
    $EndNodes 
    $Elements 
    2 
    1 2 3 4 
    2 3 5 6 
    $EndElements 

代碼:

struct Node { 
     int x; // position             
     int y; //position             
     int z; //position             
     int total_node_nums; // total node numbers       
    }; 

    struct Element{ 
     int total_elmt_num; // total element numbers      
     struct Node *node; // array of nodes        
    }; 

從主召喚:

void arr_creator(char *fname, char *str_start, char *str_end); 

arr_creator:

void arr_creator(char *fname, char *str_start, char *str_end){ 

    FILE *fl_read; 
    char buffer[512], line_buff[20]; 
    int i,num_node,tag,line = 0; 

    fl_read = fopen(fname, "r"); 
    if(fl_read == NULL){ 
     printf("\n[error reading file] :: in function arr_creator\n"); 
     return; 
    } 

    // Scan file for str_start 
    while(fgets(buffer, sizeof(buffer),fl_read) != NULL) { 

     if(strstr(buffer,str_start)){ 
      printf("\nline: %d string: %s \n",line+1, str_start); 

      fgets(buffer,sizeof(buffer),fl_read); 

      num_node = atoi(buffer); 
      printf("num_node = %d\n", num_node); 
      struct Node *node; 
      node = malloc((num_node+1)*sizeof(node)); 

      for(i=1; i<num_node+1;i++){ 

       sscanf(buffer,"%d %d %d %d", &tag, &node[i].x, &node[i].y, &node[i].z); 

       printf("--------------\n"); 
       printf(" Node %d \n", tag); 
       printf("--------------\n"); 
       printf("node[%d].x = %d\n",i, node[i].x); 
       printf("node[%d].y = %d\n",i, node[i].y); 
       printf("node[%d].z = %d\n",i, node[i].z); 
       printf("BUFFER :: %s", buffer); 
      } 
     } 
     line++; 
     if(strstr(buffer,str_end)){ 
      printf("buffer at break :: %s", buffer); 
      // buffer[0] = '\0'; 
      break; 
     } 
    } 
    if(fl_read){ 
     fclose(fl_read); 
    } 
} 
+0

壓痕描述是非常重要的!你的名字已經被列在我的縮進犯名單上。我不會再說這個。如果我們無法讀取您的代碼,我們將不會爲您解決這個問題。得到它了? – Sebivor 2013-04-27 02:10:38

+0

謝謝你的警告。 – 2013-04-27 02:24:20

回答

0

重寫代碼如下

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

struct Node { 
    int tag; 
    int x; //position 
    int y; //position 
    int z; //position 
}; 

struct Nodes { 
    int total_node_num; 
    struct Node *nodes;//array of node 
}; 

struct Nodes *arr_creator(char *fname, char *str_start, char *str_end){ 
    FILE *fl_read; 
    char buffer[512]; 
    int line = 0; 

    fl_read = fopen(fname, "r"); 
    if(fl_read == NULL){ 
     printf("\n[error reading file] :: in function arr_creator\n"); 
     return NULL; 
    } 

    while(fgets(buffer, sizeof(buffer),fl_read) != NULL) { 
     ++line; 
     if(strstr(buffer, str_start)){ 
      int i, num_node;//work 
      struct Node *node;//work 

      printf("\nline: %d string: %s \n", line, str_start); 
      struct Nodes *nodes = malloc(sizeof(struct Nodes)); 
      num_node = nodes->total_node_num = atoi(fgets(buffer,sizeof(buffer),fl_read)); 
      printf("num_node = %d\n", num_node); 
      node = nodes->nodes = malloc(num_node*sizeof(struct Node)); 
      for(i=0;;i++){ 
       fgets(buffer,sizeof(buffer),fl_read); 
       if(strstr(buffer, str_end)){ 
        if(i == num_node){ 
         printf("buffer at break :: %s", buffer); 
        } else if(i < num_node){ 
         fprintf(stderr, "The number of nodes less than the specified!"); 
         nodes->total_node_num = i; 
        } 
        fclose(fl_read); 
        return nodes; 
       } else if(i >= num_node){ 
        fprintf(stderr, "The number of nodes more than the specified!\n" 
            "*read only the number of specified.*"); 
        fclose(fl_read); 
        return nodes; 
       } 
       //read node check print 
       sscanf(buffer," %d %d %d %d ", &node[i].tag, &node[i].x, &node[i].y, &node[i].z); 
       printf("--------------\n"); 
       printf(" Node %d \n", node[i].tag); 
       printf("--------------\n"); 
       printf("node[%d].x = %d\n",i, node[i].x); 
       printf("node[%d].y = %d\n",i, node[i].y); 
       printf("node[%d].z = %d\n",i, node[i].z); 
       printf("BUFFER :: %s", buffer); 
      } 
     } 
    } 
    fclose(fl_read); 
    return NULL; 
} 

int main(void) { 
    struct Nodes *nodes; 
    struct Node *node; 
    int i; 
    nodes=arr_creator("data.txt", "$Node", "$EndNodes"); 
    node = nodes->nodes; 
    for(i=0;i<nodes->total_node_num;++i){ 
     printf("\n Node %d \n", node[i].tag); 
     printf("--------------\n"); 
     printf("node[%d].x = %d\n",i, node[i].x); 
     printf("node[%d].y = %d\n",i, node[i].y); 
     printf("node[%d].z = %d\n",i, node[i].z); 
    } 
    return 0; 
} 
+0

謝謝!這有助於解決未定義的行爲對內存分配和斷言語句的修復。我還從函數中刪除了printf語句並通過main打印。 – 2013-04-27 18:56:48

+0

@butter_pWn這很好。 – BLUEPIXY 2013-04-27 19:00:46

+0

@butter_pWn不要在發佈代碼中保留'assert'語句。我把它放在那裏的目的是爲了說明你的代碼中* wnat可能會出錯*,以這種方式不妨礙最終目標。你應該用正確的錯誤處理來替換那些......這就是爲什麼我把評論放在裏面。 – Sebivor 2013-04-28 17:18:58

1

您需要在for循環中再次撥打fgets。你只是一遍又一遍地讀取相同的緩衝區內容。它仍然是第一行,只有一個數字。

+0

@droog:謝謝,我試過了,它導致了分段錯誤。 – 2013-04-27 02:30:31

+0

查看未定義的行爲答案。他發現了比我更多的問題。 – 2013-04-27 02:34:28

1

您沒有正確分配內存。我提到這四條路線,儘管最後一條是主要犯罪分子,其他人也不太好。通過分配小於所需的空間來存儲struct Node,當您嘗試訪問超出分配的區域時,您會調用未定義的行爲。

num_node = atoi(buffer); 
printf("num_node = %d\n", num_node); 
struct Node *node; 
node = malloc((num_node+1)*sizeof(node)); 

node是一個指針。你期望指針的大小是什麼?這可能不是你想要的。

這很愚蠢,使用int來確定要分配的對象數。如果有人輸入負數呢?請注意我如何處理sscanf返回值。有一天它可能會拯救你。你可以在opengroup scanf manual(請記住「opengroup scanf手冊」,所以你知道谷歌是什麼)閱讀更多。

size_t num_node; /* Suggestion: USE A SIZE TYPE! It's what they're for. */ 
assert(sscanf(buffer, "%zu", &num_node) == 1); 
printf("num_node = %zu\n", num_node); 
struct Node *node; 
node = malloc((num_node+1) * sizeof *node); 

*node不是指針;這是一個實際的對象。你想分配的對象的大小,對不對?

我推測,從您的文件格式來看,行數與每個node分開一行。你會想FGETS另一條線,你嘗試分析它之前,在這種情況下:

/* TODO: Handle read errors, rather than just `assert`ing that the read succeeds */ 
assert(fgets(buffer,sizeof buffer,fl_read) == buffer) 

/* TODO: Handle parsing errors, rather than just `assert`ing that the parsing succeeds */ 
assert(sscanf(buffer,"%d %d %d %d", &tag, &node[i].x, &node[i].y, &node[i].z) == 4) 
+0

謝謝,我一定會添加一個if語句來處理讀取和解析錯誤。 -befp- – 2013-04-27 03:43:23