0

我必须为使用列表的电话簿开发一个库函数。此函数必须从列表中删除第 n 个条目。它是一个链表,条目是结构体,包含字符串名称、srnm、nmbr、addr、int 编号和下一个指针。但是,每次我调用该函数时,VS 都会给我很多异常和触发断点,并说我损坏了堆。我不知道我可能在哪里犯了这个破坏堆的错误。请帮助。

这是我到目前为止所做的:

typedef struct list {
  char name[20];
  char srnm[20];
  char nmbr[20];
  char addr[20];
  unsigned int number;/*Contact index*/
  struct list *next;
} entry;

static unsigned int count = 0;
static entry *hol = NULL;/*pointer to the head of the list*/

int delete_contact(unsigned int n) {
  int i=0,k=0;

  if(n>count) return -1;
  hol[n-1].next = hol[n-1].next->next;

  for(i=n;i<count;i++) {
    hol[i]=hol[i+1];
  }


  for(i=n;i<count;i++)
    hol[i].number = hol[i].number-1; /*Updates the contact index*/

  count--; /*Updates the global variable that gives the number of contacts */
  return 0;
}
4

1 回答 1

0

建议的解决方案

hol是一个指针,所以hol[n-1]等可能不会引用entry内存中的结构,请考虑何时n = 0. 无论哪种方式,这都不是您应该访问列表结构中不同条目的方式。

对于单链表,您必须考虑 3 种情况,

  1. 如果n = 0(即第一个条目)正在被删除
  2. 如果要删除的条目在列表中的某处
  3. 如果条目是列表中的最后一个条目。

我的理解number是列表条目的索引,并且您已经为列表条目使用了动态内存分配。此外,由于您似乎使用的是 C89 标准(它不允许循环变量初始化),我已尽我所能将下面的代码改编为 C89,但我自己不使用该标准:

int delete_contact(unsigned int n) {
  int i = 0;
  int k = 0;

  // Check if the index refers to an element not included in the list
  if (n > count) { return -1; }

  entry* tmp = hol;

  if (n == count - 1) {
      // Iterate to the last entry
      while (tmp->next) {
          tmp = tmp->next;
      }

      free(tmp); // Free the list entry

      // Decrement the global counter keeping track of the
      // amount of list elements
      count--; 

      // No need to edit the contact indexes
      return;
  }

  entry* remaining_list = hol;

  if (n == 0) {
      // Free the head of the list

      hol = hol->next;
      remaining_list = hol;

      free(tmp); // tmp points to the head of the list already
  } else {
      // The list entry is somewhere inside the list
      int idx = 0;

      // Iterate until tmp points to the n-1:th entry
      while (idx < n - 1) {
          tmp = tmp->next;
          idx++;
      }

      entry *to_be_freed = tmp->next; // n:th entry
      tmp->next = tmp->next->next;
      remaining_list = tmp->next;

      free(to_be_freed);
  }

  // Decrement the contact index on all the remaining entries
  while (remaining_list) {
      remaining_list->number--;
      remaining_list = remaining_list->next;
  }

  // Decrement the global counter keeping track of the
  // amount of list elements
  count--; 

  return 0;
}

提示

通过创建一个更具表现力的列表接口可能会更好地为您服务,可能是一个不绑定到存储在其中的值的接口。这样你就可以创建一个

list_size()

函数并删除全局计数器。

这里有一些东西可以帮助您入门:

typedef struct node {
    void* value;
    struct node* next;
} node;

typedef struct list {
    node* head;
    node* tail;
    size_t len;
} list;

参考资料

于 2016-06-26T17:35:20.903 回答