【问题标题】:Function to return a list node apart of a linked list in C在C中返回链表之外的列表节点的函数
【发布时间】:2013-09-26 00:38:41
【问题描述】:

我正在使用这两个结构,第一个保存员工信息,第二个保存列表信息:

typedef struct ListNodeTag{
  int idNumber;
  struct ListNodeTag *next;
} Employee;

typedef Employee Item;

typedef struct {
  int size;
  Item *head;
} List;

我有一个名为 Peek 的函数,我在其中发送一个位置、列表的头部和一个指向 Employee 之外的元素的指针。

void Peek (int position, List *L, Item *X) {

  int i;
  Item *currentPtr;

  currentPtr = L->head;

  for(i = 0; i < position; i++){
    if(currentPtr->next == NULL){
      X = currentPtr;
      break;
    }
    currentPtr = currentPtr->next;
  }

  X = currentPtr;

}

我在这个循环中从 main 调用函数 Peek。

  for(i=0;i<Length(&L);i++){
    Peek(i,&L,&S);
    printf("    %d%\n",idNumber);
  }

它的目的是将列表中的每个成员与员工 ID 打印在新行上。但是,当调用第二个成员时,列表的第一个成员会在 currentPtr = currentPtr-&gt;next; 行发生段错误

我列表中的数据是通过这个插入函数填充的:

void Insert (Item X, int position, List *L) {
  int i;
  Item *currentPtr,*previousPtr;
  Item *temp = malloc(sizeof(Item));

  temp->idNumber = X.idNumber;
  temp->next = NULL;

  previousPtr = NULL;

  if(L->head == NULL){
     L->head = temp;
  }

  else{
    currentPtr = L->head;
    for(i=0;i<=position && currentPtr!=NULL;i++){
      previousPtr = currentPtr;
      currentPtr = currentPtr->next;
    }
    temp->next = currentPtr;
    previousPtr->next = temp;
  }
  L->size +=1;
 }

在打印时,我可以在没有段错误的情况下获得结果,但是,无论列表有多长,它都会重复相同的条目。 EG:长度为 3 我得到:

10925
10925
10925

【问题讨论】:

  • 您有一个 for 循环到每个 next 位置。但是您并没有检查您是否点击了 NULL 的next。但是,这里缺少很多代码,因此很难判断您是如何填充数据的。
  • 我已经添加了我的插入功能以获得更多细节。如果它达到 NULL 那么我想它应该自动中止以避免段错误?
  • 它将如何“自动”中止?如果它引用 NULL 作为下一个指针,它将发生段错误。所以想象一下在循环迭代中,currentPtr-&gt;next 的值为 NULL 的情况。然后currentPtr 的下一个值通过赋值变为NULL。然后下一次通过你尝试的循环,基本上,NULL-&gt;next 将出现段错误。
  • 哦!我添加了一个 if 语句 if(currentPtr-&gt;next == NULL){break;} 但是它也有段错误。错误可能出在我设置下一个指针的方式上吗?
  • 我认为您需要显示更新后的代码。我不确定你把if 放在哪里。但类似的事情可能正在其他地方发生。当你在 C 中使用指针时,你必须仔细考虑它们的使用,以确保它们在你需要的时候被设置为你想要的。

标签: c pointers data-structures struct linked-list


【解决方案1】:

这段代码至少有两个问题。


第一个问题是您的Peek 函数。看最后一行:

X = currentPtr;

回想一下,C 是一种call by value 语言,这意味着这一行只改变了Peek 的本地值X,当Peek 返回时,它被简单地丢弃; main 从未见过。

您需要将Peek 更改为类似

void Peek (int position, List *L, Item **X) {

然后Peek的最后一行应该改为

*X = currentPtr;

因此,您需要将main 作为X 传递的值更改为Peek。你没有说你是如何在你的 main 函数中声明 S 的,但我认为它目前的形式是:

Item *S;

然后您需要将其更改为

Item *S[1];

Peek 调用可以单独保留为

Peek(i,&L,&S);

在这些更改之后,main 将声明一个长度为 1 的 Item 指针数组 S,并将 S 的地址传递给 PeekPeek 的最后一行然后将currentPtr 存储在其值X 所指向的地址处,覆盖数组S 中的第一个Item 指针。


第二个问题是for 循环:

for(i=0;i<Length(&L);i++){
  Peek(i,&L,&S);
  printf("    %d%\n",idNumber);
}

为什么您希望printf 在循环的每次迭代中打印不同的内容? idNumber 在循环中根本没有改变!对于Peek 的(固定)版本,唯一改变的是数组S 的第一个元素,因此您需要类似printf("%d\n", S[0]-&gt;idNumber); 的内容。


您还应该从Peek 的循环中删除X = currentPtr;

if(currentPtr->next == NULL){
  X = currentPtr;
  break;
}

因为它是多余的;在break 语句之后立即运行完全相同的行(在未修改的Peek 中)。

【讨论】:

    猜你喜欢
    • 2021-03-26
    • 2018-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-16
    • 2016-12-15
    • 1970-01-01
    • 2022-01-10
    相关资源
    最近更新 更多