从ISO C89中的列表中删除条目

时间:2015-12-23 13:34:48

标签: list function heap-memory ansi-c

我必须为使用列表的电话簿开发库函数。 此函数必须从列表中删除第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;
}

1 个答案:

答案 0 :(得分:0)

建议的解决方案

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

对于单链表,您必须考虑3个案例,

  1. 如果n = 0(即第一个条目)被删除
  2. 如果要删除的条目在列表中的某个位置
  3. 如果条目是列表中的最后一个条目。
  4. 据我了解,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;
    

    参考资料