【问题标题】:Head constantly changing in c linked list头在c链表中不断变化
【发布时间】:2017-05-29 09:16:00
【问题描述】:

我正在尝试在 C 中实现一个简单的链表,但似乎没有正确添加第一个元素。 这是我的代码:

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

typedef struct person{
    int phoneNumber;
    char* name;
    struct person *nextPers;
}person;

person* firstPerson=NULL;
person* lastPerson=NULL;

void addPerson (person* _person){
/*Adds a new person to the linked list after the last one added
*/  
if (firstPerson!=NULL){
    fprintf(stderr,"DEBUG(addPerson): First person is %s \n",firstPerson->name);
    fprintf(stderr,"DEBUG (addPerson): Last Person is (before adding the new one) %s \n",lastPerson->name);}
fprintf(stderr,"DEBUG: Adding person %s \n",_person->name);
_person->nextPers= NULL;
if (firstPerson==NULL){
    firstPerson = _person;
    lastPerson= _person;
    fprintf(stderr,"DEBUG: The head of the list is %s \n",firstPerson->name);   

}else{
    fprintf(stderr,"DEBUG: Last person (before adding the new one) %s \n",lastPerson->name);
    fprintf(stderr,"DEBUG (addPerson):Adding to the list %s \n",_person->name); 
    lastPerson->nextPers =_person;
    lastPerson=_person;
    fprintf(stderr,"DEBUG: Last person %s \n",lastPerson->name);
    }
}


int main(int argc, char* argv[]){
    char line[80],name[80];
    int number;
    setvbuf(stdout,(char*)malloc(sizeof(char)*80),_IOLBF,80);
    setvbuf(stdin,(char*)malloc(sizeof(char)*80),_IOLBF,80);

    for(;fgets(line,80,stdin);){
        if(!strcmp(line,"Finish\n"))
              break;

        sscanf(line,"%[^:]: %d",name,&number);
        /* Stores the person introduced from stdin as Name:phone */
        if(firstPerson!=NULL){
            fprintf(stderr,"DEBUG (Before storing new data aparently): First person is %s \n",firstPerson>name);    
        }
        person * newPerson= malloc(sizeof(person));

        newPerson->phoneNumber = number;    
        newPerson->name = name;

        fprintf(stderr,"DEBUG: Adding person %s \n",newPerson->name);
        fprintf(stderr,"DEBUG: phone number %d \n",newPerson->phoneNumber); 

        addPerson(newPerson);

        fprintf(stderr,"DEBUG: There is a new person on the list\n");                   

        }
}

预期的输出是:

Harvey:12345
DEBUG: Adding person Harvey 
DEBUG: phone number 12345 
DEBUG: Adding person Harvey 
DEBUG: The head of the list is Harvey 
DEBUG: There is a new person on the list
Adam:23456 
DEBUG (Before storing new data aparently): First person is Harvey 
DEBUG: Adding person Adam 
DEBUG: phone number 23456 
DEBUG(addPerson): First person is Harvey
DEBUG (addPerson): Last Person is (before adding the new one) Harvey 
DEBUG: Adding person Adam 
DEBUG: Last person (before adding the new one) Harvey
DEBUG (addPerson):Adding to the list Adam 
DEBUG: Last person Adam  
DEBUG: There is a new person on the list

但是,输出却是:

Harvey:12345
DEBUG: Adding person Harvey 
DEBUG: phone number 12345 
DEBUG: Adding person Harvey 
DEBUG: The head of the list is Harvey 
DEBUG: There is a new person on the list
Adam:23456
DEBUG (Before storing new data aparently): First person is (null) //Wrong, its Harvey
DEBUG: Adding person Adam 
DEBUG: phone number 23456 
DEBUG(addPerson): First person is Adam //Wrong, its Harvey
DEBUG (addPerson): Last Person is (before adding the new one) Adam //Wrong, its Harvey
DEBUG: Adding person Adam 
DEBUG: Last person (before adding the new one) Adam //Wrong its Harvey
DEBUG (addPerson):Adding to the list Adam 
DEBUG: Last person Adam 
DEBUG: There is a new person on the list

总结一下,主要思路是得到一个链表就是:Harvey->Adam->(next) 但是不知道哪里出错了。

【问题讨论】:

  • fprintf(stderr, "DEBUG (Before storing new data aparently): First person is %s \n", firstPerson&gt;name); -> fprintf(stderr, "DEBUG (Before storing new data aparently): First person is %s \n", firstPerson-&gt;name);
  • 并注意编译器警告:lastPerson-&gt;nextPers = _person;:这里_person 的类型是person*,而lastPerson-&gt;nextPers 的类型是struct proceso *。你搞混了。
  • 您向我们展示了预期的和实际的输出,这很好,但您也应该展示输入。
  • 最后但同样重要的是:学习如何使用调试器,而不是进行“printf 调试”。它的效率要高得多,而且您花在学习上的时间会很快得到回报。

标签: c linked-list head


【解决方案1】:

你的代码的链表部分是正确的,我知道这会让你发疯。您的代码中还有一些其他错误,与链表无关。

            fprintf(stderr,"DEBUG (Before storing new data aparently): First person is %s \n",firstPerson>name);    

看到你写的是 firstPerson>name 而不是 firstPerson->name,这是进行布尔比较并返回零 - 这就是为什么你有一个“null”。

第二个错误在这里:

    newPerson->phoneNumber = number;    
    newPerson->name = name

您正在将 phoneNumber 设置为名称和号码数组的 指针。因此,当您在这里进行第二次打印时:

DEBUG (addPerson): Last Person is (before adding the new one) Adam //Wrong, its Harvey

它实际上是在检索正确的值 - 因为您将 Harvey 覆盖到了 Adam。

解决方法很简单:将字符串复制到 newPerson 而不是将其指向名称。

newPerson->name = malloc(sizeof(char) * strlen(name) + 1); 
strcpy(newPerson->name, name);

这应该可以解决您的问题。

【讨论】:

    【解决方案2】:

    你犯了一些错误:

    struct proceso *nextPers;
    

    这个没意义,改成

    person *nextPers;
    

    然后保存在结构中的名称指向 name[80](main() 中的 var),因此每次您的 this var 更改时,您的结构中的 var 也会更改。你必须把它复制到你的结构上;

    memcpy(newPerson->name, name, 80);
    

    并将您的结构更改为:

    typedef struct person{
        int phoneNumber;
        char name[80];
        struct person *nextPers;
    }person;
    

    还记得在完成后释放列表中的所有节点

    【讨论】:

      猜你喜欢
      • 2013-09-09
      • 2022-01-01
      • 2015-06-27
      • 1970-01-01
      • 2012-10-29
      • 2016-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多