作业09: 简单的链表运用问题。
1. 定义一个结构体变量(包括年,月,日)编写程序,要求输入年,月,日,程序能计算并输出该日在本年中是第几天。注意润年问题。
2. 运用链表实现电话簿管理:设计一个基本电话簿管理程序,具有加入、删除和显示联系人电话号码的功能。程序要求采用链表数据结构来实现。
/*******第七章,第01题
定义一个结构体变量(包括年,月,日)编写程序,要求输入年,月,日,
程序能计算并输出该日在本年中是第几天。注意润年问题。
*****************************************************************/
#include <iostream>
using namespace std;
struct date
{
private:
int year;
int month;
int day;
public:
void input();
int deal1();
};
void date::input()
{
cout<< "请输入年,月,日,并用空格间开:";
cin >> year >> month >> day;
cout<< endl;
}
int date::deal1()
{
//先用if断断是不是1月和2月的
//再用if判断是不是润年
//后用确定2月份的天数后,后面的天数可以直接加上
/*判断每个月份的天数
31天的月份有:1.3.5.7.8.10.12
30天的月份有:4.6.9.11
28或29天的月份有:2
*/
int n; //设定n为总天数
static int n2;
int d = day;
//31天的
static int n31 = 31;
int& n1 = n31; int& n3 = n31; int& n5 = n31;
int& n7 = n31; int& n8 = n31; int& n10 = n31;
int& n12 = n31;
//30天的
static int n30 = 30;
int& n4 = n30; int& n6 = n30; int& n9 = n30;
int& n11 = n30;
//开始计算
if ( (month==1)||(month==2) )
{
if (month==1)
{
n = d;
return n;
}
if (month==2)
{
n = n1+d;
return n;
}
}
else
{
if (year%4==0&&year%100!=0)
n2 = 29;
else
n2 = 28;
switch(month)
{
case 3 : n = n1+n2+d; break;
case 4 : n = n1+n2+n3+d; break;
case 5 : n = n1+n2+n3+n4+d; break;
case 6 : n = n1+n2+n3+n4+n5+d; break;
case 7 : n = n1+n2+n3+n4+n5+n6+d; break;
case 8 : n = n1+n2+n3+n4+n5+n6+n7+d; break;
case 9 : n = n1+n2+n3+n4+n5+n6+n7+n8+d; break;
case 10 : n = n1+n2+n3+n4+n5+n6+n7+n8+n9+d; break;
case 11 : n = n1+n2+n3+n4+n5+n6+n7+n8+n9+n10+d; break;
case 12 : n = n1+n2+n3+n4+n5+n6+n7+n8+n9+n10+n11+d; break;
}
}
return n;
}
void main()
{
typedef date time; //本句没什么必要用,写出这句是因为想试一下用typedef
time e;
date* p;
p = &e;
(*p).input();
(*p).deal1();
int n = (*p).deal1();
cout<< "该日在本年中是第 " << n << "天" <<endl;
}
/*********链表
运用链表实现电话簿管理:
设计一个基本电话簿管理程序,具有加入、删除和显示联系人电话号码的功能。
程序要求采用链表数据结构来实现。
***********************************/
//问题一:输入N个电话号码,输出的只是N-1个号码
//已解决问题一:将for里面的判断条件改为 pz!=NULL
//问题二:add 函数出现问题。需调试。
//已解决:改了循环的条件,再改了结点的位置,了解到了一点,->next就是该地址的下一地址。
#define NULL 0
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
struct telephone_directory //定义电话簿结构类型
{
string name; //联系人姓名
long num; //电话号码
telephone_directory* next; //结点
};
typedef telephone_directory td; //用typedef声明,指定用td代表telephone_directory类型
long n = 0; //电话簿的内容中的序号
/**** 主函数 **/
/**** 主函数 **/
void main(void)
{
/************************* 定义+声明 ********************************/
td *creat(void); //创建(函数声明)
td *insert(td *,string, int); //加入(函数声明)
td *del(td*,string); //删除(函数声明)
td *show(td*); //显示(函数声明)
td *head; //定义头指针
td tda; //定义这个电话簿的一个变量
string dname; //定义删除的联系人名称
/************************* 输入 ********************************/
cout << "请输入联系人姓名和联系电话:(输入“数字0”结束输入)" << endl;
cout << "序号" << setw(8) << "姓名" << setw(8) << "电话" <<endl;
head = creat(); //返回头指针
show(head); //输出电话簿
/************************* 删除 ********************************/
cout << "请输入要删除的联系电话的姓名:" ;
cin >> dname;
cout << endl;
head = del(head,dname); //删除后链表的头地址
show(head); //输出电话簿
/************************* 加入 ********************************/
cout << "请输入要加入联系人的姓名及电话号码:" ;
string nname;int nnum; //定义一个需加入的姓名,电话。
cin >> nname >>nnum;
cout << endl;
head = insert(head, nname, nnum);//加入后链表的地址
show(head); //输出电话簿
}
/**** 建立链表的函数,返回头指针 ***/
/**** 建立链表的函数,返回头指针 ***/
td *creat(void)
{
td *head; //定义头文件及两个指针
td *pa;
td *pb;
pa = new td; //开辟一个新单元(建立第一个结点),并使pa指向它
cout << ++n << setw(3) <<":"; //输入序号
cin >> pa->name ;
cin >> pa->num;
cout << endl;
/*生成头结点;while(未结束){ 生成新结点; 把新结点插入链表;}*/
head = NULL; //生成头结点(链表头指针初始化)
for ( n=2; pa->num!=0 ; n++)//向链表插新结点
{
if (head==NULL)
head = pa;
else
pb->next = pa; //指向本结点
pb = pa;
pa = new td; //生成新结点
cout << n << setw(3) <<":"; //输入数据
cin >> pa->name ;
cin >> pa->num;
cout << endl;
}
pb->next = NULL; //
delete pa; //释放值为0的结点
return (head); //返回头指针
}
/*********建立一个 删除 结点的函数*************************/
/*********建立一个 删除 结点的函数*************************/
td *del(td *head,string dname)
{
if (head==NULL) //是空表
{
cout << "这是一个空的电话薄,无法删除" <<endl;
return (head);
}
else
{
td *pa;
td *pb;
pa = head; //使pa指向第一个结点
for (;dname!=pa->name && pa->next!=NULL;)//pa所指向的不是要找的结点且不是最后一个结点
{
pb = pa;
pa = pa->next;
}
if ( dname==pa->name ) //假如找到了要删的名字
if ( pa==head )
head = pa->next; //若pa是首地址,则将下一个地址赋予head
else
{
pb->next = pa->next; //否则,将下一结点地址赋予上一结点地址
cout << "删除成功!" << endl;
}
else
cout << "电话簿中找不到" << dname << "这联系人" << endl;
}
return (head);
}
/*************** 建立新结点的函数 ******************/
/*************** 建立新结点的函数 ******************/
td *insert(td * head,string nname, int nnum)
{
td *pa;
td *pb;
for (pa=head; pa->next!=NULL; pa= pa->next);//找到最后结点
pb = new td; //新建一个结点
pa->next = pb; //连接两个结点
pb->name = nname; //赋值
pb->num = nnum;
pb->next = NULL;
return(head);
}
/******** 按序排列并输出电话簿(此处先不排序) *******/
td *show(td *head)
{
td *pz ;
pz = head;
cout << "您输入的电话簿经整理后:" << endl ;
cout << "序号" << setw(8) << "姓名" << setw(8) << "电话" <<endl;
for (n=1; pz!=NULL; n++)
{
cout << n << setw(3) << pz->name << setw(8) << pz->num << endl;
pz = pz->next; //让指针结点指向下一个
}
return(NULL);
}
#include <string>
#include <iostream>
#include <cstdio>
using namespace std;
typedef struct tel
{
string name;
string number;
tel *next;
}TEL;
//root为链表的头指针
TEL *root = NULL;
char menu()
{
cout << "--------" << endl;
cout << "1,登记" << endl;
cout << "2,删除" << endl;
cout << "3,查询" << endl;
cout << "4,列表" << endl;
cout << "0,退出" << endl;
cout << "--------" << endl;
cout << "请选择:";
char choice;
cin >> choice;
cout << endl;
return choice;
}
//从文件加载数据,未实现
TEL* load()
{
return NULL;
}
//把数据保存到文件,未实现
int save()
{
return 0;
}
//登记
void reg()
{
//获取数据
string name;
while(name.empty())
{
cout << "请输入姓名:";
cin >> name;
}
string number;
while(number.empty())
{
cout << "请输入号码:";
cin >> number;
}
//分配新结点
TEL* t = new TEL;
t->next = NULL;
t->name = name;
t->number = number;
//如果root指针为空,则直接赋值root
if(root == NULL)
{
root = t;
}
else
{
//找到最后一个结点,并使它指向新的结点
TEL* p = root;
while(p->next != NULL)
p = p->next;
p->next = t;
}
}
//显示结点数据
void show(TEL* t)
{
cout << t->name << '\t' << t->number << endl;
}
//删除
//采用的方法是:遍历root链表,模糊找查并提供用户是否删除。
//如果用户确认删除当前结点,则移动指针到下个结点继续上面的过程
//如果当前结点无须删除,则将他移动到新的链表中
//最后,将root指向新的链表的第一个结点
void del()
{
cout << "请输入:";
string some;
cin >> some;
//p1指向root,移动p1指针,遍历root
TEL* p1 = root;
//new_root为新链表的头指针
TEL* new_root = NULL;
//p2指向新链表的最后一个结点
TEL* p2 = NULL;
while(p1 != NULL)
{
if(p1->name.find(some) != string::npos ||
p1->number.find(some) != string::npos)
{
show(p1);
cout << "确定删除(y/n):";
char c;
cin >> c;
//找到符合条件的结点,让用户确认删除
if(c == 'y')
{
TEL* temp = p1->next;
delete p1;
p1 = temp;
continue;
}
}
if(new_root == NULL)
{
new_root = p1;
p1 = p1->next;
p2 = new_root;
p2->next = NULL;
}
else
{
p2->next = p1;
p1 = p1->next;
p2 = p2->next;
p2->next = NULL;
}
}
root = new_root;
}
//查询
void query()
{
string some;
cout << "请输入:";
cin >> some;
TEL* p = root;
while(p != NULL)
{
if(p->name.find(some) != string::npos ||
p->number.find(some) != string::npos)
show(p);
p = p->next;
}
}
//列表
void list()
{
TEL* p = root;
int i = 0;
cout << "姓名\t号码\t" << endl;
while(p != NULL)
{
show(p);
p = p->next;
}
}
int main()
{
root = load();
do
{
char c = menu();
switch(c)
{
case '1'://登记
reg();
break;
case '2'://删除
del();
break;
case '3'://查询
query();
break;
case '4'://列表
list();
break;
case '0':
{
int total_saved = save();
cout << total_saved << "items saved." << endl;
exit(0);
}
break;
default:
break;
}
}while(true);
return 0;
}