1. 项目文件组成(vs2022)
1. Contact.h和Contact.c分别为实现通讯录的头文件和源文件。
2. SList.h和SList.c分别为实现单链表的头文件和源文件。
3. test.c为测试用的源文件,用于调用通讯录提供的函数。
4. Contact.txt用于存储联系人信息。
2. 单链表
C语言单链表-CSDN博客
2.1 头文件
对于该项目,有用的接口就四个。
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "Contact.h"
typedef PeoInfo SLTDataType;
typedef struct SListNode
{
SLTDataType data;
struct SListNode* next;
}SLTNode;
//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x);
//头删
void SLTPopFront(SLTNode** pphead);
//删除pos位置节点
void SLTErase(SLTNode** pphead, SLTNode* pos);
//申请结点
SLTNode* SLTBuyNode(SLTDataType x);
2.2 源文件
#define _CRT_SECURE_NO_WARNINGS
#include "SList.h"
//创建新结点
SLTNode* SLTBuyNode(SLTDataType x)
{
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
if (newnode == NULL)
{
perror("malloc fail!");
exit(1);
}
newnode->data = x;
newnode->next = NULL;
return newnode;
}
//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
assert(pphead);
SLTNode* newnode = SLTBuyNode(x);
if (*pphead == NULL)
{
*pphead = newnode;
}
else
{
SLTNode* ptail = *pphead;
while (ptail->next != NULL)
{
ptail = ptail->next;
}
ptail->next = newnode;
}
}
//头删
void SLTPopFront(SLTNode** pphead)
{
assert(pphead && *pphead);
SLTNode* newphead = (*pphead)->next;
free(*pphead);
*pphead = newphead;
}
//删除pos位置节点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
assert(pphead && *pphead);
assert(pos);
if (pos == *pphead)
{
SLTPopFront(pphead);
}
else
{
SLTNode* prev = *pphead;
while (prev->next != pos)
{
prev = prev->next;
}
prev->next = pos->next;
free(pos);
}
}
3. 通讯录
3.1 头文件
#pragma once
#define NAME_MAX 100
#define SEX_MAX 10
#define TEL_MAX 11
#define ADDR_MAX 100
//前置声明
typedef struct SListNode contact;
//用户数据
typedef struct PersonInfo
{
char name[NAME_MAX];
char sex[SEX_MAX];
int age;
char tel[TEL_MAX];
char addr[ADDR_MAX];
}PeoInfo;
//初始化通讯录
void InitContact(contact** con);
//添加通讯录数据
void AddContact(contact** con);
//删除通讯录数据
void DelContact(contact** con);
//展示通讯录数据
void ShowContact(contact* con);
//查找通讯录数据
void FindContact(contact* con);
//修改通讯录数据
void ModifyContact(contact** con);
//销毁通讯录数据
void DestroyContact(contact** con);
3.2 源文件
#define _CRT_SECURE_NO_WARNINGS
#include "Contact.h"
#include "SList.h"
//初始化通讯录
void InitContact(contact** con)
{
*con = NULL;
FILE* pf = fopen("Contact.txt", "rb");
if (pf == NULL)
{
perror("fopen");
exit(-1);
}
PeoInfo tmp;
contact* pcur = *con;
while (fread(&tmp, sizeof(PeoInfo), 1, pf) == 1)
{
if (*con == NULL)
{
*con = SLTBuyNode(tmp);
pcur = *con;
}
else
{
pcur->next = SLTBuyNode(tmp);
pcur = pcur->next;
}
}
fclose(pf);
}
//添加通讯录数据
void AddContact(contact** con)
{
static PeoInfo newpeo;
printf("请输入新联系人姓名:>");
scanf("%s", newpeo.name);
printf("请输入新联系人性别:>");
scanf("%s", newpeo.sex);
printf("请输入新联系人年龄:>");
scanf("%d", &(newpeo.age));
printf("请输入新联系人电话:>");
scanf("%s", newpeo.tel);
printf("请输入新联系人地址:>");
scanf("%s", newpeo.addr);
SLTPushBack(con, newpeo);
printf("添加成功!\n");
//system("pause"); fflush(stdin); system("cls");
}
//销毁通讯录数据
void DestroyContact(contact** con)
{
FILE* pf = fopen("Contact.txt", "wb");
if (pf == NULL)
{
perror("fopen");
exit(-1);
}
contact* pcur = *con;
*con = NULL;
while (pcur != NULL)
{
contact* del = pcur;
pcur = pcur->next;
fwrite(del, sizeof(PeoInfo), 1, pf);
free(del);
del = NULL;
}
fclose(pf);
}
//按名字查找
contact* ConFindByName(contact* con, char* name)
{
assert(con);
contact* pcur = con;
while (pcur != NULL)
{
if (strcmp(pcur->data.name, name) == 0)
return pcur;
pcur = pcur->next;
}
return NULL;
}
//删除通讯录数据
void DelContact(contact** con)
{
assert(*con);
char name[NAME_MAX];
printf("请输入要删除的联系人的姓名:>");
scanf("%s", name);
contact* find = ConFindByName(*con, name);
if (find == NULL)
{
printf("查无此人!\n");
}
else
{
SLTErase(con, find);
printf("删除成功!\n");
}
}
//展示通讯录数据
void ShowContact(contact* con)
{
if (con == NULL)
{
printf("暂无联系人!\n");
return;
}
contact* pcur = con;
printf("%-10s\t%-10s\t%-5s\t%-20s\t%-20s\n", "姓名", "性别", "年龄", "电话", "地址");
while (pcur != NULL)
{
printf("%-10s\t%-10s\t%-5d\t%-20s\t%-20s\n", pcur->data.name, pcur->data.sex, pcur->data.age, pcur->data.tel, pcur->data.addr);
pcur = pcur->next;
}
}
//查找通讯录数据
void FindContact(contact* con)
{
assert(con);
char name[NAME_MAX];
printf("请输入要查找的联系人的姓名:>");
scanf("%s", name);
contact* find = ConFindByName(con, name);
if (find == NULL)
{
printf("查无此人!\n");
}
else
{
printf("%-10s\t%-10s\t%-5s\t%-20s\t%-20s\n", "姓名", "性别", "年龄", "电话", "地址");
printf("%-10s\t%-10s\t%-5d\t%-20s\t%-20s\n", find->data.name, find->data.sex, find->data.age, find->data.tel, find->data.addr);
}
}
//修改通讯录数据
void ModifyContact(contact** con)
{
assert(*con);
char name[NAME_MAX];
printf("请输入要修改的联系人的姓名:>");
scanf("%s", name);
contact* find = ConFindByName(*con, name);
if (find == NULL)
{
printf("查无此人!\n");
}
else
{
printf("请输入该联系人的新名字:>");
scanf("%s", find->data.name);
printf("请输入该联系人的新性别:>");
scanf("%s", find->data.sex);
printf("请输入该联系人的新年龄:>");
scanf("%d", &(find->data.age));
printf("请输入该联系人的新电话:>");
scanf("%s", find->data.tel);
printf("请输入该联系人的新地址:>");
scanf("%s", find->data.addr);
printf("修改成功!\n");
}
}
4. test.c
#define _CRT_SECURE_NO_WARNINGS
#include "Contact.h"
#include "SList.h"
enum options
{
Exit,
Add,
Del,
Find,
Modi,
Show
};
void menu()
{
printf("||=========通讯录=========||\n");
printf("||======1.增加联系人======||\n");
printf("||======2.删除联系人======||\n");
printf("||======3.查找联系人======||\n");
printf("||======4.修改联系人======||\n");
printf("||======5.查看通讯录======||\n");
printf("||=========0.退出=========||\n");
}
int main()
{
contact* con;
InitContact(&con);
int input = 0;
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case Exit:
DestroyContact(&con);
printf("退出!\n");
break;
case Add:
AddContact(&con);
break;
case Del:
DelContact(&con);
break;
case Find:
FindContact(con);
break;
case Modi:
ModifyContact(&con);
break;
case Show:
ShowContact(con);
break;
default:
printf("输入错误,请重新输入!\n");
break;
}
system("pause"); fflush(stdin); system("cls");
} while (input);
return 0;
}
下面这一行的作用是
1. 暂停让用户看执行结果。
2. 清除输入缓存,防止输入粘连。
3. 清空屏幕,以免屏幕上留下太多信息。
system("pause"); fflush(stdin); system("cls");