在LinkedList中获取分段错误

时间:2017-06-29 07:31:00

标签: c++

我在此代码中遇到了分段错误,但我没有看到任何原因 我检查head是否为NULL然后它将被初始化为temp。

void insertFirst(int id,char *name){
    struct Student *temp;
    temp->id=id;
    strcpy(temp->name,name);
    temp->next=NULL;
    temp->prev=NULL;
    if(head==NULL){
        head=temp;
    } else{
        temp->next=head;
        head->prev=temp;
        head=temp;
    }
}
void append(int id, char *name){
    struct Student* temp;
    temp->id=id;
    strcpy(temp->name,name);
    temp->next=NULL;
    temp->prev=NULL;
    if(head==NULL){
        head=temp;
    } else{
        while(head->next!=NULL){
            head=head->next;
        }
        head->next=temp;
        temp->prev=head;
    }
}

1 个答案:

答案 0 :(得分:0)

此代码存在许多问题。

只是一个有效的例子

Complete example

有解释的错误

假设

到目前为止,我们还没有完整的问题定义,因此我对您的代码做了几个假设。

Student定义

struct Student {
  int id;
  char* name;
  Student* next;
  Student* prev;
}; 

head是全局变量

致命错误

未初始化的指针

指针只是某种整数。所以当你写:

struct Student* temp;

您只需创建整数值而无需初始化。 最好始终正确初始化变量,例如使用NULL值:

struct Student* temp = NULL;

结构实例化

以下代码未创建Student

的内容
struct Student* temp;

相反,它只是创建一个指针,如上所示。 要实际实例化Student,您必须写下这样的内容:

struct Student* temp = NULL;
temp = new Student;

或shorlty:

struct Student* temp = new Student;

此处将创建Student的新实例。

使用单位指针复制字符串

此问题与第一个类似。 实例化Student后,Student::name点无处(实际上它指向内存中的某处)。 在复制name之前,您必须为该副本分配内存&在那里点Student::name。为此,我们要:

  • 获取要分配的内存(在这种情况下为字符数)。

    size_t chars_count = strlen(name);
    
  • 分配所需的内存。

    char* pointer_to_string = new char[chars_count];
    
  • 将指针值指定给Struct::name

    temp->name = pointer_to_string;
    

或者很快:

temp->name = new char[strlen(name)];

追加功能

head是全局变量,必须指向学生列表的开头。 但在append函数中,此代码:

while(head->next != NULL) {
  head = head->next;
}

将在每次迭代时重新分配head。因此,在第一次循环执行后,head将指向最后一个列表条目。 为避免这种情况,我们要使用其他变量,指向当前元素。

struct Student* pCurrent = head;
while(pCurrent->next != NULL) {
  pCurrent = pCurrent->next;
}

以下代码将相对更改:

pCurrent->next=temp;
temp->prev=pCurrent;

P.S。这不是此代码中的完整错误列表,但应该使其正常工作。

Recomendations

从我这边添加几个风格的推荐。 完整的代码示例根据主题创建。

代码重复。 此示例中的每个函数都使用完全相同的代码创建新的Student实例。 为避免这种情况,我们要添加新功能:

Student* createStudent(const int id, const char* name, Student* pNext, 
                       Student* pPrev) {
  struct Student* pStudent = new Student;
  pStudent->id = id;
  pStudent->name = new char[strlen(name)];
  strcpy(pStudent->name, name);
  temp->next = pNext;
  temp->prev = pPrev;
  return pStudent;
}

尽可能使用const。

两个函数的签名包含:

functionName(int id, char* name)

但很可能您不会更改提供的ID或名称,因此请将其替换为:

functionName(const int id, const char* name)

将头部作为参数传递。

我们要避免使用全局变量来控制更多。