基于链表的通讯录管理(数据结构)
如有bug望指正 谢谢

头文件
#ifndef __HEAD_H__
#define __HEAD_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//信息结构体
typedef struct info
{
int id;
char name[128];
char gender[10];
char tele[20];
struct info* next;
}info,*info_m;
//链结构体
typedef struct link
{
int len;
info_m front;
info_m rear;
}link,*link_k;
//登录结构体
typedef struct log
{
char username[128];
char password[128];
int length;
struct log* pass;
}log,*log_g;
//一级菜单函数声明↓
//1、注册模块 将注册的信息存入结构体中
void register_login(log_g G,link_k L);
//2、登录模块
void log_in(log_g G,link_k L);
//3、退出系统
void exit();
//1. 申请账户存储空间
log_g create_log();
//2. 添加新用户
void add_log(log_g G);
//3. 退出系统
void exit_system();
//一级菜单页面
void menu_login(log_g G,link_k L);
//二级菜单页面
void menu_info(link_k L,log_g G);
//辅助功能菜单栏
void menu_assist(link_k L,log_g G);
//二级菜单函数声明↓
//1、create 创建链表 完成对信息的存储
link_k create_link();
//2、add 添加数据 添加通讯录的信息放入链中
void add_info(link_k L);
//3、find 查找信息 可以通过姓名进行查找
void find_info(link_k L);
//4、updata_select 修改信息 可以修改联系人信息并保存 分别修改 同时修改
void updata_select(link_k L);
//4.1 updata_all
void updata_info(link_k L);
//4.2 updata_part
void updata_part(link_k L);
//5、delete 删除信息 可以根据输入的姓名进行删除
void delete_info(link_k L);
//6、insert 插入信息 将给定的信息以及插入位置信息完成插入
void insert_info(link_k L);
//7、show 展示信息 将通讯录的所有信息进行展示
void show_info(link_k L);
//8、按照姓名将通讯录排序
void sort_info(link_k L);
//辅助功能函数声明↓
//10、初始化链表init:将链表进行初始化
void bzero_info(link_k L);
//11、获取链表长度getlength
void getlength_info(link_k L);
//12、统计性别;
void stat_gender(link_k L);
//13、释放链表空间
void destroy_link(link_k* L);
#endif
功能函数
#include "head.h"
//二级菜单
//1、create 创建链表 完成对信息的存储
link_k create_link()
{
link_k L = (link_k)malloc(sizeof(link));
if (L == NULL)
return NULL;
L->front = NULL;
L->rear = NULL;
L->len = 0;
return L;
}
//2、add 添加数据 添加通讯录的信息放入链中
void add_info(link_k L)
{
info_m new = (info_m)malloc(sizeof(info));
if (new == NULL)
return;
printf("编号:");scanf("%d",&new->id);
info_m p = L->front;
while(p != NULL)
{
if (new->id == p->id)
{
printf("\n该编号已存在!即将放回上页面......\n");
return;
}
p = p->next;
}
printf("姓名:");scanf("%s",new->name);
printf("性别(man/woman):");scanf("%s",new->gender);
printf("电话:");scanf("%s",new->tele);
if (L->rear == NULL)
{
L->front = new;
L->rear = new;
}
else
{
L->rear->next = new;
L->rear = new;
}
L->len++;
printf("该成员数据添加成功!\n");
}
//3、find 查找信息 可以通过姓名进行查找
void find_info(link_k L)
{
if (L == NULL)
return;
if (L->len == 0)
{
printf("没有人员信息录入,返回上一级\n");
return;
}
char name[128];
int found = 0;
printf("name=");
scanf("%s",name);
info_m p = L->front;
while(p != NULL)
{
if(strcmp(name,p->name)==0)
{
found =1;
break;
}
p = p->next;
}
if (found == 1)
{
printf("\n该人员信息如下:\n");
printf("%d\t",p->id);
printf("%s\t",p->name);
printf("%s\t",p->gender);
printf("%s\t\n",p->tele);
}
if (found == 0)
{
printf("\n没有记录该人员,请检查输入是否有误!\n");
}
}
//4.1 updata_all
void updata_info(link_k L)
{
if (L == NULL)
return;
printf("\n请选择您要修改的对象名字:");
char name[128];
int found = 0;
scanf("%s",name);
info_m p = L->front;
while(p != NULL)
{
if(strcmp(name,p->name)==0)
{
found = 1;
break;
}
p = p->next;
}
if (found == 1)
{
printf("该人员信息如下:\n");
printf("请输入新的编号(原编号为%d):",p->id);
scanf("%d",&p->id);
printf("请输入新的名字(原名字为%s):",p->name);
scanf("%s",p->name);
printf("请输入新的性别(原性别为%s):",p->gender);
scanf("%s",p->gender);
printf("请输入新的电话(原电话为%s):",p->tele);
scanf("%s",p->tele);
// printf("变更后的结果如下:");
// printf("%d\t",p->id);
// printf("%s\t",p->name);
// printf("%s\t",p->gender);
// printf("%s\t\n",p->tele);
}
if (found == 0)
{
printf("没有记录该人员,请检查输入是否有误!\n");
}
}
//4.2 updata_part
void updata_part(link_k L)
{
int choice = 0;
printf("\n===== 请输入你的选择:=====\n");
printf("1.修改编号\n");
printf("2.修改姓名\n");
printf("3.修改性别\n");
printf("4.修改电话\n");
printf("\n请输入您的选择:");
scanf("%d",&choice);
switch(choice)
{
case 1:{
printf("\n请选择您要修改的对象名字:");char name[128];
int found = 0 ;scanf("%s",name);info_m p = L->front;
while(p != NULL){
if(strcmp(name,p->name)==0){
found = 1;break;}
p = p->next;}
if(found == 1){
printf("请输入新的编号(原编号为%d):",p->id);
scanf("%d",&p->id);return;}
if(found == 0){
printf("没有记录该人员,请检查输入是否有误!\n");}
break;}
case 2:{
printf("\n请选择您要修改的对象名字:");char name[128];
int found = 0;scanf("%s",name);info_m p = L->front;
while(p != NULL){
if(strcmp(name,p->name)==0){
found = 1;break;}
p = p->next;}
if(found == 1){
printf("请输入新的名字(原名字为%s):",p->name);
scanf("%s",p->name);return;}
if(found == 0){
printf("没有记录该人员,请检查输入是否有误!\n");}
break;}
case 3:{
printf("\n请选择您要修改的对象名字:");char name[128];
int found = 0;scanf("%s",name);info_m p = L->front;
while(p != NULL){
if(strcmp(name,p->name)==0){
found = 1;break;}
p = p->next;}
if(found == 1){
printf("请输入新的性别(原性别为%s):",p->gender);
scanf("%s",p->gender);return;}
if(found == 0){
printf("没有记录该人员,请检查输入是否有误!\n");}
break;}
case 4:{
printf("\n请选择您要修改的对象名字:");char name[128];
int found = 0;scanf("%s",name);info_m p = L->front;
while(p != NULL){
if(strcmp(name,p->name)==0){
found = 1;break;}
p = p->next;}
if(found == 1){
printf("请输入新的电话(原电话为%s):",p->tele);
scanf("%s",p->tele);return;}
if(found == 0){
printf("没有记录该人员,请检查输入是否有误!\n");}
break;}
default:printf("\n选择无效!\n");break;
}
}
//4、updata_select 修改信息 可以修改联系人信息并保存 分别修改 同时修改
void updata_select(link_k L)
{
int choice = 0;
printf("\n===== 请输入你的选择:=====\n");
printf("1.进行全部修改\n");
printf("2.对部分进行修改\n");
printf("3.退出\n");
printf("\n请输入您的选择:");
scanf("%d",&choice);
switch(choice)
{
case 1:updata_info(L);break;
case 2:updata_part(L);break;
case 3:printf("\n即将退出选择...\n");break;
default:printf("\n选择无效!\n");break;
}
}
//5、delete 删除信息 可以根据输入的姓名进行删除
void delete_info(link_k L)
{
if (L == NULL || L->len == 0)
return;
printf("\n请选择您要删除的对象名字:");
char name[128];
scanf("%s",name);
info_m p = L->front; //p从头开始
info_m q = p; //q保留p的位置 用于记录
int found = 0;
char flag[10];
while(p != NULL)
{
if (strcmp(name,p->name) == 0)
{
found = 1;
break;
}
q = p; //p在交换成下一个前 保存p的位置
p = p->next; //p循序往下走
}
if (found == 0)
{
printf("\n没有记录该人员,请检查输入是否有误!\n");
return;
}
if (found == 1)
{
printf("\n是否确认要删除!!!\n");
printf("(yes/no):");
scanf("%s",flag);
if (strcmp(flag,"yes") == 0)
{
if (p == L->front) //头删
{
L->front = p->next;
if (L->rear == p)
{
L->rear = NULL;
}
}
q->next = p->next; //中间删
if (p == L->rear) //尾删
{
L->rear = q;
}
free(p);
L->len--;
printf("删除成功!\n");
}
else
return;
}
}
//6、insert 插入信息 将给定的信息以及插入位置信息完成插入
void insert_info(link_k L)
{
info_m new_pos = (info_m)malloc(sizeof(info));
if (new_pos == NULL)
return;
info_m p = L->front;
printf("\n给定以下信息\n");
printf("编号:");scanf("%d",&new_pos->id);
while(p != NULL)
{
if (new_pos->id == p->id)
{
printf("\n该编号已存在!即将返回上一页面......\n");
return;
}
p = p->next;
}
printf("姓名:");scanf("%s",new_pos->name);
printf("性别(man/woman):");scanf("%s",new_pos->gender);
printf("电话:");scanf("%s",new_pos->tele);
int pos;
printf("\n请输入要插入的位置:");
scanf("%d",&pos);
if (pos == 0)
{
new_pos->next = L->front;
L->front = new_pos;
if (L->rear == NULL)
L->rear = new_pos;
L->len++;
return;
}
if (pos > 0 && pos <= L->len)
{
info_m start = L->front;
for(int i=1;i<pos;i++)
{
start = start->next;
} //遍历找到pos前的位置
new_pos->next = start->next;
start->next = new_pos;
if (new_pos->next == NULL)
{
L->rear = new_pos;
}
L->len++;
return;
}
else
{
printf("\n插入不合理\n");return;
}
}
//7、show 展示信息 将通讯录的所有信息进行展示
void show_info(link_k L)
{
info_m p = L->front;
if (L->len == 0)
{
printf("\n没有人员信息录入!\n");
return;
}
printf("\n编号\t姓名\t性别\t电话\t\n");
while(p != NULL)
{
// printf("编号\t姓名\t性别\t电话\t\n");
printf("%d\t",p->id);
printf("%s\t",p->name);
printf("%s\t",p->gender);
printf("%s\t\n",p->tele);
// printf("一共有%d人。\n",L->len);
p=p->next;
}
printf("所有信息输出完成,一共有%d人。\n",L->len);
}
//8、按照姓名将通讯录排序
void sort_info(link_k L)
{
if (L == NULL || L->len <= 1)
return;
int swapped;
info_m p;
info_m last = NULL;
do{
swapped = 0;
p = L->front;
while(p->next != last)
{
if(strcmp(p->name,p->next->name)>0)
{
info_m temp = p->next;
p->next = temp->next;
temp->next = p;
if(p == L->front)
{
L->front = temp;
}
else
{
info_m pre = L->front;
while(pre->next != p)
{
pre = pre->next;
}
pre->next = temp;
}
swapped = 1;
}
else
{
p = p->next;
}
}
last = p;
}while(swapped);
}
//9、放回上一级
//辅助功能
//10、初始化链表init:将链表进行初始化
void bzero_info(link_k L)
{
if (L == NULL)
return;
bzero(L,sizeof(link));
L->front = NULL;
L->rear = NULL;
L->len = 0;
}
//11、获取链表长度getlength
void getlength_info(link_k L)
{
if (L == NULL)
return;
int getlength;
getlength = (L->len)*sizeof(link);
printf("getlength=%d\n",getlength);
printf("链表长度为%d\n",L->len);
}
//12、统计性别;
void stat_gender(link_k L)
{
if (L == NULL)
return;
info_m p = L->front;
int count = 0;
char gender[128]="woman";
while(p != NULL)
{
if(strcmp(gender,p->gender) == 0)
{
count++;
}
p = p->next;
}
int boy = L->len - count;
printf("\n性别为女性的有%d人\n",count);
printf("性别为男性的有%d人\n",boy);
printf("总计有%d人\n",L->len);
}
//13、释放链表空间
void destroy_link(link_k* L)
{
if (*L == NULL|| L == NULL)
return;
free(*L);
*L = NULL;
}
菜单栏函数
#include "head.h"
//一级菜单
//1、注册模块 将注册的信息存入结构体中
void register_login(log_g G,link_k L)
{
if (G == NULL)
return;
add_log(G);
printf("回到上一界面!\n");
// menu_login(G,L);
}
//2、登录模块
void log_in(log_g G,link_k L)
{
char username[128];
char password[128];
printf("\n请输入你的账号:");
scanf("%s",username);
printf("请输入您的密码: ");
scanf("%s",password);
if(strcmp(username,G->username)==0 && strcmp(password,G->password)==0)
{
printf("登录成功!\n");
menu_info(L,G);
}
else
{
printf("登录失败,账号或密码错误...\n");
// menu_login(G,L);
}
return;
}
//一级菜单页面
void menu_login(log_g G,link_k L)
{
int choice = 0;
do
{
printf("\n======== 登录页面 ========\n");
printf("1.注册账号\n");
printf("2.登录\n");
printf("3.退出系统\n");
// int choice = 0;
printf("\n请输入您的选择:");
scanf(" %d",&choice);
switch(choice)
{
case 1:register_login(G,L);break;
case 2:log_in(G,L);break;
case 3:exit_system;break;
default:printf("\n选择无效!\n");
}
}while(choice!=3);
}
//二级菜单页面
void menu_info(link_k L,log_g G)
{
int choice=0;
do{
printf("\n======== 功能页面 ========\n");
printf("1.录入新用户信息\n");
printf("2.查找用户信息\n");
printf("3.修改用户信息\n");
printf("4.删除用户信息\n");
printf("5.插入用户信息\n");
printf("6.展示所有用户信息\n");
printf("7.按照姓名进行排序\n");
printf("8.返回上一级\n");
printf("9.辅助功能\n");
printf("\n请输入您的选择:");
scanf("%d",&choice);
switch(choice)
{
case 1:add_info(L);break;
case 2:find_info(L);break;
case 3:updata_select(L);break;
case 4:delete_info(L);break;
case 5:insert_info(L);break;
case 6:show_info(L);break;
case 7:sort_info(L);break;
case 8:return;
case 9:menu_assist(L,G);break;
case 10:printf("开发中...\n");break;
default:printf("\n无效的选择!\n");
}
}while(choice!=10);
}
//辅助功能菜单栏
void menu_assist(link_k L,log_g G)
{
int choice = 0;
do{
printf("\n======== 辅助功能页面 ========\n");
printf("1.初始化链表\n");
printf("2.获取链表长度\n");
printf("3.统计性别\n");
printf("4.返回上一级\n");
printf("\n请输入您的选择:");
scanf("%d",&choice);
switch(choice)
{
case 1:bzero_info(L);break;
case 2:getlength_info(L);break;
case 3:stat_gender(L);break;
case 4:;return;
default:printf("\n无效的选择!\n");
}
}while(choice!=4);
}
//1. 申请账户存储空间
log_g create_log()
{
log_g G = (log_g)malloc(sizeof(log));
if (G == NULL)
return NULL;
return G;
}
//2. 添加新用户
void add_log(log_g G)
{
if (G == NULL)
return;
printf("\n请输入您的用户名:");scanf("%s",G->username);
printf("请输入您的密码:");scanf("%s",G->password);
G->length++;
printf("\n注册成功!\n");
}
//3. 退出系统
void exit_system()
{
printf("\n即将退出系统.......\n");
exit(0);
}
makefile
EXE=login
Filename=$(wildcard *.c)
Objs=$(patsubst %.c,%.o,$(Filename))
CC=gcc
CFlags= -c -o
login=$(wildcard *.h)
all=$(EXE)
$(EXE):$(Objs)
$(CC) $^ -o $@
%.o:%.c
$(CC) $< $(CFlags) $@
.PHONY:clean
clean:
rm $(EXE) $(Objs)
基于链表的通讯录管理
基于链表的通讯录管理
本代码有以下三个结构体
1、信息结构体
typedef struct info
{
int id;
char name[128];
char gender[10];
char tele[20];
struct info* next;
}info,*info_m;2、链结构体
typedef struct link
{
int len;
info_m front;
info_m rear;
}link,*link_k;3、登录结构体
typedef struct log
{
char username[128];
char password[128];
int length;
struct log* pass;
}log,*log_g;有以下功能👇
通过结构体3实现用户的注册和登录完成一级菜单设置在二级菜单内
在堆区申请空间 使用malloc函数
添加数据 添加通讯录的信息放入链中
先遍历一次链表 判断输入的编号是否存在
已有则无法输入 若无则可以继续添加 长度+1查找信息 修改信息 删除信息 插入信息 都根据姓名来进行匹配
输出信息的时候直接从头开始遍历链表 输出信息
给定信息插入时 会匹配pos的值 看插入是否合理 不合理结束
根据姓名进行排序时 使用冒泡排序 同时设定一个标志
在遍历链表过程中 前后两两比较 发生交换时标志为1
当无法交换时标志为0 结束循环 冒泡升序排序完成
辅助功能页面
初始化链表内 使用bzero清零
统计性别模块 让链表中的gender与设定的“man/woman”strcmp
有一次匹配则计数器+1 直至遍历完链表最后执行完成后 退出系统时 free(*L)链表
更多推荐



所有评论(0)