如何在读取文件时使用malloc链表节点

时间:2015-06-02 19:56:58

标签: c file file-io linked-list malloc

我发布了类似的问题,但我能够进一步缩小问题的范围。我很确定我知道问题是什么,但我一直在想弄清楚如何解决它。

//assuming typedef struct person person;

 struct person{
     char first_n[100];
     char last_n[100]; 
     char middle_n[100];
     struct person* next;
};


void open_file_and_read(char* file){
     FILE* fp = fopen(file_name, "r");
     if (fp != NULL){
         while (!feof(fp)){
               person* person = malloc(sizeof(person));
               person->next = NULL;
               while (fscanf(fp, "%s %s %s", person->first_n, person->last_n, person->middle_n) == 3){
                   add_to_contacts(person);
               }
         }
      }
}  

void open_write_file(char* file){
    FILE* filep = fopen(file, "w");
    person* copy;
    for (copy = front; copy != NULL; copy=copy->next){
            fprintf(filep, "%s %s %s\n", copy->last_n, copy->first_n, copy->middle_n);
    }
    fclose(filep);

}

void add_to_contacts(person* person){
    printf("last_name: %s", person->last_name);
    if (head == NULL){
        person->next = head;
        head = person;
    else{
        person->next = head;
        head = person;
    }
}


int main(int argc, char * argv[])
{
char* inputFilename = argv[1];
if (inputFilename == NULL){
    inputFilename = "myRolodex";
}
open_read_file(inputFilename);
char command;
while (command != 'Q' && command != 'q'){
    printf("STARTING TO READ COMMAND\n");
    command = read_command(inputFilename);
    evaluate_command(command);
}
open_write_file(inputFilename); 
clear_rolodex();

printf将文件中的所有内容打印为一个节点。例如:文件包含:
Bob Lee Steve Mike Steven Noel first, last, middle
James Nguyen Lee

printf打印出LeeStevenNguyen。这些应该是分开的。

我认为问题与malloc只被调用一次有关,而我真正需要的是每次扫描时调用它。但是我无法在person* person = malloc(sizeof(person));循环下移动while...fscanf,因为fscanf依赖于已创建person。那么我该怎么做每个新人的mallocing。类似的任务将在几个小时内到期,我花了最后10个小时试图让一切工作,我相信这是最重要的部分。

谢谢

编辑以获取更多详细信息:我的add_to_contacts函数中有一个print语句,用于打印出node-> lasts_name。我还在排序功能(未发布)之前添加了一个print语句,并且无限打印

2 个答案:

答案 0 :(得分:0)

有几种方法可以解决这个问题。

我认为最符合你想要的是:

               person* person = malloc(sizeof(person));
               person->next = NULL;
               while (fscanf(fp, "%s %s %s", person->first_n, person->last_n, person->middle_n) == 3){
                   add_to_contacts(person);
                   person = malloc(sizeof(person));
                   person->next = NULL;
               }
               free(person);

这假设add_to_contacts插入了malloc&#d; d 指向数据结构的指针,所以我们需要下一个fscanf来放置它 数据位于不同的位置。

完成此操作后,将始终分配一个person* 最后实际上并没有传递给add_to_contacts,所以我们 当循环退出时,可以而且应该释放该指针。

略有变化

               person* person = malloc(sizeof(person));
               while (fscanf(fp, "%s %s %s", person->first_n, person->last_n, person->middle_n) == 3){
                   person->next = NULL;
                   add_to_contacts(person);
                   person = malloc(sizeof(person));
               }
               free(person);

(这个想法是唯一需要person->next = NULL;的东西 这大概是add_to_contacts(person),并推迟 person->next = NULL;直到最后一刻我们不必打电话 它在循环之外以及循环内部。)

另一种(完全不同的)方法是 声明局部变量,让fscanf写入它们, 并将它们复制到循环内新分配的person

第三种方法是使person成为堆栈分配(不是malloc< d; d)变量, 并让add_to_contacts按顺序制作自己的malloc副本 将副本插入数据结构中。

但最后两个选项涉及fscanf将数据写入一个地方 然后必须将其复制到另一个,以便将其放入更大的结构中。看来你可能想避免复制。

答案 1 :(得分:0)

关于这部分问题:

相信问题与malloc只被调用一次有关,当我真正需要的是每次我scanf时调用它。但是我无法移动person * person = malloc(sizeof(person));在while ... fscanf循环下,因为fscanf依赖于已经创建了一个人

建议fscanf()为局部变量(记得在格式参数上使用长度修饰符以避免缓冲区溢出。

然后,在循环内,malloc,错误检查,复制变量,调用函数将malloc内存插入到链表中。