大家好,如果觉得我这篇文章写的不错并且对你有帮助的话就关注一下呗。
这是我关于双向循环链表的博客,可以点进去康康啦
编译器是VS2019,依旧是分为三个文件
我先把三个文件的原码放出来,然后对于函数 一 一 解释。
struct Contact* BuyNewNode(char* name, int age, char* sex, char* tel, char* adr)
{
struct Contact* newnode = (struct Contact*)malloc(sizeof(struct Contact));
assert(newnode);
newnode->next = newnode;
newnode->front = newnode;
strcpy(newnode->name , name);
newnode->age = age;
strcpy(newnode->sex , sex);
strcpy(newnode->tel , tel);
strcpy(newnode->adr , adr);
return newnode;
}
这里用 feof判断文件光标后面是否有内容,如果光标后面没有内容则返回非0,如果有内容则返回0,党光标后面有内容的时候我们需要读取文件,所以循环条件为 while(!feof)
void SaveFileData(PC*phead)
{
FILE* fp = fopen("data.txt", "r");
assert(phead);
if (fp == NULL)
{
printf("%s", strerror(errno));
return;
}
getc(fp);
if (!feof(fp))
{
rewind(fp);
}
while (!feof(fp))
{
PC* newnode = BuyNewNode("000000", 0, "000000", "00000", "000000");
fscanf(fp, "%s ", newnode->name);
fscanf(fp, "%d ", &(newnode->age));
fscanf(fp, "%s ", newnode->sex);
fscanf(fp, "%s ", newnode->tel);
fscanf(fp, "%s ", newnode->adr);
PC* head = phead->front;
head->next = newnode;
newnode->front = head;
newnode->next = phead;
phead->front = newnode;
}
fclose(fp);
fp = NULL;
}
void ADDPc(PC* phead)
{
PC* newnode = BuyNewNode("000000", 0, "000000", "00000", "000000");
assert(phead);
assert(newnode);
printf("请输入姓名\n");
scanf("%s", newnode->name);
printf("请输入年龄\n");
scanf("%d", &(newnode->age));
printf("请输入性别\n");
scanf("%s", newnode->sex);
printf("请输入电话\n");
scanf("%s", newnode->tel);
printf("请输入地址\n");
scanf("%s", newnode->adr);
PC* head = phead->front;
head->next = newnode;
newnode->front = head;
newnode->next = phead;
phead->front = newnode;
printf("添加成功\n");
}
void DelPc(PC* pos)
{
assert(pos);
PC* Front = pos->front;
PC* Next = pos->next;
Front->next = Next;
Next->front = Front;
free(pos);
pos = NULL;
}
PC* Find_by_name( PC* phead, char* name)
{
assert(phead);
PC* pos = phead->next;
while (pos !=phead)
{
if (0 == strcmp(name, pos->name))
{
return pos;
}
pos = pos->next;
}
return NULL;
}
void MoDify(PC* pos)
{
char str_name2[NAM_MAX] = "0";
char str_sex2[SEX_MAX] = "0";
char str_tel2[TEL_MAX] = "0";
char str_adr2[ADR_MAX] = "0";
assert(pos);
printf("请输入新的姓名\n");
scanf("%s", str_name2);
strcpy(pos->name, str_name2);
printf("请输入新的年龄\n");
scanf("%d", &(pos->age));
printf("请输入新的性别\n");
scanf("%s", str_sex2);
strcpy(pos->sex, str_sex2);
printf("请输入新的电话\n");
scanf("%s",str_tel2);
strcpy(pos->tel, str_tel2);
printf("请输入新的地址\n");
scanf("%s", str_adr2);
strcpy(pos->adr, str_adr2);
}
void Print(PC* phead)
{
PC* cur = phead->next;
assert(phead);
if (cur == phead)
{
printf("还没有添加信息\n");
}
printf("姓名 年龄 性别 电话 地址\n");
while (cur != phead)
{
printf("%-15s\t%-5d\t%-5s\t%-15s\t%-10s\n", cur->name, cur->age, cur->sex, cur->tel, cur->adr);
cur = cur->next;
}
}
void DesTroy(PC* phead)
{
assert(phead);
PC* cur=phead->next;
while (cur != phead)
{
PC* Next = cur->next;
free(cur);
cur = Next;
}
phead->next = phead;
phead->front = phead;
}
由于qsort是用于一个连续的空间,所以,这里用冒泡排序。
算个数的时候要加上phead,但是排序的时候不要排phead
void Compare_ByName(PC*phead)
{
int i =0;
int j = 0;
PC* cur = phead->next;
PC* Next = cur->next;
char Name_s[NAM_MAX] = "0";
int age_s=0;
char sex_s[SEX_MAX] = "0";
char tel_s[TEL_MAX] = "0";
char adr_s[ADR_MAX] = "0";
assert(phead);
for (i = 0; i < Size(phead)+1; i++)
{
for (j = 0; j < Size(phead) - i ;j++)
{
if ((strcmp(cur->name, Next->name) > 0) && (cur != phead) && (Next != phead))
{
strcpy(Name_s, cur->name);
strcpy(cur->name, Next->name);
strcpy(Next->name, Name_s);
age_s = cur->age;
cur->age = Next->age;
Next->age = age_s;
strcpy(sex_s, cur->sex);
strcpy(cur->sex, Next->sex);
strcpy(Next->sex, sex_s);
strcpy(tel_s, cur->tel);
strcpy(cur->tel, Next->tel);
strcpy(Next->tel, tel_s);
strcpy(adr_s, cur->adr);
strcpy(cur->adr, Next->adr);
strcpy(Next->adr, adr_s);
}
cur = cur->next;
Next = Next->next;
}
}
}
void SaveData(PC* phead)
{
FILE* fp = NULL;
PC* cur = phead->next;
assert(phead);
fp = fopen("data.txt", "w");
if (fp == NULL)
{
printf("%s", strerror(errno));
return;
}
while (cur != phead)
{
fprintf(fp, "%s ", cur->name);
fprintf(fp, "%d ", cur->age);
fprintf(fp, "%s ", cur->sex);
fprintf(fp, "%s ", cur->tel);
fprintf(fp, "%s ", cur->adr);
fprintf(fp, "\n");//换行
cur = cur->next;
}
fclose(fp);
fp = NULL;
}
以下就是contact.h的内容
#pragma once
#include
#include
#include
#include
#include
#include
#define NAM_MAX 20
#define SEX_MAX 10
#define TEL_MAX 20
#define ADR_MAX 20
typedef struct Contact
{
struct Contact* front;
char name[NAM_MAX];
int age;
char sex[SEX_MAX];
char tel[TEL_MAX];
char adr[ADR_MAX];
struct Contact* next;
}PC;
//申请空间√
PC* BuyNewNode(char* name, int age, char* sex, char* tel, char* adr);
void ADDPc(PC* phead);//增加联系人√
void DelPc(PC* pos);//删除联系人√
PC* Find_by_name(PC* phead,char* name);//通过姓名寻找联系人√
void Print(const PC* phead);//打印联系人√
void DesTroy(PC* phead);//销毁通讯录√
void MoDify(PC* pos);//修改联系人信息√
int Size(PC* phead);//计算数据数量√
void Compare_ByName(PC*phead);//按名字排序 abcdefg......√
void SaveData(PC*phead);// 保存数据√
void SaveFileData(PC*phead);//先将文件中的数据存到链表中√
contac.c是每个函数的实现:
#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"
struct Contact* BuyNewNode(char* name, int age, char* sex, char* tel, char* adr)
{
struct Contact* newnode = (struct Contact*)malloc(sizeof(struct Contact));
assert(newnode);
newnode->next = newnode;
newnode->front = newnode;
strcpy(newnode->name , name);
newnode->age = age;
strcpy(newnode->sex , sex);
strcpy(newnode->tel , tel);
strcpy(newnode->adr , adr);
return newnode;
}
void SaveFileData(PC*phead)
{
FILE* fp = fopen("data.txt", "r");
assert(phead);
if (fp == NULL)
{
printf("%s", strerror(errno));
return;
}
getc(fp);
while (!feof(fp))
{
rewind(fp);
PC* newnode = BuyNewNode("000000", 0, "000000", "00000", "000000");
fscanf(fp, "%s ", newnode->name);
fscanf(fp, "%d ", &(newnode->age));
fscanf(fp, "%s ", newnode->sex);
fscanf(fp, "%s ", newnode->tel);
fscanf(fp, "%s ", newnode->adr);
PC* head = phead->front;
head->next = newnode;
newnode->front = head;
newnode->next = phead;
phead->front = newnode;
}
fclose(fp);
fp = NULL;
}
void Print(PC* phead)
{
PC* cur = phead->next;
assert(phead);
if (cur == phead)
{
printf("还没有添加信息\n");
}
printf("姓名 年龄 性别 电话 地址\n");
while (cur != phead)
{
printf("%-15s\t%-5d\t%-5s\t%-15s\t%-10s\n", cur->name, cur->age, cur->sex, cur->tel, cur->adr);
cur = cur->next;
}
}
void ADDPc(PC* phead)
{
PC* newnode = BuyNewNode("000000", 0, "000000", "00000", "000000");
assert(phead);
assert(newnode);
printf("请输入姓名\n");
scanf("%s", newnode->name);
printf("请输入年龄\n");
scanf("%d", &(newnode->age));
printf("请输入性别\n");
scanf("%s", newnode->sex);
printf("请输入电话\n");
scanf("%s", newnode->tel);
printf("请输入地址\n");
scanf("%s", newnode->adr);
PC* head = phead->front;
head->next = newnode;
newnode->front = head;
newnode->next = phead;
phead->front = newnode;
printf("添加成功\n");
}
PC* Find_by_name( PC* phead, char* name)
{
assert(phead);
PC* pos = phead->next;
while (pos !=phead)
{
if (0 == strcmp(name, pos->name))
{
return pos;
}
pos = pos->next;
}
return NULL;
}
void DelPc(PC* pos)
{
assert(pos);
PC* Front = pos->front;
PC* Next = pos->next;
Front->next = Next;
Next->front = Front;
free(pos);
pos = NULL;
}
void DesTroy(PC* phead)
{
assert(phead);
PC* cur=phead->next;
while (cur != phead)
{
PC* Next = cur->next;
free(cur);
cur = Next;
}
free(phead);
phead = NULL;
}
void MoDify(PC* pos)
{
char str_name2[NAM_MAX] = "0";
char str_sex2[SEX_MAX] = "0";
char str_tel2[TEL_MAX] = "0";
char str_adr2[ADR_MAX] = "0";
assert(pos);
printf("请输入新的姓名\n");
scanf("%s", str_name2);
strcpy(pos->name, str_name2);
printf("请输入新的年龄\n");
scanf("%d", &(pos->age));
printf("请输入新的性别\n");
scanf("%s", str_sex2);
strcpy(pos->sex, str_sex2);
printf("请输入新的电话\n");
scanf("%s",str_tel2);
strcpy(pos->tel, str_tel2);
printf("请输入新的地址\n");
scanf("%s", str_adr2);
strcpy(pos->adr, str_adr2);
}
int Size(PC* phead)
{
int sz = 0;
PC* cur = phead->next;
assert(phead);
while (cur != phead)
{
sz++;
cur = cur->next;
}
return sz;
}
void Compare_ByName(PC*phead)
{
int i =0;
int j = 0;
PC* cur = phead->next;
PC* Next = cur->next;
char Name_s[NAM_MAX] = "0";
int age_s=0;
char sex_s[SEX_MAX] = "0";
char tel_s[TEL_MAX] = "0";
char adr_s[ADR_MAX] = "0";
assert(phead);
for (i = 0; i < Size(phead)+1; i++)
{
for (j = 0; j < Size(phead) - i ;j++)
{
if ((strcmp(cur->name, Next->name) > 0) && (cur != phead) && (Next != phead))
{
strcpy(Name_s, cur->name);
strcpy(cur->name, Next->name);
strcpy(Next->name, Name_s);
age_s = cur->age;
cur->age = Next->age;
Next->age = age_s;
strcpy(sex_s, cur->sex);
strcpy(cur->sex, Next->sex);
strcpy(Next->sex, sex_s);
strcpy(tel_s, cur->tel);
strcpy(cur->tel, Next->tel);
strcpy(Next->tel, tel_s);
strcpy(adr_s, cur->adr);
strcpy(cur->adr, Next->adr);
strcpy(Next->adr, adr_s);
}
cur = cur->next;
Next = Next->next;
}
}
}
void SaveData(PC* phead)
{
FILE* fp = NULL;
PC* cur = phead->next;
assert(phead);
fp = fopen("data.txt", "w");
if (fp == NULL)
{
printf("%s", strerror(errno));
return;
}
while (cur != phead)
{
fprintf(fp, "%s ", cur->name);
fprintf(fp, "%d ", cur->age);
fprintf(fp, "%s ", cur->sex);
fprintf(fp, "%s ", cur->tel);
fprintf(fp, "%s ", cur->adr);
fprintf(fp, "\n");//换行
cur = cur->next;
}
fclose(fp);
fp = NULL;
}
test.c是各个函数之间的调用:
#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"
enum MyEnum
{
Exit,
Add,
Dele,
Find,
Modify,
Show,
Destroy,
Sort,
Save
};
void Menu()
{
//system("cls");
printf("*******************************\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("*********0.退出*******\n");
printf("************************\n");
}
int main(void)
{
PC* phead = BuyNewNode("000000", 0, "000000", "00000", "000000");//初始化一个头节点
SaveFileData(phead);
int input = 0;
int sz = 0;//求联系人的个数
char str_name[NAM_MAX] = "0";//用来通过姓名寻找
do
{
Sleep(500);
Menu();
printf("请输入你的选择->");
scanf("%d", &input);
switch (input)
{
case Exit:
printf("即将退出程序\n");
for (int i = 0; i < 10; i++)
{
printf("-");
Sleep(100);
}
break;
case Add:
if (phead == NULL)
{
phead= BuyNewNode("000000", 0, "000000", "00000", "000000");
}
ADDPc(phead);
break;
case Dele:
printf("请输入你要删除的姓名:\n");
scanf("%s", str_name);
PC* pos = Find_by_name(phead, str_name);
if (pos)
{
printf("姓名 年龄 性别 电话 地址\n");
printf("%-15s\t%-5d\t%-5s\t%-15s\t%-10s\n", pos->name, pos->age, pos->sex, pos->tel, pos->adr);
DelPc(pos);
printf("删除成功\n");
}
else
{
printf("没有找到\n");
}
break;
case Show:
sz = Size(phead);
printf("共有%d个联系人\n", sz);
Print(phead);
break;
case Find:
printf("请输入你要寻找的姓名:\n");
scanf("%s", str_name);
PC* pos1=Find_by_name(phead,str_name);
if (pos1)
{
printf("姓名 年龄 性别 电话 地址\n");
printf("%-15s\t%-5d\t%-5s\t%-15s\t%-10s\n", pos1->name, pos1->age, pos1->sex, pos1->tel, pos1->adr);
}
else
{
printf("没有找到\n");
}
break;
case Modify:
printf("请输入你要寻找的姓名:\n");
scanf("%s", str_name);
PC* pos2 = Find_by_name(phead, str_name);
if (pos2)
{
printf("姓名 年龄 性别 电话 地址\n");
printf("%-15s\t%-5d\t%-5s\t%-15s\t%-10s\n", pos2->name, pos2->age, pos2->sex, pos2->tel, pos2->adr);
MoDify(pos2);
}
else
{
printf("没有找到\n");
}
break;
case Destroy:
DesTroy(phead);
printf("销毁成功\n");
break;
case Sort:
sz = Size(phead);
printf("共有%d个联系人\n", sz);
Compare_ByName(phead);
Print(phead);
break;
case Save:
SaveData(phead);
printf("保存成功\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}