2016-07-16 743 views
-2

我正在学习C中的数据结构,并认为实现相同, 下面是代码和它给怪异的输出,它显示正确的数据时,显示在添加记录功能,但当相同函数被调用从主值改变,我知道它与价值调用有关,但无法弄清楚确切的原因。链接列表添加功能不按预期工作

PS:抱歉,如果程序过长或不按标准

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

struct record; 
typedef struct record data_record; 

struct record{ 
    int data; 
    struct record *next_record; 
}; 

// forward function declarations 
data_record *get_record(); 
void initialize_record(data_record *,int); 
void display_record(data_record *); 
void display_list(data_record *,int); 
data_record *generate_link_list(data_record *,int); 
void add_record(data_record *,data_record,int); 

int main(int argc,char *argv[]) 
{ 
    printf("Initializing the data ... \n"); 
    printf("Data length: %d \n",sizeof(data_record)); 
    int array_length = 5; 

    data_record *start; 
    // generate_list function 
    start = generate_link_list(start,array_length); 
    printf("------------------------------------\n\n"); 
    display_list(start,array_length); 
    printf("Address : %x \n",start); 

    // add the extra item to the existing list 
    data_record record; 
    record.data = 100; 
    record.next_record = NULL; 
    add_record(start,record,2); 
    display_list(start,array_length +1); 

    printf("Terminating the program \n"); 
    return 0; 
} 

data_record *get_record() 
{ 
    return (data_record *)malloc(sizeof(data_record)); 
} 

void initialize_record(data_record *record,int data) 
{ 
    record->data = data; 
    record->next_record = NULL; 
} 

void display_record(data_record *record) 
{ 
    printf("Printing data: \t"); 
    printf("Data: %d \t",record->data); 
    printf("Next Item address: %x \n",record->next_record); 
} 

void display_list(data_record *list,int length) 
{ 
    data_record *list_pointer = list; 
    printf("Printing the list: \n"); 
    int index; 
    for(index = 0;index < length;index++) 
    { 
     display_record(list_pointer); 
     list_pointer = list_pointer->next_record; 
    } 
    printf("Done with the printing \n"); 
} 

data_record *generate_link_list(data_record *list,int array_length) 
{ 
    list = get_record(); 
    initialize_record(list,0); 
    data_record *current_record_pointer, *record; 
    int index = 0; 

    current_record_pointer = list; 

    printf("First record: "); 
    display_record(current_record_pointer); 

    for(index = 1;index < array_length;index ++) 
    { 
     record = get_record(); 
     initialize_record(record,index); 
     current_record_pointer->next_record = record; 
     current_record_pointer = record; 
    } 
    return list; 
} 

void add_record(data_record *list,data_record record,int position) 
{ 
    printf("Start address %x \n",list); 
    printf("New record address %x \n",&record); 
    data_record *list_pointer = list; 
    int list_position = 0; 
    for(list_position = 0;list_position < position - 1;list_position ++) 
    { 
     list_pointer = list_pointer->next_record; 
    } 
    if(list_pointer != NULL) 
    { 
     data_record *next_record = list_pointer->next_record; 
     list_pointer->next_record = &record; 
     record.next_record = next_record; 
    } 
    display_list(list,6); 
} 

从add函数调用时display_list显示正确的,但同样从主叫值改变

附加功能后,当

回答

2

问题是传递给add_recordrecordmain中的record的副本。当参数是一个结构时,这就是通过值传递的方式。所以对record的更改只会影响副本,而不会影响原始副本。

要解决此问题,声明record为指针

void add_record(data_record *list,data_record *record,int position) 
{ 
    ... 

    list_pointer->next_record = record; 
    record->next_record = next_record; 

    ... 
} 

main

add_record(start,&record,2); 

旁注通过记录的地址:这是毫无意义的start传递给generate_link_list由于start不包含generate_link_list需要的任何信息或使用。因此,将其更改为:

data_record *generate_link_list(int array_length) 
{ 
    data_record *list = get_record(); 

    ... 
} 

另注:正如评论所指出的@JonathanLeffler,你应该总是使用get_record函数来创建记录。我会走得更远,并说get_recordinitialize_record应该组合成单一功能create_record,例如,

data_record *create_record(int data) 
{ 
    data_record *record = malloc(sizeof(data_record)); 
    if (record) 
    { 
     record->data = data; 
     record->next_record = NULL; 
    } 
} 

然后在main代码变得

// add the extra item to the existing list 
data_record *record = create_record(100); 
if (record) 
    add_record(start,record,2); 
display_list(start,array_length +1); 

通过使用列表中的create_record所有的记录,你可以放心地在需要的时候free在列表中的项目。

+1

如果你真的很细心,你会注意到在'main()'中定义了'data_record记录;并且在修改后的代码中通过地址传递给'add_record()'。对于这个答案(当前程序)这可以正常工作,但是当你想要释放分配给列表的内存时,这个未分配的记录将成为灾难的根源。确保你统一分配列表中的所有节点。如果不这样做,释放与列表关联的内存将变得非常困难。 –