从文件读到结构

时间:2013-04-27 02:00:15

标签: c structure fgets scanf

我正在尝试从文件中读取已保存的数据。我试图将缓冲区中的信息从字符串转换为字符,并将其值分配给结构的成员。 似乎数据未被正确访问,当我打印出节点值时,它与文件中的内容不同。我不知道我哪里出错了。

文件格式:

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

来自main的电话:

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

3 个答案:

答案 0 :(得分:1)

您需要在fgets循环中再次呼叫for 。你只是一遍又一遍地读取相同的缓冲区内容。它仍然是第一行,只有一个数字。

答案 1 :(得分: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手册”,以便了解google的内容)。

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分开。在尝试解析之前,你需要先尝试另一行,在这种情况下:

/* 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)

答案 2 :(得分: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;
}