【问题标题】:C - Linked Lists - Deleting Head - Segmentation FaultC - 链表 - 删除头部 - 分段错误
【发布时间】:2016-06-05 13:03:32
【问题描述】:

我正在为一个班级解决一个问题,我们正在学习 C 语言中的链表。我得到了一段代码来完成,特别是删除节点部分,我在删除头时遇到了问题。每次我尝试删除 head 时,都会收到分段错误。谁能告诉我我做错了什么?

EDIT2 我的老师写了除了查找和删除功能之外的所有东西。

我已经修复了来自莫斯科的绅士和 Petriuc 先生指出的明显错误,但是代码仍然无法运行。确实可以编译,但是head还是有问题。

这里是完整的代码:

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

#include "linkedList.h"

// keep an unsorted array of char *'s, strings.

/*
  Create an empty node, return 0 if fail, 1 if succeed
 */
struct node * createNode() {
  struct node *p = (struct node *) malloc(sizeof(struct node));
  if (p == NULL) return 0;

  p->prev = p->next = NULL;
  p->data = NULL;
}


/*
  Lookup string in the list, return pointer to node of first occurence, NULL if not found.
 */
struct node * lookup(struct node *head, char *s) {
  struct node *p;
  for(p=head; p!=NULL; p=p->next){
    if(strcmp(s,p->data)==0){
      return p;
    }
  // just like print, but check if strcmp(s, p->data) == 0, and if so then return p
  }
  return NULL;
}


/*
  Insert new string into the linked list, return 1 if success, 0 if fail.
 */
int insert(struct node **head, char *newS, int insertDuplicate) {
  struct node *p = lookup(*head, newS);

  if (p == NULL || insertDuplicate) {
    // create a new node, put it at the front.
    p = createNode();
    if (p == NULL) return 0;

    // put the string in the new node
    p->data = (char *) malloc(sizeof(char) * (1 + strlen(newS)));
    if (p->data == NULL) return 0;
    strcpy(p->data, newS);

    // note: make changes and use old head before setting the new head...
    p->next = *head;   // next of new head is previous head

    if (*head != NULL)
      (*head)->prev = p; // previous of old head is new head

    *head = p;         // set the new head
  }

  return 1;
}

/*
  Remove string from list if found, return 1 if found and deleted, 0 o/w.
 */
int delete(struct node **head, char *s) {
  struct node *p,*pr,*ne;
  // first do a lookup for string s, call lookup.
  p=lookup(*head, s);

  if(p==*head){
    *head = p->next;
    free(p);
    return 1;
  }

  if(p!=NULL){
     printf("%s",p);
     pr = p->prev;
     ne = p->next;

     free(p->data);
     free(p);

    if(pr==NULL||ne==NULL){
      return 0;
    }
     pr->next=ne;
     ne->prev=pr;
  // if lookup returns NULL, done, return 0.
  // if lookup returns p, not NULL,
  // pr = p->prev, ne = p->next
  //  set pr->next to ne, ne->prev to pr
  //  but what if pr or ne is NULL
  // and note that we need node **head because if delete head,
  // need to update head pointer back in calling function, in
  // here if you want head probably do *head.  like in insert.
  // also, before the pointer to the one you're deleting is gone,
  // free p->data and p.
    return 1;
  }
  return 0;
}


void print(struct node *head) {
  struct node *p;
  for(p = head; p != NULL ; p = p->next) {
    printf("%s\n", p->data);
  }
}

【问题讨论】:

  • 请说明您在哪一行出现了段错误?
  • free(tmp); 之前为*head 分配了什么值? *head 现在是什么? (例如“它现在指向什么?”)
  • 显示你调用delete的代码并显示lookup函数。
  • 我不知道段错误发生在哪里。我只知道它发生在程序尝试删除 head 之后。

标签: c pointers linked-list segmentation-fault doubly-linked-list


【解决方案1】:

你在做

p->下一个 = *head;

但是 p 没有分配到任何地方。

【讨论】:

  • 那个,以及其他错误:(
  • free(*head); 之后并没有太大的不同。
【解决方案2】:

你的函数没有意义。你调用了函数lookup 3 次。

此外,您还使用未初始化的指针,例如

p->next = *head;

printf("%s",p);
pr = p->prev;
ne = p->next;

函数可以这样写

int delete( struct node **head, char *s ) 
{
    int success;
    struct node *target = lookup( *head, s );

    if ( ( success = target != NULL ) )
    {
        if ( target->prev != NULL )
        {
            target->prev->next = target->next;
        }
        else
        {
            *head = target->next;
        }

        if ( target->next != NULL )
        {
            target->next->prev = target->prev );
        }

        free( target );
    }        

    return success;
}

考虑到函数的第二个参数和函数查找的对应参数应该用限定符const声明

int delete( struct node **head, const char *s ) ;
                                ^^^^^
struct node * lookup( struct node *head, const char *s );
                                         ^^^^^^

【讨论】:

    【解决方案3】:

    简化的 delete() 函数。我内联了lookup(),因为函数本身毫无价值(你需要一个指向指针的指针,而不是要作用的指针)

    /*
      Remove string from list if found, return 1 if found and deleted, 0 o/w.
     */
    int delete(struct node **head, char *s) {
      struct node *tmp;
    
          // first do a lookup for string s, no need to call call lookup.
      for( ;*head; head = &(*head)->next ){
        if (!strcmp( (*head)->data, s)) break;
        }
      if (!*head) return 0; // not found
    
      tmp = *head
      *head = tmp->next
      free(tmp);
      return 1;
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-19
      • 2016-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-31
      相关资源
      最近更新 更多