📄 5-5.cpp
字号:
/*第5题 电话簿管理--源代码及关键源代码注解如下:*/
//PhoneBook 1.0 By Mark Miller
#include<fstream.h>
#include<conio.h>
#include<iostream.h>
#include<iomanip.h>
#include<string.h>
#include<stdlib.h>
//全程结构及变量
class friend_node //类类型定义,包括:姓、名和电话号码
{
char last_name[20];
char first_name[15];
char phone_num[12];
friend_node *next,*prev;
char pause;//定义一字符型变量,用于接受输入的任意键
public:
//函数原形说明
void handle_choice(int choice); //处理选择
void add_record();//增加记录
void insert_node(friend_node *new_rec_ptr);//插入节点
friend_node *position_insertion_point(char lastname[20]);//寻找节点插入位置
void make_node_new_head(friend_node *new_rec_ptr);//插入链首
void add_node_to_end(friend_node *new_rec_ptr);//插入链尾
void move_current_to_end();//使当前指针指向链尾
void display_list();//显示链表
void delete_record();//删除记录
void delete_head_of_list();//删除链首
void delete_end_of_list(friend_node *previous_ptr);//删除链尾
void delete_from_middle_of_list(friend_node *previous_ptr);//删除链表中一节点
int verify_delete();//确认是否删除
void delete_node(friend_node *previous_ptr);//删除一节点
void delete_list();//删除链表
void search_by_name();//精确查找某一记录
void modify_record();//修改记录
void write_list_to_file();//将链表写入文件
void load_list_from_file();//从文件中提取链表数据
void help_me();//帮助文件
int welcome();
};
friend_node *head_ptr; //全程变量,链头指针
friend_node *current_ptr; //全程变量,用于指明当前节点在链表中的位置
friend_node *tail_ptr;//全程变量
friend_node *temp_ptr;
//主函数
int friend_node::welcome()
{
cout<<endl<<endl<<endl<<endl<<endl<<endl<<endl<<endl<<endl<<endl;
cout << "\t\t 欢迎使用电话簿管理程序 version_1.0 "<<endl<<endl;
cout<<"\t\t\t 修改及汉化 吴锴"<<endl<<endl;
cout << "\t\t\t~~~按回车键继续~~~";
char str[20];
cin.getline(str,20);//接受输入的任意字符
system("cls"); //执行系统命令:cls-清屏
int choice;
head_ptr = NULL; //初始化链首指针为空
load_list_from_file(); // 从磁盘文件读取链表数据
do
{ //主菜单显示
cout <<"\t《系统菜单》V1.0"<<endl<<"-------------------------------------------------"<<endl;
cout << "\t1 ----- {增加新的电话簿记录}\n\n"; //
cout << "\t2 ----- {显示所有电话簿记录}\n\n"; //
cout << "\t3 ----- {查找确定电话簿记录(姓名精确查找)}\n\n";
cout << "\t4 ----- {删除确定电话簿记录(通过姓氏查找)}\n\n";
cout << "\t5 ----- {修改确定电话簿记录(姓名精确查找)}\n\n";
cout << "\t6 ----- {帮助}\n\n";
cout << "\t7 ----- {退出系统}\n\n";
cout << "---------------------------请选择: ";
cin >> choice;//输入选择
handle_choice(choice); // 调用handle_choice()函数根据选择作出反映,从而调动相应的功能函数
} while(choice != 7); // 返回菜单直到用户选择退出
return 0;//主函数是int,不是void
}
void friend_node::handle_choice(int choice) // 根据用户选择(choice)调用对应处函数
{
switch(choice) // 根据choice的值执行
{
case 1:
add_record(); // 往链表中增加记录
break;
case 2:
display_list(); // 显示链表中所有记录
break;
case 3:
search_by_name(); //精确查找某一记录
break;
case 4:
delete_record(); //找到某记录后删除该记录
break;
case 5:
modify_record();//修改记录
break;
case 6:
help_me();//帮助文件
break;
case 7:
write_list_to_file(); //将数据存入文件并从内存中释放链表所占用的空间
if(head_ptr != NULL)
{
delete_list();
}
break;
default : // 任何其他的选择都将显示出错信息
cout <<"无效的选择!\n";
break;
}
}
void friend_node::add_record() // 在链表中增加一个记录
{
friend_node *new_rec_ptr; // 为新节点申请一指针
new_rec_ptr = new friend_node; // 为新节点分配内存并初始化指针使指向它
if(new_rec_ptr != NULL) // 若分配内存过程中没有出错,获取数据并使节点插入链表
{
system("cls");
// 从用户那里得到姓名和电话号码.
cin.ignore(20,'\n');//清空缓冲区,碰到字符串结束符就结束,从而接受新的字符
//以下程序中出现这一语句表同一意思
cout << "姓: ";
cin.get(new_rec_ptr->last_name,20);
cin.ignore(20,'\n');
cout << "名: ";
cin.get(new_rec_ptr->first_name,15);
cin.ignore(20,'\n');
cout << "电话号码: ";
cin.get(new_rec_ptr->phone_num,15);
cin.ignore(20,'\n');
insert_node(new_rec_ptr);
}
else // 若在分配内存中出错,显示警告信息并不要创建节点
{
cout << "警告: 分配内存出错!新节点不能建立!\n";
}system("cls");
}
// 插入某节点
void friend_node::insert_node(friend_node *new_rec_ptr) //将一个由new_rec_ptr 指向的新节点插入链表中
{
system("cls");
friend_node *before_ptr;
friend_node *after_ptr;
if(head_ptr == NULL)
{ //若链表中没有节点,即链表为空,则将新插入的节点作为链首
head_ptr=tail_ptr = new_rec_ptr;//双向链表
new_rec_ptr->next =new_rec_ptr->prev= NULL; //双向链表
}
else//链表不为空,又分3种情况
{
if(strcmp(new_rec_ptr->last_name, head_ptr->last_name) < 0)
{ //若新的记录小于链首,则将新插入节点
make_node_new_head(new_rec_ptr); // 作为新的链首
}
else // 否则,再继续看应插在何位置
{
current_ptr = position_insertion_point(new_rec_ptr->last_name);//确定应插入的位置
before_ptr = current_ptr; // 用指针保持跟踪节点
after_ptr = current_ptr->next; //在插入点位置的两边
if(after_ptr == NULL) // 若 after_ptr已达链尾,则将新节点插入链尾
{
add_node_to_end(new_rec_ptr);
}
else //否则将节点插入before_ptr和after_ptr各自所向的节点之间
{
before_ptr->next = new_rec_ptr;
new_rec_ptr->next = after_ptr;
}
}
}
}
friend_node *friend_node::position_insertion_point(char lastname[20])//对应后面的实参为new_rec_ptr->last_name
{ // 根据姓氏,返回其在链表中的正确位置。新节点即将插入此点。
char temp_name[20];
int tempint;
if(head_ptr->next != NULL) // 若不指一个节点存在
{ // 搜寻链表找到正确插入点
current_ptr = head_ptr;
temp_ptr = current_ptr->next;
strcpy(temp_name, temp_ptr->last_name);
// 循环直至找到合适的插入位置
tempint = strcmp(lastname,temp_name);
while((tempint > 0) && (current_ptr->next !=NULL))
{
current_ptr = temp_ptr;
// 检测current_ptr所指节点是否即为链尾节点
if(current_ptr->next != NULL)
{
temp_ptr = current_ptr->next;
strcpy(temp_name, temp_ptr->last_name);
tempint = strcmp(lastname,temp_name);
}
}
}
else // 若任何一节点已存在于链表中, 则current_ptr所指即为链首
{ // 新的节点将被加到链表尾部
current_ptr = head_ptr;
}
return(current_ptr);//返回一个地址
}
// 使被new_rec_ptr所指的节点成为链首的函数
// 用来处理插入时的一类特殊情况.
void friend_node::make_node_new_head(friend_node *new_rec_ptr)
{
friend_node *temp_ptr; // 定义一临时指针,保持跟踪链首
temp_ptr = head_ptr; // 使temp_ptr指向当前的链首
new_rec_ptr->next = temp_ptr; // 使欲插入节点的next指针指向当前链首
temp_ptr->prev=new_rec_ptr; //使temp_ptr指针的前向指针指向新插入节点
head_ptr = new_rec_ptr; // 再使欲插入节点成为新的链首,即成功插入新节点至链表首
}
// 使被new_rec_ptr所指的节点成为链尾的函数
// 用来处理插入时的一类特殊情况.
void friend_node::add_node_to_end(friend_node *new_rec_ptr)
{
new_rec_ptr->next = NULL; // 使欲插入节点的next指针指向NULL.
new_rec_ptr->prev=tail_ptr;
move_current_to_end(); // 调用move_current_to_end()函数使current_ptr指向链表尾
current_ptr->next = new_rec_ptr; // 使current_ptr的next指向欲插入节点,从而使欲插入节点成为链尾
}
// 使current_ptr指向链表尾的函数
void friend_node::move_current_to_end()
{
current_ptr = head_ptr; // 把头指针的地址给current_ptr
while(current_ptr->next != NULL)
{ // 遍历链表直至到达链表尾
current_ptr = current_ptr->next;
}
}
// 显示整个链表
void friend_node::display_list()
{
char fullname[36];// 定义一个字符型数组,用来存放姓名
int n;//每屏显示的纪录数
current_ptr = head_ptr; // 把头指针的地址给current_ptr,从而实现遍历链表
if(current_ptr != NULL)
{
cout << endl;
cout << "请输入每屏显示的纪录数:";
cin >> n;
cout << " 姓名 电话号码\n";
cout << "-------------------------------\n";
do
{
int i=1;
while (i<=n&¤t_ptr != NULL)
{
strcpy(fullname,""); // 首先清空fullname
strcat(fullname, current_ptr->last_name); // 以下3行均为字符串处理函数,实现拼接
strcat(fullname, " "); // 拼接为"last_name,first_name"
strcat(fullname, current_ptr->first_name);
cout.setf(ios::right);//设置右对齐
cout << setw(10)<<fullname;
cout.unsetf(ios::left);//设置左对齐
cout.setf(ios::right);//设置右对齐
cout << setw(20) << current_ptr->phone_num << endl;
current_ptr = current_ptr->next; // 使current_ptr指向下一个结点.
cout <<endl;
i++;
}
cout << "按Enter继续 \n";
cin.get(pause);
cin.ignore(1,pause);
} while(current_ptr != NULL); // 循环直到链表尾
system("cls"); }
else // 若链表为空,显示此信息
{
cout << "\n没有记录可显示\n";
}
}
void friend_node::search_by_name() //精确查找某一记录
{
system("cls");
char last_name_string[20];// 定义一字符型数组用来存放last_name
char first_name_string[20]; // 定义一字符型数组用来存放first_name
current_ptr = head_ptr; // 移current_ptr指针至链首
cin.ignore(20,'\n');
cout << "\n请输入你想查询(或修改)者的姓: ";
cin.get(last_name_string,20); //输入姓并保存在last_name_string
cin.ignore(20,'\n');
cout << "\n请输入你想查询(或修改)者的名:";
cin.get(first_name_string,20); //输入名并保存在first_name_string
if(current_ptr != NULL) // 如果 current_ptr 不为空,查找开始
{
while( current_ptr!=NULL )
{
if( strcmp(current_ptr->first_name, first_name_string) == 0 &&
strcmp(current_ptr->last_name, last_name_string) == 0)
{
temp_ptr=current_ptr;
cout << "\n找到信息\n";
cout << endl;
cout << "----------------------------------- ------------\n";
cout << "姓名 电话号码 \n";
cout << "----------------------------------- ------------\n";
cout.unsetf(ios::left);
cout.setf(ios::right);
cout <<current_ptr->last_name << ' '<< current_ptr->first_name ;
cout << setw(36) << current_ptr->phone_num << endl;
}
current_ptr = current_ptr->next;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -