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");