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

How to print correctly a linked list with name of persons?

本文关键字:链表 何正确 打印      更新时间:2023-10-16

我做了一个代码,我想打印一个简单的链表,列表的信息包括人名和电话号码。不幸的是,当我打印我的列表时,只有我读到的最后一个人的名字,但电话号码不同。我不知道为什么我的代码不起作用。

所以,这是我的代码

#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

你能帮我修复代码吗?

您的代码中有许多错误:

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

后来:

cin.getline(n, 50); UB here

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

纠正:

char* n = new char[50];
  • 如果你仔细观察你的输出,你会看到什么:

    Andreea 98776489Andreea 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;
}
  • 最后一件事是,一个好的链表将添加和删除节点的函数定义为成员方法,并且应该有析构函数来释放内存