这是一个比较简单的程序,对链表的要求不是很高(双向链表,单向链表,内核链表也可以),我给大家带的是双向链表的使用。
首先要通讯录的功能,能够新增联系人,删除联系人,修改联系人信息,查询联系人信息,显示联系人的信息。
根据功能要求对链表进行操作
首先建立一个结构体
//定义一个结构体
typedef struct node
{
char name[name_max];
char number[number_max];
char home[home_max];
char classfy;
struct node *prev;
struct node *next;
}node;
定义联系人的姓名,电话号码,家庭地址,宏定义了#define name_max 20
大家可以根据需求进行修改。
对链表进行初始化节点
node *initList(void)
{
node *new=malloc(sizeof(node));
if( new == NULL )
{
printf("malloc fail\n");
return NULL;
}
new->name;
new->number;
new->home;
new->classfy;
new->prev=new;
new->next=new;
return new;
}
//从尾部插入节点信息
void insets(node *head,node *new)
{
new->prev=head->prev;
new->next=head;
head->prev->next=new;
head->prev=new;
}
这里我插入链表用的是尾插法(尾插法更符合人类的书写习惯)
链表初始化已经完成,开始写main函数
int main(void)
{
int sort;
int flag=1;
char ch;
node *head,*new;
head=initList();
redyun_number();
while(flag)
{
printf("\033[0;32;34m""===================通讯录====================\n");
printf("=====按下a:新增联系人 按下b:显示联系人=====\n");
printf("=====按下c:查找联系人 按下d:删除联系人=====\n");
printf("=====按下s:修改联系人 按下p:退出通讯录=====\n");
printf("=====按下y:上传云文件 按下q:清空联系人=====\n");
printf("=====按下t:进行联系人排序 =====\n");
printf("=======每次新增联系人会自动上传云文件========\n""\033[m");
printf("\033[1;31m""每次操作通讯录后需上传文件保存!\n");
printf("\033[1;31m""注意删除联系人之前请上传云文件,防止数据丢失,清空通讯录后请勿上传云文件,防止数据被覆盖,无法找回!!!\n""\033[m");
ch=getchar();
switch (ch)
{
case 'a':
new_number(head,new);
break;
case 'b':
show_number(head);
break;
case 'c':
find_number(head);
break;
case 'd':
del_number(head);
break;
case 's':
date_number(head);
break;
case 'p':
flag=0;
break;
case 'y':
yun_number(head);
break;
case 'q':
clear_number(head);
printf("\033[1;31m""通讯录在清空中......\n");
sleep(2);
printf("清空完成\n");
break;
case 't':
sort=sort_number(head);
if(sort !=0)
{
printf("\033[1;34m""联系人排序中......\n");
sleep(2);
printf("排序完成\n");
}
else
{
printf("\033[0;32;31m""联系人中无数据,无法排序\n");
}
break;
default:
break;
}
while(getchar()!='\n');
}
return 0;
}
想必大家对链表的操作和熟练掌握程度比我都高,我就不一一细说了。
全部代码都在这了,有需要的小伙伴可以看一下。
比较注意的几个点
(1)通讯录中允许存在同名同姓的人查找时如果用常规遍历查询只会查询到一个,所以在代码中我写了两个查询函数,一个是查询数据使用的查询函数fine_number()。还有一个是删除或修改查找的函数fine_dnumber() 注意查找删除或是修改联系人的必须是姓名和电话号码一致,才能正确返回节点的地址,否则会出现误删情况
(2)通讯录中的姓名可以同名同姓,但电话号码独一无二,在新增联系人的同时,需要遍历链表查询是否出现相同的电话号码,如果出现则需要重新输入,或退出编辑
本代码仅供参考,帮助一些困难的同学容易理解,如对代码有疑惑可以留言(仅对代码有解释,其他的我也不会QAQ)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include<time.h>
#define name_max 20
#define number_max 20
#define home_max 20
//定义一个结构体
typedef struct node
{
char name[name_max];
char number[number_max];
char home[home_max];
char classfy;
struct node *prev;
struct node *next;
}node;
//生成新的一个节点保存数据
node *initList(void)
{
node *new=malloc(sizeof(node));
if( new == NULL )
{
printf("malloc fail\n");
return NULL;
}
new->name;
new->number;
new->home;
new->classfy;
new->prev=new;
new->next=new;
return new;
}
//从尾部插入节点信息
void insets(node *head,node *new)
{
new->prev=head->prev;
new->next=head;
head->prev->next=new;
head->prev=new;
}
//新增联系人并且无重复电话号码
int new_number(node *head,node *new)
{
node *p;
new=initList();
printf("\033[0;32;32m""新增联系人的姓名:\n");
scanf("%s",new->name);
printf("新增联系人的电话:\n");
scanf("%s",new->number);
//遍历链表查看是否有重复电话号码
for(p=head->next;p!=head;p=p->next)
{
while(strcmp(p->number,new->number)==0)
{
printf("该电话号码已存在是否需要继续编辑\n");
printf("按下a继续进行编辑\n");
printf("按下b退出本次编辑\n");
while(getchar()!='\n');
switch(getchar())
{
case 'a':
printf("新增联系人的电话:\n");
scanf("%s",new->number);
break;
case 'b':
return 0;
default:
break;
}
}
}
printf("新增联系人的家庭住址:\n");
scanf("%s",new->home);
srand((int)time(0));
new->classfy=rand()%26+65;
insets(head,new);
printf("联系人写入中......\n");
sleep(1);
printf("联系人写入通讯录成功\n");
//每次新增联系人时将联系人信息写入文本
FILE *fp;
fp=fopen("number.txt","r+"); //文件读写权限
if(fp == NULL)
{
printf("云文件打开失败\n");
}
for(p=head->next;p!=head;p=p->next)
{
fwrite(p,sizeof(node),1,fp);
fprintf(fp,"%c",'\n');
}
fclose(fp);
}
//显示联系人的信息
void show_number(node *head)
{
node *p=NULL;
p=head->next;
if(p!=head)
{
printf("\033[1;32m""正在显示联系人信息中.......\n");
}
for(p=head->next;p!=head;p=p->next)
{
sleep(1);
printf("\033[1;32m""姓名:%s\n",p->name);
printf( "电话号码:%s\n""\033[m",p->number);
printf( "\033[1;34m""家庭住址:%s\n",p->home);
printf("第%c组\n""\033[m",p->classfy);
printf("\n");
}
}
//不删除使用的查找
void find_number(node *head)
{
node *p=NULL;
char name[name_max];
char number[number_max];
printf("\033[1;32m""输入联系人:\n");
scanf("%s",name);
printf("输入联系人电话号码:\n");
scanf("%s",number);
for(p=head->next;p!=head;p=p->next)
{
if(strcmp(p->name,name) == 0 || strcmp(p->number,number) == 0)
{
sleep(1);
printf("\n");
printf("姓名:%s\n",p->name);
printf("电话号码:%s\n",p->number);
printf("家庭住址:%s\n",p->home);
printf("第%c组\n",p->classfy);
printf("\n");
}
}
}
//删人使用的查找
node *find_dnumber(node *head)
{
node *p=NULL;
char name[name_max];
char number[number_max];
printf("\033[1;31m""输入联系人:\n");
scanf("%s",name);
for(p=head->next;p!=head;p=p->next)
{
if(strcmp(p->name,name) == 0 )
{
sleep(1);
printf("\n");
printf("姓名:%s\n",p->name);
printf("电话号码:%s\n",p->number);
printf("家庭住址:%s\n",p->home);
printf("第%c组\n",p->classfy);
printf("\n");
}
}
printf("输入联系人电话号码:\n");
scanf("%s",number);
printf("查找联系人中......\n");
sleep(1);
for(p=head->next;p!=head;p=p->next)
{
if(strcmp(p->name,name) == 0 && strcmp(p->number,number) == 0)
{
return p;
}
}
return NULL;
}
//删除联系人
int del_number(node *head)
{
node *del;
del=find_dnumber(head);
if(del == NULL)
{
printf("\033[1;31m""查无此人\n");
}
else
{
del->prev->next=del->next;
del->next->prev=del->prev;
del->next=del;
del->prev=del;
printf("删除联系人中......\n");
sleep(2);
printf("删除成功\n");
free(del);
}
}
//修改联系人
int date_number(node *head)
{
int flag=1;
char sh;
node *date;
date=find_dnumber(head);
if(date == NULL)
{
printf("查无此人\n");
return 0;
}
else
while(flag)
{
printf("\n");
printf("姓名:%s\n",date->name);
printf("电话号码:%s\n",date->number);
printf("家庭住址:%s\n",date->home);
printf("第%c组\n",date->classfy);
printf("\n");
printf("你需要修改什么:\n");
printf(" a.名字\n");
printf(" b.电话号码\n");
printf(" c.家庭住址\n");
printf(" q.分组\n");
printf(" d.退出修改\n");
while(getchar()!='\n');
sh=getchar();
switch(sh)
{
case 'a':printf("修改后的名字:\n");
scanf("%s",date->name);
printf("修改信息中请勿乱动......\n");
sleep(1);
printf("修改信息成功\n");
break;
case 'b':printf("修改后的电话号码:\n");
scanf("%s",date->number);
printf("修改信息中请勿乱动......\n");
sleep(1);
printf("修改信息成功\n");
break;
case 'c':printf("修改后的家庭住址:\n");
scanf("%s",date->home);
printf("修改信息中请勿乱动......\n");
sleep(1);
printf("修改信息成功\n");
break;
case 'q':printf("修改后的分组:\n");
scanf("%s",&date->classfy);
printf("修改信息中请勿乱动......\n");
sleep(1);
printf("修改信息成功\n");
break;
case 'd':
flag=0;
break;
default:
break;
}
}
}
//上传云文件
void yun_number(node *head)
{
node *p;
FILE *fp;
fp=fopen("number.txt","w");
if(fp == NULL)
{
printf("云文件打开失败\n");
}
for(p=head->next;p!=head;p=p->next)
{
fwrite(p,sizeof(node),1,fp);
fprintf(fp,"%c",'\n');
}
fclose(fp);
printf("\033[1;32m""上传云文件中......\n");
sleep(2);
printf("文件上传成功\n");
}
//自动读取云文件
void redyun_number()
{
FILE *fp;
node *head;
fp=fopen("number.txt","r+");
fseek(fp,0,SEEK_END); //将文件光标移动文件末尾
int size = ftell(fp); //计算文件的字节数
fseek(fp,0,SEEK_SET); //将文件光标移动到文件头
while(ftell(fp)!=size) //判断文件是否读到末尾
{
node *new_node = initList();
fread(new_node,sizeof(node),1,fp);
insets(head,new_node);
fseek(fp,1,SEEK_CUR); //将光标移动一个位置
}
fclose(fp);
}
//清空联系人
void clear_number(node *head)
{
node *p=NULL,*tmp;
for(p=head->next;p!=head;p=tmp)
{
tmp=p->next;
free(p);
}
head->next=head;
head->prev=head;
}
//解除节点
void remo(node *head,node *q)
{
node *p=NULL;
for(p=head;p->next!=q;p=p->next);
p->next=q->next;
q->next=NULL;
}
//按组来排序
int sort_number(node *head)
{
node *p,*tmp;
int len=0;
p=head->next;
if(p == head)
{
return 0;
}
for(p=head->next;p!=head;p=p->next)
{
len++;
}
for(int i=0;i<len-1;i++)
{
p=head->next;
for(int j=0;j<len-1-i;j++)
{
tmp=p->next;
if(p->classfy > tmp->classfy)
{
remo(head,p);
p->next=tmp->next;
tmp->next=p;
}
else
{
p=p->next;
}
}
}
return 1;
}
int main(void)
{
int sort;
int flag=1;
char ch;
node *head,*new;
head=initList();
redyun_number();
while(flag)
{
printf("\033[0;32;34m""===================通讯录====================\n");
printf("=====按下a:新增联系人 按下b:显示联系人=====\n");
printf("=====按下c:查找联系人 按下d:删除联系人=====\n");
printf("=====按下s:修改联系人 按下p:退出通讯录=====\n");
printf("=====按下y:上传云文件 按下q:清空联系人=====\n");
printf("=====按下t:进行联系人排序 =====\n");
printf("=======每次新增联系人会自动上传云文件========\n""\033[m");
printf("\033[1;31m""每次操作通讯录后需上传文件保存!\n");
printf("\033[1;31m""注意删除联系人之前请上传云文件,防止数据丢失,清空通讯录后请勿上传云文件,防止数据被覆盖,无法找回!!!\n""\033[m");
ch=getchar();
switch (ch)
{
case 'a':
new_number(head,new);
break;
case 'b':
show_number(head);
break;
case 'c':
find_number(head);
break;
case 'd':
del_number(head);
break;
case 's':
date_number(head);
break;
case 'p':
flag=0;
break;
case 'y':
yun_number(head);
break;
case 'q':
clear_number(head);
printf("\033[1;31m""通讯录在清空中......\n");
sleep(2);
printf("清空完成\n");
break;
case 't':
sort=sort_number(head);
if(sort !=0)
{
printf("\033[1;34m""联系人排序中......\n");
sleep(2);
printf("排序完成\n");
}
else
{
printf("\033[0;32;31m""联系人中无数据,无法排序\n");
}
break;
default:
break;
}
while(getchar()!='\n');
}
return 0;
}