目录
一 总览
思路:
基于上个版本 对联系人进行删除 修改信息等;整体多了两个函数
第一个 writetxt 将txt文件清空 并将修改过单链表(包括删除联系人等)整体写入 txt 文件
基于上个版本只用将writetxt函数加在修改信息代码段之后
第二个 readtxt2 运行程序开始第一不 创建空的链表 并将txt文件的数据(联系人)并按首字母排序读入链表中;
1.1main.c文件
#include "tongxunlu.h"
int main(int argc, char const *argv[])
{
tongxunlist *head = tongxunlistcreate();
readtxt2(head);//将txt文件里的 联系人信息按首字母大小排序并读入单链表中
while (1)//这个循环可以实现 功能结束返回菜单
{
menu(); //菜单
myswitch(head); //这里在tongxunlu.c封装好了也可直接在main.c里写
}
return 0;
}
1.2 tongxunlu.h
#ifndef _TONGXUNLU_h
#define _TONGXUNLU_H
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
typedef int datatype;
typedef struct tongxunlu
{
char name[32];//姓名
datatype age; //年龄
char adress[32];//住址
char tel[32];//电话
struct tongxunlu *next; //指针域
}tongxunlist;
tongxunlist* tongxunlistcreate();
//mymenu 菜单
void menu();
void myswitch();
//mystrncmp
int my_strncmp(const char *str,const char *str1,int n);
//判断链表是否为空
int tongxunempty(tongxunlist *head);
//my_strcmp
int my_strcmp(char *str,char *str1);
//直接插入排序
void linklist_straight_insertion(tongxunlist *head);
//单链表的遍历
void linklistprintf(tongxunlist *head);
//查找联系人
void Find_person(tongxunlist *head);
//删除联系人
void del_person(tongxunlist *head);
//修改联系人信息
void tongxunlistdata_data(tongxunlist *head);
//结束进程
void endp();
//txt文件读取至单链表
//void readtxt(tongxunlist *head);
//将修改过的链表存入txt文件
void writetxt(tongxunlist *head);
//从文件中读取数据并排序放入链表
void readtxt2(tongxunlist *head);
//单链表的整表删除
void linklist_all_delete(tongxunlist *head);
#endif
三 tongxunlu.c
1.创建空链表
tongxunlist* tongxunlistcreate()
{
tongxunlist *head = (tongxunlist *)malloc(sizeof(tongxunlist));
head->next = NULL;
return head;
}
2.菜单
tongxunlist* tongxunlistcreate()
{
tongxunlist *head = (tongxunlist *)malloc(sizeof(tongxunlist));
head->next = NULL;
return head;
}
//mymenu 菜单
void menu()
{
printf("**************欢迎使用通讯录*****************\n");
printf("*********************************************\n");
printf("** 1.添加联系人 2.查看联系人 **\n");
printf("** 3.搜索联系人 4.删除联系人 **\n");
printf("** 5.修改用户信息 6.退出通讯录 **\n");
printf("*********************************************\n");
printf("*********************************************\n");
}
3.switch case 调用函数
void myswitch(tongxunlist *head)
{
int num;//定义整形 数字
scanf("%d",&num); //输入数字 调用对应功能
getchar(); //吞噬垃圾字符 防止出现错误
while(1) //此处用循环可以为下面连续使用对应功能
{
switch (num)
{
case 1:
printf("正在添加联系人.....\n");
putchar(10);//没什么作用为了让终端显示的不那么拥挤
linklist_straight_insertion(head);//添加联系人函数调用
break;
case 2:
printf("正在查看联系人.....\n");
putchar(10);
linklistprintf(head);//查看联系人函数调用
break;
case 3:
printf("正在搜索联系人.....\n");
Find_person(head);
putchar(10);
;//搜索联系人函数调用
break;
case 4:
printf("正在删除联系人.....\n");
del_person(head);
putchar(10);
;//删除联系人函数调用
break;
case 5:
printf("正在修改联系人.....\n");
putchar(10);
tongxunlistdata_data(head);//修改联系人函数调用
break;
case 6:
printf("正在退出通讯录.....\n");
endp(head);//退出函数调用
break;
default:
printf("对不起您输入有误,请重新输入\n");
return;
}
break;
}
}
4.判断链表是否为空
int tongxunempty(tongxunlist *head)
{
if (head->next==NULL)
{
return 1 ;
}
else
{
return 0;
}
}
5.添加联系人
//添加联系人
void linklist_straight_insertion(tongxunlist *head)
{
tongxunlist *tmp=(tongxunlist *)malloc(sizeof(tongxunlist));
tmp->next=NULL;
printf("请输入姓名:\n");
scanf("%s",tmp->name);
printf("请输入年龄:\n");
scanf("%d",&tmp->age);
printf("请输入住址:\n");
scanf("%s",tmp->adress);
printf("请输入电话号码:\n");
scanf("%s",tmp->tel);
putchar(10);
tongxunlist *p =head;//定义一个指针为表头
//q=q->next;
if(1==tongxunempty(head))
{
tmp->next=head->next;//令新插入的结点指针指向下一个结点
//tmp 新插入结点的地址
head->next=tmp;
}
else
{
while(p->next!=NULL&&my_strncmp(p->next->name , tmp->name,1)<0)//当目的name小于源name
{
p=p->next;
}
//当p->next指向的数据大于或者等于需要插入的数据是跳出循环
//此事p->next 向的是第一个大于value的值
tmp->next=p->next;
p->next=tmp; //然后将其插入大于value的值之前
printf("*****联系人添加完成*****\n");
putchar(10);
}
//将数据写入txt文本
writetxt(head);
int num = 0;
printf("*请选择是否继续添加联系人*\n");
printf("*1.继续添加* 2.返回菜单*\n");
scanf("%d",&num);
getchar();
if(num == 1)
{
linklist_straight_insertion(head);//继续添加就在此调用函数
}
else
{
return ; //不添加就结束 把程序流程从被调函数转向主调函数 main.c在此循环进入菜单
}
}
6.查看所有联系人
//链表查看所有联系人
void linklistprintf(tongxunlist *head)
{
//定义一个指针 遍历保存第一个有数据的结点
tongxunlist *p = head->next;
if(1==tongxunempty(head))
{
printf("该通讯录为空请添加联系人\n");
printf("请进行添加联系人\n");
return;
}
//循环遍历单链表,直到指针指为空结束循环 因为最后一个结点的指针域指向NULL
while(p->next !=NULL)
{
printf("╔════════════════════════════════════════════════════════╗\n");
printf("*姓名%s__年龄:%d___住址:%s__电话%s*\n",p->name,p->age,p->adress,p->tel);
printf("╚════════════════════════════════════════════════════════╝\n");
//p循环中指向下一个结点
p=p->next;
}
printf("╔════════════════════════════════════════════════════════╗\n");
printf("*姓名%s__年龄:%d___住址:%s__电话%s*\n",p->name,p->age,p->adress,p->tel);
printf("╚════════════════════════════════════════════════════════╝\n");
putchar(10);
}
7.查找联系人
//查找联系人
void Find_person(tongxunlist *head)
{
if(1==tongxunempty(head))
{
printf("该通讯录为空请添加联系人\n");
printf("请进行添加联系人\n");
return;
}
char s1[32]={0};//定义一个字符串数组 用于保存你输入想要查找联系人的名字
printf("********************************\n");
printf("请输入您所查找联系人的姓名或者住址\n");
printf("********************************\n");
int i;
scanf("%s",s1);
tongxunlist *p =head;
while(p!=NULL)//如果用p->next!=NULL 当p在最后一个结点是 p->next=NULL 无法进入循环
{
if(my_strcmp(s1,p->name) == 0 )
{
printf("╔═══════════════════════════════════════════════════════════╗\n");
printf("* 姓名%s__年龄:%d___住址:%s__电话%s *\n",p->name,p->age,p->adress,p->tel);
printf("╚═══════════════════════════════════════════════════════════╝\n");
break;
}
else if(my_strcmp(s1,p->adress) == 0 ) //这个是按地址查询 道理与上面相同
{
printf("╔═══════════════════════════════════════════════════════════╗\n");
printf("*姓名%s__年龄:%d___住址:%s__电话%s*\n",p->name,p->age,p->adress,p->tel);
printf("╚═══════════════════════════════════════════════════════════╝\n");
break;
}
p=p->next;
}
if(p==NULL)
{
printf("**查无此人**\n");
putchar(10);
}
printf("请问是否要继续查询联系人\n");
printf("**1.继续查找** **2.返回菜单**\n");
putchar(10);
int num = 0;
getchar();//吞噬垃圾字符
scanf("%d",&num);
if(num==1)
{
Find_person(head);//强行执行下次循环继续查找
}
else
{
return; //如果输入不为1 退出 进入主函数 在次循环进出菜单
}
}
8.删除联系人
//删除联系人
void del_person(tongxunlist *head)
{
if(1==tongxunempty(head))
{
printf("该通讯录为空请添加联系人\n");
printf("请进行添加联系人\n");
return;
}
printf("**请输入你想删除联系人的名字**\n");
char s2[32] = {0};
scanf("%s",s2);
tongxunlist *p = head;
tongxunlist *q;
while(p->next!=NULL)
{
if(my_strcmp(s2,p->next->name)==0)
{
q=p->next;
p->next=p->next->next;
free(q);
q=NULL;
printf("删除成功\n");
writetxt(head);
return;
}
p=p->next;
}
}
9.修改联系人信息
//修改联系人信息
void tongxunlistdata_data(tongxunlist *head)
{
if(1==tongxunempty(head))
{
printf("该通讯录为空请添加联系人\n");
printf("请进行添加联系人\n");
return;
}
printf("**请输入您所要修改信息的人名**\n");
char s3[32] = {0};
scanf("%s",s3);
tongxunlist *p=head;//定义一个指针指向头结点
p=p->next;//头结点无数据 直接跳过
while(p!=NULL)
{
if(my_strcmp(s3,p->name) == 0 )
{
printf("请输入新的姓名\n");//下面直接进行覆盖就行了
scanf("%s",p->name); //把新的信息覆盖旧的信息
printf("请输入新的年龄\n");
scanf("%d",&p->age);
printf("请输入新的住址\n");
scanf("%s",p->adress);
printf("请输入新的电话\n");
scanf("%s",p->tel);
printf("修改成功\n");
writetxt(head);//重新写入
return; //修改完 返回主函数 循环进入菜单
}
p=p->next;
}
if(p==NULL)
{
printf("**不存在该联系人**\n");
putchar(10);
}
}
10 结束整个进程
//结束整个进程
void endp(tongxunlist *head)
{
linklist_all_delete(head);//内容已经保存至txt删除整个单链表
exit(0);
}
11.writetxt 将改动后的单链表写入txt
//改动后的链表写入txt
void writetxt(tongxunlist *head)
{
tongxunlist *q =head;
//q=q->next;
FILE *fp = fopen("./1.txt","w");
if(NULL == fp)//失败返回NULL 成功返回文件流指针
{
perror("fopen");
return ;
}
while(q->next!=NULL)
{
if(1 != fwrite(q->next,sizeof(tongxunlist),1,fp))//成功返回大小,失败返回个数
{
perror("fwrite");
return ;
}
q=q->next;
}
fclose(fp);
printf("链表写入文件...");
putchar(10);
}
12.将txt文件内容读入单链表
//读取文件并将其排序存入链表
void readtxt2(tongxunlist *head)
{
tongxunlist *p = head;
FILE *fp = fopen("./1.txt","r"); //成功返回文件流指针 失败返回NULL
if(NULL == fp)
{
perror("fopen");
return ;
}
while(0 == feof(fp)) //循环读取txt文件
{
tongxunlist *tmp=(tongxunlist *)malloc(sizeof(tongxunlist));
tmp->next=NULL;
//将读取的数据 保存至tmp中
if(0 == fread(tmp,sizeof(tongxunlist),1,fp))//成功返回个数 失败返回0
{
if(feof(fp))//达到文件末尾返回非0 其他返回0
{
printf("文件内容读入链表..\n");
printf("正在进入菜单....\n");
break;
}
else
{
perror("fread");
return ;
}
}
//将按首字母大小插入单链表中
if(1==tongxunempty(head))
{
tmp->next=head->next;//令新插入的结点指针指向下一个结点
//tmp 新插入结点的地址
head->next=tmp;
}
else
{
while(p->next!=NULL&&my_strncmp(p->next->name , tmp->name,1)<0)//当目的name小于源name
{
p=p->next;
}
//当p->next指向的数据大于或者等于需要插入的数据是跳出循环
//此事p->next 就是插入的位置
tmp->next=p->next;
p->next=tmp;
}
putchar(10);
}
}
13.单链表的整表删除函数
//链表的整表删除
void linklist_all_delete(tongxunlist *head)
{
if(tongxunempty(head))
{
printf("链表为空\n");
return;
}
tongxunlist *p,*q;//定义两个指针
q=NULL;
p=head->next;//令p相当于头结点指向第一个结点
while(p!=NULL)
{
q=p; //q相当于头结点 也指向第一个结点
p=p->next; //p指向第二个结点
free(q); //q=head->next 释放第一个结点
}
head->next=NULL;//头结点 置空
printf("整表释放成功....\n");
return;
}
本文含有隐藏内容,请 开通VIP 后查看