如何正确打印带有人名的链表?

时间:2017-10-14 10:45:46

标签: c++ list char

我做了一个代码,我要在其中打印一个简单的链接列表,列表的信息包含人名和号码电话。不幸的是,当我打印我的列表时,只有我读过的最后一个人的姓名,但电话号码不同。我不知道为什么我的代码不起作用。

所以,这是我的代码

#pragma once

struct Nodd{
   int phone;
   char *name;
   Nodd *next;
};

void InsertList(Nodd *&L,int nr,char *n);
void PrintList(Nodd *&L);


#include <iostream>
#include "Header.h"
using namespace std;
void InsertList(Nodd *&L,int nr, char *n){
    Nodd *p = new Nodd;
    p->name = n;
    p->phone = nr;
    p->next = L;
    L = p;
}

void PrintList(Nodd *&L){
     Nodd *p = L;
     while(p){
       cout << p->name << " " << p-> phone << endl;
       p = p->next;
     }
}

#include <iostream>
#include "Header.h"
using namespace std;

int main(){

    Nodd *L = 0; //L = first element of the linked list
    int nr, i, t;
    char *n;
    n = new char;

    cout <<"Read number of people: ";
    cin >> t;

    for(i = 0; i < t; i++){
        cout << "Name: ";
        cin.ignore(50, '\n');
        cin.getline(n, 50);

        cout << "Phone number: ";
        cin >> nr;
        InsertList(L, nr, n);
    }

    PrintList(L);

    return 0;
}

我编译的是:

阅读人数:2

Name: Elena
Phone number: 99776244

Name: Andreea 
Phone number: 98776489

............................

Andreea  98776489
Andreea  99776244

你能帮我解决一下如何修复我的代码吗?

1 个答案:

答案 0 :(得分:0)

您的代码中有很多错误:

char *n;
n = new char; // A single dynamic character

后来:

cin.getline(n, 50); UB here

正如您所看到的,为单个字符变量分配50个字符,因此它是一个未定义的行为。

要纠正它:

char* n = new char[50];
  • 如果你仔细看看你看到的输出:

    Andreea 98776489 Andreea 99776244

同名,但整数值是正确的!所以你的插入节点功能是正确的,但问题是关于名称。为什么呢?

在插入节点中编写:

p->name=n; // That is not the way you should do it.

纠正于:

  p->name = new char[strlen(n) + 1];
  strcpy(p->name, n);

您必须为每个不共享同一节点的节点分配内容name

  • 此外,当您完成动态内存时,必须释放并清理以避免内存泄漏:

    delete[] n;
    
  • 添加一个函数来释放成员名称的所有节点的内存:

    void FreeupMemory(Nodd*& L){
        Nodd* pTmp = L;
        while(pTmp){
            delete[] pTmp->name;
            pTmp = pTmp->next;
        }
    }
    

在主要打印后节点数据释放内存:

      FreeupMemory(L);
  • 我的建议:只要C ++为您提供了许多强大的类,实用程序就会放弃使用动态数组,因此您可以使用class stringvector。这真的很好,不介意内存泄漏。

  • 请相信我,如果您的成员数据name是一个字符串类对象,您就不会陷入这样容易出错的状态。

    struct Nodd{
        int phone;
        std::string name;
       Nodd *next;
    };
    
    void InsertList(Nodd *&L,int nr, std::string n){
        // your code
        p->name = n; // ok
        // ...
    }
    

主要:

    std::string n;
    for(int i(0); i < t; i++){
        std::getline(std::cin, n);
    }

**还有一件坏事:

为什么要包含标题? “递归包容”?

你可以创建一个头文件“header.h”只包含类接口和函数的原型和另一个源文件“MyLinkedList.cpp”  包括标题。和main.cpp。

// header.h
#pragma once

struct Nodd{
   int phone;
   char *name;
   Nodd *next;
};

void InsertList(Nodd *&L,int nr,char *n);
void PrintList(Nodd *&L);
void FreeupMemory(Nodd*&L);


// MyLinkedList.cpp

#include "header.h"
#include <iostream>
using namespace std;


void InsertList(Nodd*& L, int nr, char* n){
    Nodd *p  = new Nodd;
    p->name  = n;
    p->phone = nr;
    p->next  = L;
    L = p;
}

void PrintList(Nodd *&L){
    Nodd* p = L;
    while(p){
        cout << p-> name << " " << p->phone << endl;
        p = p->next;
    }
}

void FreeupMemory(Nodd*& L){
    Nodd* pTmp = L;
    while(pTmp){
        delete[] pTmp->name;
            pTmp = pTmp->next;
    }
}

// main.cpp

#include <iostream>
#include "Header.h"
using namespace std;

int main(){
    Nodd* L = 0; //L = first element of the linked list
    int nr, i, t;
    char* n = new char[50];

    cout << "Read number of people: ";
    cin >> t;

    for(int i = 0; i < t; i++){
        cout << "Name: ";
        cin.ignore(1, '\n');
        cin.getline(n, 50);

        cout << "Phone number: ";
        cin >> nr;

        InsertList(L, nr ,n);
    }

    PrintList(L);
    FreeupMemory(L);
    delete[] n;

    return 0;
}
  • 最后一件好的链接列表定义了添加和删除节点作为成员方法的函数,并且应该有析构函数来释放内存。