这里分了四部分,不喜欢一堆堆代码挤在一起的,开了个项目写的这些代码,我觉得是很通俗易懂的那种代码了,具体链表实现的讲解,以及对指针的运用,请移步各大教学视频/文档
代码的具体解释请看注释哟~
1.List.h
#ifndef LIST_H_
#define LIST_H_
const int size = 40;
//数据域
struct Data
{
char name[size];
int account;
};
//结点
struct Node
{
Data data;
Node *next;
};
//管理结点的类
class NodeManager
{
private:
int length;
Node headNode;
public:
NodeManager();//对头节点进行初始化
void addNode(Node *newNode);//添加结点
int findIndex(const char *name);
void removeNode(const char *name);//删除结点
Node* findNode(const char *_name);
void insertNode(const char *_name, Node *newNode);//插入结点
void updateNode(const char *oldName, char *newName, double acc);//修改节点
void showNode() const;//查看结点
};
//这里是我嫌弃一堆堆的代码出现在main函数里加的
void Add(NodeManager* manager);
void Remove(NodeManager* manager);
void Insert(NodeManager* manager);
void Update(NodeManager* manager);
#endif
2.List.cpp
#include<iostream>
#include<cstring>
#include"list.h"
NodeManager::NodeManager()
{
strcpy(headNode.data.name, "");
headNode.data.account = 0.0;
headNode.next = NULL;
length = 0;
}
void NodeManager::addNode(Node *newNode)
{
if(headNode.next==NULL)
headNode.next = newNode;
else
{
//创建临时结点去遍历
Node *temp = headNode.next;
while(temp->next!=NULL)
temp = temp->next;
//直到遍历到最后一个,也就是temp->next==NULL
temp->next = newNode;
newNode->next = NULL;
}
++length;
}
//为了提供方便(虽然现在只有删除用到了下标,但是以防万一,这是用来找对应的名字的对象的下标的)
int NodeManager::findIndex(const char *_name)
{
Node *temp = headNode.next;//从头节点的指针开始找
int index = 0;
while(temp!=NULL)//注意这里是temp,而不是temp->next
{
if(strcmp(temp->data.name, _name)==0)
return index;
else
{
++index;
temp = temp->next;
}
}
//temp==NULL
std::cout << "This guy's not on the list!\n";
return -1;//因为前面有可能index=0,所以这里得是负数了
}
void NodeManager::removeNode(const char *_name)
{//这个有图解
int index = findIndex(_name);
if(index==-1)
return;
else
{
Node *temp = &headNode;//要注意这里是头节点
int s_index = 0;//开始遍历的下标,也就是记录temp指到第几个了
while(temp->next!=NULL)
{
if(s_index==index)
break;
else
{
++s_index;
temp = temp->next;
}
}
/*
注意这里,如果要删除的数据是最后一个的话,就不能用下面那种:
temp->next->next,这里会造成指针越界,因为next->next已经是NULL了
*/
if(s_index==length)
{
temp->next==NULL;
delete temp;
}
else//不是最后一个数据执行这里
{
Node *nextNextNode = temp->next->next;
/*
防止指针释放不干净,所以要将指针的地址指向NULL(只是地址,不影响内容)
比如你要添加一个新的节点放末尾
结果计算机又分配到了这个被释放的指针
而这时候又没有初始化,则这个指针可能还指着某个节点
*/
temp->next->next = NULL;
delete temp->next;
temp->next = nextNextNode;
--length;
}
}
}
//找对象,这里下面两个都用到了相同功能的代码,方便!
Node* NodeManager::findNode(const char *_name)
{
Node *temp = headNode.next;
while(temp!=NULL)
{
if(strcmp(temp->data.name, _name)==0)
return temp;
else
temp = temp->next;
}
//temp==NULL
std::cout << "This guy's not on the list!\n";
return temp;
}
void NodeManager::insertNode(const char *_name, Node *newNode)
{//这个有图解
Node *temp = findNode(_name);
if(temp==NULL)
return ;
else
{
newNode->next = temp->next;
temp->next = newNode;
++length;
}
}
void NodeManager::updateNode(const char *oldName, char *newName, double acc)
{//其实这里的参数,可以跟上面的一样,主要看后面Menu.cpp咋写,就是交互问题,这里分两种方法展示了
Node *temp = findNode(oldName);
if(temp==NULL)
return;
else
{
strcpy(temp->data.name, newName);
temp->data.account = acc;
}
}
void NodeManager::showNode() const
{
if(length==0)
{
std::cout << "Empty!\n";
return;
}
using std::cout;
Node *temp = headNode.next;
for(int i=0; i<length; i++)
{
cout << "第" << i+1 << "个数据:\n"
<< " Name: " << temp->data.name
<< "\tAccount: " << temp->data.account << '\n';
temp = temp->next;
}
}
3.Menu.cpp
//这一整个cpp文件就是因为我嫌挤在一起丑弄的
#include<iostream>
#include"list.h"
using std::cout;
using std::cin;
void Add(NodeManager* manager)
{
Node *temp = new Node;
temp->next = NULL;
cout << "请输入用户的姓名和账户密码:\n";
cin.get();
cin.getline(temp->data.name, size);
cin >> temp->data.account;
manager->addNode(temp);
cout << "Add successfully!\n";
}
void Remove(NodeManager* manager)
{
char _name[size];
cout << "请输入要删除的用户的姓名:";
cin.get();
cin.getline(_name, size);
manager->removeNode(_name);
cout << "Remove successfully!\n";
}
void Update(NodeManager* manager)
{
char _name[size], nName[size];
int acc;
cin.get();
cout << "请输入要修改的用户的姓名:";
cin.getline(_name, size);
cout << "请输入新的用户名和密码:\n";
cin.getline(nName, size);
cin >> acc;
manager->updateNode(_name, nName, acc);
cout << "Update successfully!\n" ;
}
4.main.cpp
#include<iostream>
#include"list.h"
int main()
{
using namespace std;
NodeManager* manager = new NodeManager;
bool isExit = true;
int input;
char _name[size];
while(isExit)
{
cout << "\t1.添加数据" << endl
<< "\t2.删除数据" << endl
<< "\t3.修改数据" << endl
<< "\t4.查看数据" << endl
<< "\t5.退出" << endl
<<"--------------------------------------" << endl;
while(!(cin>>input))
{
cin.clear();
while(cin.get() != '\n')
continue;
cout << "请重新输入!\n" ;
}
system("cls");
switch(input)
{
case 1:
Add(manager);
break;
case 2:
Remove(manager);
break;
case 3:
Update(manager);
break;
case 4:
manager->showNode();
break;
case 5:
isExit = false;
break;
default:
cout << "请重新输入!" << endl;
}
}
}
有什么问题欢迎来提问鸭~
也欢迎各位大佬们前来指正!