手机通讯录(结构体实现,链表还不会!)

//global.cpp
int num=0;
//main.cpp
#include<iostream>
#include"add_list.h"
using namespace std;
int main()
{
	linkman man[N];//linkman类型数组man,最多存15个人信息
	char na[N]={0};//存储每个人姓名第一个字母,这种赋值属于字符数组的赋值,区别去字符串的初始化
	int sign[N]={0};//存储联系人编号
	in_data(man,na);//读取数据,并获得联系人数目num
	count i;
	for(i=0;i<num;i++)//给每个联系人一个编号
		sign[i]=i;
	in_turn(na,sign);//对联系人按姓名从小到大排序
	show_data(man,sign);//显示排序后的联系人
	show_function(man,na,sign);//功能界面
}
//add_list.h
extern int num;
struct linkman
{
	char name[10];
	char tel_num[12];//以11位手机号为例说明
	char kind;//联系人分类变量
	char e_mail[30];//邮箱限制在30个字节
};
void in_data(linkman *p,char *q);
#define N 40
typedef int count;
void show_data(linkman *p,int *q);//显示联系人函数
void show_menu();//功能显示菜单
void show_function(linkman *p,char *q,int *r);//功能实现函数
void add_man(linkman *p,char *q,int *r);//添加联系人函数
void out_data(linkman *p,char *q,int *r);//程序退出时将数据保存入文件
void in_turn(char *p,int *q);//将姓名按字母排序,q数组则存放排序后的联系人编号
int com_name(linkman *p,char *q);//比较输入姓名与已存姓名是否有相同的
void edit_man(linkman *p);//修改联系人信息
void del_man(linkman *p,char *q,int *r);//删除联系人
void call(linkman *p);
//add_list.cpp
#include<iostream>
#include<fstream>
#include"add_list.h"
using namespace std;
void in_data(linkman *p,char *q)
{
	ifstream infile;
	infile.open("linkman.txt",ios::in);//只读方式打开,文件必须存在
	if(!infile.is_open())
	{
		cout<<"open error";
		exit(1);
	}
	count i=0;
/***********************************************/
	char ch;//姓名前的第一个字母
	//***********规定:存入姓名的时候必须先存首字母,方便后续按姓名排序
	//***********这里要求先存的首字母应该是另外单独放个数组,只作为排序参考而不显示,文件中要存放
	if(!infile.get(ch))//读取EOF,函数返回值为0,执行if,退出程序
	{
		cout<<"文件为空!";
		//exit(1);//文件为空,不退出,回到功能界面
	}
	else
	{
		infile.seekg(0,ios::beg);//不是空文件,则将指针移动到文件头,开始读取
		while(!infile.eof())//在指向EOF时,还会执行一次,所以,最后一个联系人是空的,什么内容也没有,这个问题暂时先不管
		{
			infile>>q[i]>>p[i].name>>p[i].tel_num>>p[i].kind>>p[i].e_mail;//先将姓名第一个字符存入na数组
			i++;
		}
		num=i;//确定实际联系人数量,不用减一,因为这里读取字符串的情况不会多执行一次
		//show_data(p,q,r);//显示联系人数据//此时联系人还未进行编号,不能显示
	}
	infile.close();
	cout<<"当前文件中有"<<num<<"个联系人"<<endl;
	cout<<"数据读取完成"<<endl;	
	
}
void show_data(linkman *p,int *q)//p指向联系人数组,q指向编号数组sign
{
	count i;
	cout<<num<<endl;
	for(i=0;i<num;i++)
	{
		cout<<"第"<<i<<"个联系人"<<endl;
		cout<<p[q[i]].name<<‘\t‘<<p[q[i]].tel_num<<‘\t‘<<p[q[i]].kind<<‘\t‘<<p[q[i]].e_mail<<‘\n‘;
	}
	cout<<"联系人数据显示完成!"<<endl;
}
void show_menu()
{
	cout<<‘\t‘<<"手机通讯录系统"<<‘\t‘<<endl;
	cout<<"1.添加联系人"<<‘\t‘<<"2.查看联系人"<<‘\n‘;
	cout<<"3.拨打电话"<<‘\t‘<<"4.编辑联系人"<<‘\n‘;
	cout<<"5.删除联系人"<<‘\t‘<<"6.退出"<<‘\n‘;
}
void show_function(linkman *p,char *q,int *r)
{
	char i;
	//in_data(p,q);//读取文件数据放到主函数显示功能界面前
	
	while(1)
	{
		show_menu();//显示功能菜单
		cin>>i;
		switch(i)
		{
			case ‘1‘:add_man(p,q,r);break;//p这里多次传递地址,都是结构体数组首地址
			case ‘2‘:show_data(p,r);break;//显示联系人数据
			case ‘3‘:call(p);break;//拨打电话
			case ‘4‘:edit_man(p);break;//修改联系人数据,
			case ‘5‘:del_man(p,q,r);break;//删除联系人
			case ‘6‘:out_data(p,q,r);break;//退出前保存数据到文件
		}
		if(i==‘6‘)
			break;//如果选择的是退出功能,则在保存数据后退出,否则循环继续
		
	}
}
void add_man(linkman *p,char *q,int *r)
{
	char ch[10];//存储新输入的姓名
	int n;
	cout<<num<<endl;
	cout<<"欢迎来到添加联系人界面:"<<endl;
	cout<<"姓名:";
	cin>>ch;//输入需要添加的姓名
	n=com_name(p,ch);//判断姓名是否已经存在
	if(n>=0&&n<num)//姓名存在
	{
		cout<<endl<<"此姓名已经存在"<<endl;
		return;//姓名存在,直接返回
	}
	else if(n==-1)//姓名不存在则执行以下的添加信息操作
	{
		strcpy(p[num].name,ch);//输入名字
		cout<<"姓名首字母:";
		cin>>q[num];//输入姓名首字母
		r[num]=num;//添加联系人的编号
				   //漏掉了这一句,由于之前初始化的时候,sign数组初值全部为零,也就是代表文本中第一个联系人,刘中华
				  //在没有给联系人标号时,排序自然跟他没关系,输出的时候也输出不到他,按我的程序输出的时候,人数是对的
		         //但是,只是多输出了第一个人而已
		cout<<endl;
		cout<<"手机号:";
		cin>>p[num].tel_num;
		cout<<endl;
		cout<<"类别:";
		cin>>p[num].kind;
		cout<<endl;
		cout<<"电子邮箱:";
		cin>>p[num].e_mail;
		cout<<endl<<"新增联系人成功";
		num+=1;
		in_turn(q,r);//添加联系人后排序,再显示
		show_data(p,r);
		cout<<"添加后的联系人数目"<<num<<endl;
		return;
	}
}
void out_data(linkman *p,char *q,int *r)//q指向na字符数组,r指向sign整型数组
{
	ofstream outfile;//定义文件流对象
	outfile.open("linkman1.txt",ios::out);//以输出方式打开文件,只写操作,新建文件或清空文件内容(文件存在)
	count i;
	for(i=0;i<num;i++)
	{
		outfile<<q[i]<<‘\t‘<<p[r[i]].name<<‘\t‘<<p[r[i]].tel_num<<‘\t‘<<p[r[i]].kind<<‘\t‘<<p[r[i]].e_mail;
		if(i!=num-1)
			outfile<<‘\n‘;//最后一行不输出回车
	}
	cout<<"数据保存完成"<<endl;
	outfile.close();
}
/*********************************************************************************
/*	关于排序后数据的变化说明:排序后,变化的只是na数组,和sign数组中的内容,联系人数组还是
/*原来的顺序,只是在显示的时候按照sign所存的编号顺序即可,文本中存的是什么顺序,内存中man
/*数组的存放也是那个顺序,从i到num
**********************************************************************************/
void in_turn(char *p,int *q)//p对应na字符数组,q对应sign整型数组,按由小到大排序
{
	count i,j,k;
	char ch;int mid; //中转变量
	for(i=0;i<num-1;i++)//趟数n-1
	{
		k=0;
		for(j=num-1;j>0;j--,k++)//每趟比较次数
		{
			if(p[k]>p[k+1])
			{
				ch=p[k];
				p[k]=p[k+1];
				p[k+1]=ch;//姓名首字母交换完成
				mid=q[k];
				q[k]=q[k+1];
				q[k+1]=mid;//联系人编号交换完成
			}
		}
	}
}
int com_name(linkman *p,char *q)//p指向man数组,q指向输入的姓名数组
{
	int n=-1;
	count i;
	for(i=0;i<num;i++)
	{
		n=strcmp(p[i].name,q);//字符串比较函数,可以按排序后的联系人顺序比较也可以直接比较,记住相同的联系人编号即可
		if(n==0)
		{
			cout<<"此姓名已经存在"<<endl;//姓名存在,返回联系人的编号i,这个不影响数据的编辑修改,
										//只是显示的时候按照排序后的顺序显示即可
			return i;//姓名已经存在返回i到num的一个整数
		}
	}
	if(n!=0)
	{
		cout<<"此姓名不存在"<<endl;
		return -1;//这里模仿文件指针位置,姓名不存在返回-1,
	}
}
void edit_man(linkman *p)
{
	cout<<"输入待编辑联系人姓名:";
	char ch[10];
	cin>>ch;
	int n;
	n=com_name(p,ch);//判断姓名是否存在,n则代表了联系人的标号,是第几个联系人
	if(n>=0&&n<num)//姓名存在
	{
		cout<<endl<<"此姓名存在"<<endl;
		cout<<"输入电话号码:";
		cin>>p[n].tel_num;
		cout<<endl<<"输入联系人类别:";
		cin>>p[n].kind;
		cout<<endl<<"输入电子邮箱:";
		cin>>p[n].e_mail;
		cout<<endl<<"信息修改完成"<<endl;	
	}
	else
		return;//姓名不存在直接返回
}
/******************************************************************
/*删除应该有两种思路,一种,从要删除的文职开始,后面的依次往前覆盖,另一种
/*用先输出,再读入的方式,这里用第一种的话,na数组的内容与man数组不对应,需要寻找,
/*较麻烦,用第二种
********************************************************************/
void del_man(linkman *p,char *q,int *r)//q指向sign整型数组
{
	count i;
	int n,k;
	ofstream outfile;
	outfile.open("linkman.txt",ios::out);
	if(!outfile.is_open())
	{
		cout<<"打开失败"<<endl;
		return;
	}
	cout<<"输入要删除的联系人姓名:";
	char ch[10];//存储输入的姓名
	cin>>ch;
	n=com_name(p,ch);//n代表了联系人的编号
	cout<<"要删除的联系人编号"<<n<<endl;
	if(n>=0&&n<num)//姓名存在
	{
		k=0;
		for(i=0;i<num;i++)
		{
			cout<<"r[i]值"<<r[i]<<"n值"<<n<<endl;
			if(n!=r[i])//需要删除的数据不输出
			{
				outfile<<q[i]<<‘\t‘<<p[r[i]].name<<‘\t‘<<p[r[i]].tel_num<<‘\t‘<<p[r[i]].kind<<‘\t‘<<p[r[i]].e_mail;
				k++;
			}
			cout<<"k值"<<k<<endl;
			if(n!=r[i]&&k!=num-1)//k在这里代表的是行数,总共有num-1行,而不是最后一行的标号num-2
			{
				cout<<i<<"  "<<k<<"输出回车"<<endl;
				outfile<<‘\n‘;
			}
		}
		num-=1;//删除数据后的联系人数目
		cout<<"删除后数据输出完成"<<endl;//这个时候再读一次数据,那么就没有之前要删除的数据了
		outfile.close();//输出完毕,关闭文件
		in_data(p,q);//重新读取应该要将原来数据全部清空,我这里没有清空数据,用人数num控制显示,其实后面还是有数据的
		cout<<"删除后的数据读取完成"<<endl;//此时就应该没有要删除的数据了
	}
	else
		return;//姓名不存在直接返回
}
void call(linkman *p)
{
	cout<<"请输入对方姓名:";
	char ch[10];
	cin>>ch;
	int n;//存放所拨打联系人的编号
	n=com_name(p,ch);
	if(n>=0&&n<num)//姓名存在
	{
		cout<<"正在呼叫……"<<endl;
		cout<<"  "<<ch<<"  "<<endl;
		cout<<p[n].tel_num<<endl;
	}
}
	
	

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。