删除列表中特定值下的元素

时间:2017-06-12 10:44:38

标签: c

到目前为止,我已经编写了这段代码。这是我的结构,但我真正使用的是这个函数中的平均场。

 struct grade
 {
   char *crs;
   int grd;
 };
 struct student
 {
    char *name;
    int yr;
    struct grade grades[3];
    float avg;
    struct student *nxt;

}*root;

现在这是相应的函数,在调用时会导致分段错误。

void delete_failed()
{
    struct student *i=root;
    for (;i->nxt!=NULL;i=i->nxt);
    if (i->nxt->avg<5.00)
    {
      struct student *j=i->nxt;
      i->nxt=i->nxt->nxt;
      free(j);
      delete_failed();
    }
}

2 个答案:

答案 0 :(得分:1)

您的功能存在许多问题。首先,for循环检查i->nxt不是NULL。如果列表为空怎么办?这会使i为NULL并导致崩溃。

其次,for循环跳过大部分列表直到最后一个元素(即i->nxt为NULL时),这似乎并不特别有用。特别是当您开始使用i->nxt做NULL时。

所以在任何一种情况下,你的功能都会崩溃。

这是修订版......

void delete_failed()
{
    struct student *i,*last=NULL,*next_i;
    for (i=root;i!=NULL;i=next_i)
    {
        next_i=i->nxt;
        if (i->avg<5.00)
        {
           if(last)
           {
               last->nxt=i->nxt;
           }
           else
           {
               root = i->nxt;
           }
           if(i->name) free(i->name);
           free(i);
           }
       }
       else
       {
           last=i;
       }
    }
}
  • 它跟踪保留的最后一个元素。这样它就知道你是不是 从列表的开头删除元素并可以更新 相应地root,或者可以将last->nxt指向i->nxt
  • 在执行任何其他操作之前,它会在i->nxt中保留next_i的副本,以便它可以使用它来更新i以进行下一次循环迭代。

  • 它还会释放原先未包含的i->name,并且需要将其视为char *

答案 1 :(得分:0)

我不确定你要做什么,但是......

for (;i->nxt !=NULL;i=i->nxt);

这会将i增加到i == NULL

然后,在该循环之后的代码中,您尝试取消引用i并使用它的值,这是未定义的行为,因此您会遇到段错误。

也许你的意思是:

for (;i->nxt!=NULL;i=i->nxt)
{
  if (i->nxt->avg<5.00)
  {
    struct student *j=i->nxt;
    i->nxt=i->nxt->nxt;
    free(j);
    delete_failed();
  }
}