目录
[2.1 初始化通讯录](#2.1 初始化通讯录)
[2.2 添加通讯录数据](#2.2 添加通讯录数据)
[2.3 展示通讯录](#2.3 展示通讯录)
[2.4 按名字来查找通讯录信息](#2.4 按名字来查找通讯录信息)
[2.5 删除通讯录的数据](#2.5 删除通讯录的数据)
[2.6 查找通讯录的数据](#2.6 查找通讯录的数据)
[2.7 修改通讯录的数据](#2.7 修改通讯录的数据)
[2.8 销毁通讯录](#2.8 销毁通讯录)
前言
之前我们讲了数据结构中的顺序表:数据结构------顺序表
今天我们基于顺序表来实现通讯录,实现添加,删除,查找,修改,展示的功能。通过结构体来存储通讯录的数据,通过菜单进行交互,最后进行上传到文件中保存,这就是我们通讯录的功能实现。
一、 基于动态顺序表实现通讯录
C语⾔基础要求:结构体、动态内存管理、顺序表、文件操作
1、功能要求
1)至少能够存储100个人的通讯信息
2)能够保存用户信息:名字、性别、年龄、电话、地址等
3)增加联系⼈信息
4)删除指定联系⼈
5)查找制定联系⼈
6)修改指定联系⼈
7)显示联系⼈信息
以上就是通讯录的功能要求,现在我们就来实现代码。
二、代码具体实现
实现我们是基于顺序表代码实现的,所以我们需要顺序表的头文件
cpp
//Seqlist.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>
#include"contact.h"
typedef PeoInfo SLDataType;//定义新的数据类型
typedef struct Seqlist {
SLDataType* arr;
int size; //有效数据个数
int capacity; //数组容量
} SL;
//初始化和销毁
void SLInit(SL* ps);
void SLDestroy(SL* ps);
void SLPrint(SL* ps);
//扩容
void SLCheckCapacity(SL* ps);
//头部插入
void SLPushFront(SL* ps, SLDataType x);
//尾部插入
void SLPushBack(SL* ps, SLDataType x);
//头部删除
void SLPopFront(SL* ps);
//尾部删除
void SLPopBack(SL* ps);
//插入任意位置
void SLInsert(SL* ps, int pos, SLDataType x);
//删除任意位置
void SLErase(SL* ps, int pos);
//查找元素
int SLFind(SL* ps, SLDataType x);
跟顺序表一样,只不过顺序表内容不是整型内容,而是我们定义的结构体内容(联系人信息)
cpp
//contact.h
#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 12
#define ADDR_MAX 100
typedef struct PersonInfo
{
char name[NAME_MAX];//姓名
char sex[SEX_MAX];//性别
int age;//年龄
char tel[TEL_MAX];//电话
char addr[ADDR_MAX];//住址
}PeoInfo;//结构体类型
现在我们就要进行通讯录的功能实现了
主要接口:
cpp
//contact.h
//前置类型声明
struct Seqlist;//调用必须先声明
typedef struct Seqlist contact;//给顺序表重命名为contact
//初始化通讯录
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);
//读取本地通讯录
void LoadContact(contact* con);
//上传通讯录数据到文件
void SaveContact(contact* con);
2.1 初始化通讯录
cpp
//初始化通讯录
void InitContact(contact* con) {
SLInit(con);
}
调用顺序表的初始化函数SLInit函数,即可完成对通讯录的初始化。
2.2 添加通讯录数据
cpp
void AddContact(contact* con) {
PeoInfo info; //定义一个结构体类型为 通讯录数据
printf("请输入姓名:\n");
scanf("%s", &info.name);
printf("请输入性别:\n");
scanf("%s", &info.sex);
printf("请输年龄:\n");
scanf("%d", &info.age);
printf("请输入电话:\n");
scanf("%s", &info.tel);
printf("请输入住址:\n");
scanf("%s", &info.addr);
printf("添加成功\n");
SLPushBack(con, info);//调用顺序表尾插
}
我们要添加联系人,就要添加一个我们定义的PeoInfo结构体(联系人信息)的结构体变量,然后往里面添加姓名,性别,年龄,电话,住址信息,最后插入通讯录。
2.3 展示通讯录
我们添加后查看通讯录里面的有哪些联系人信息。
cpp
void ShowContact(contact* con) {
printf("%-10s %-4s %-4s %15s %-20s\n", "姓名", "性别", "年龄", "电话", "住址");
for (int i = 0; i < con->size; i++) {//打印个数小于有效数据个数
printf("%-10s %-4s %-4d %15s %-20s\n",
con->arr[i].name,
con->arr[i].sex,
con->arr[i].age,
con->arr[i].tel,
con->arr[i].addr);
}
}
2.4 按名字来查找通讯录信息
我们进行删除,修改,查找操作之前我们要找到操作的对象,我们以名字来查找。
cpp
int FindByName(contact* con, char name[]) {
for (int i = 0; i < con->size; i++) {
if (strcmp(con->arr[i].name, name) == 0) {
return i;//找到返回下标
}
}
return -1;//没找到返回-1
}
2.5 删除通讯录的数据
cpp
void DelContact(contact* con) {
char name[NAME_MAX];//定义数组为删除人的名字
printf("请输入删除人的姓名:\n");
scanf("%s", name);
int pos = FindByName(con, name);//进行查找
if (pos < 0) {
printf("没有找到删除的人名,删除失败\n");
}
else {
SLErase(con, pos);
printf("删除成功!\n");
}
}
我们调用顺序表删除任意位置的元素SLErase函数,进行删除通讯录里面的数据。
2.6 查找通讯录的数据
cpp
//查找通讯录的数据
void FindContact(contact* con) {
char name[NAME_MAX];//定义数组为查找人的姓名
printf("请输入查找人的姓名:\n");
scanf("%s", name);
int pos = FindByName(con, name);//查找是否存在
if (pos < 0) {
printf("没有找到,查找失败\n");
}
else {
printf("找到了:\n");//找到了打印信息
printf("%-10s %-4s %-4d %15s %-20s\n",
con->arr[pos].name,
con->arr[pos].sex,
con->arr[pos].age,
con->arr[pos].tel,
con->arr[pos].addr);
}
}
2.7 修改通讯录的数据
cpp
void ModifyContact(contact* con) {
char name[NAME_MAX];//定义数组为修改人的姓名
printf("请输入姓名:\n");
scanf("%s", name);
int pos = FindByName(con, name);//查找
if (pos < 0) {
printf("没有找到,修改失败\n");
}
else {
printf("请输入修改人的姓名:\n");
scanf("%s", &con->arr[pos].name);
printf("请输入修改人的性别:\n");
scanf("%s", &con->arr[pos].sex);
printf("请输修改人的年龄:\n");
scanf("%d", &con->arr[pos].age);
printf("请输入修改人的电话:\n");
scanf("%s", &con->arr[pos].tel);
printf("请输入修改人的住址:\n");
scanf("%s", &con->arr[pos].addr);
printf("修改成功\n");
}
}
2.8 销毁通讯录
cpp
//销毁通讯录数据
void DestroyContact(contact* con) {
SLDestroy(con);
}
我们调用顺序表的销毁函数SLDestroy进行销毁通讯录的数据
但是我们要保留通讯录的数据,那么我们就可以在销毁前写入文件中:
上传通讯录数据
cpp
void SaveContact(contact* con) {
FILE* pf = fopen("contact.txt", "wb");//文件指针
if (pf == NULL) {
perror("fopen error!\n");
return;
}
//将通讯录数据写⼊⽂件
for (int i = 0; i < con->size; i++)
{
fwrite(con->arr + i, sizeof(PeoInfo), 1, pf);//通过fwrite写入文件
}
printf("通讯录数据保存成功!\n");
}
在下次使用时初始化中
写入通讯录数据
cpp
void LoadContact(contact* con) {
FILE* pf = fopen("contact.txt", "rb");
if (pf == NULL) {
perror("fopen error!\n");
return;
}
//循环读取⽂件数据
PeoInfo info;//定义info为通讯录数据
while (fread(&info, sizeof(PeoInfo), 1, pf))//读info类型数据不为空
{
SLPushBack(con, info);//尾插info数据
}
printf("历史数据导入通讯录成功!\n");
}
三、完整代码
通讯录功能头文件
cpp
//contact.h
#pragma once
#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 12
#define ADDR_MAX 100
typedef struct PersonInfo
{
char name[NAME_MAX];
char sex[SEX_MAX];
int age;
char tel[TEL_MAX];
char addr[ADDR_MAX];
}PeoInfo;
//前置类型
struct Seqlist;
typedef struct Seqlist contact;
//初始化通讯录
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);
//读取本地通讯录
void LoadContact(contact* con);
//上传通讯录数据到文件
void SaveContact(contact* con);
通讯录功能具体实现
cpp
//contact.c
#include"Seqlist.h"
#include"contact.h"
//初始化通讯录
void InitContact(contact* con) {
SLInit(con);
LoadContact(con);
}
//添加通讯录数据
void AddContact(contact* con) {
PeoInfo info;
printf("请输入姓名:\n");
scanf("%s", &info.name);
printf("请输入性别:\n");
scanf("%s", &info.sex);
printf("请输年龄:\n");
scanf("%d", &info.age);
printf("请输入电话:\n");
scanf("%s", &info.tel);
printf("请输入住址:\n");
scanf("%s", &info.addr);
printf("添加成功\n");
SLPushBack(con, info);
}
//展⽰通讯录
void ShowContact(contact* con) {
printf("%-10s %-4s %-4s %15s %-20s\n", "姓名", "性别", "年龄", "电话", "住址");
for (int i = 0; i < con->size; i++) {
printf("%-10s %-4s %-4d %15s %-20s\n",
con->arr[i].name,
con->arr[i].sex,
con->arr[i].age,
con->arr[i].tel,
con->arr[i].addr);
}
}
//按名字来查找
int FindByName(contact* con, char name[]) {
for (int i = 0; i < con->size; i++) {
if (strcmp(con->arr[i].name, name) == 0) {
return i;
}
}
return -1;
}
//删除通讯录的数据
void DelContact(contact* con) {
char name[NAME_MAX];
printf("请输入删除人的姓名:\n");
scanf("%s", name);
int pos = FindByName(con, name);
if (pos < 0) {
printf("没有找到删除的人名,删除失败\n");
}
else {
SLErase(con, pos);
printf("删除成功!\n");
}
}
//查找通讯录的数据
void FindContact(contact* con) {
char name[NAME_MAX];
printf("请输入查找人的姓名:\n");
scanf("%s", name);
int pos = FindByName(con, name);
if (pos < 0) {
printf("没有找到,查找失败\n");
}
else {
printf("找到了:\n");
printf("%-10s %-4s %-4d %15s %-20s\n",
con->arr[pos].name,
con->arr[pos].sex,
con->arr[pos].age,
con->arr[pos].tel,
con->arr[pos].addr);
}
}
//修改通讯录数据
void ModifyContact(contact* con) {
char name[NAME_MAX];
printf("请输入姓名:\n");
scanf("%s", name);
int pos = FindByName(con, name);
if (pos < 0) {
printf("没有找到,修改失败\n");
}
else {
printf("请输入修改人的姓名:\n");
scanf("%s", &con->arr[pos].name);
printf("请输入修改人的性别:\n");
scanf("%s", &con->arr[pos].sex);
printf("请输修改人的年龄:\n");
scanf("%d", &con->arr[pos].age);
printf("请输入修改人的电话:\n");
scanf("%s", &con->arr[pos].tel);
printf("请输入修改人的住址:\n");
scanf("%s", &con->arr[pos].addr);
printf("修改成功\n");
}
}
//销毁通讯录数据
void DestroyContact(contact* con) {
SaveContact(con);
SLDestroy(con);
}
//读取本地通讯录
void LoadContact(contact* con) {
FILE* pf = fopen("contact.txt", "rb");
if (pf == NULL) {
perror("fopen error!\n");
return;
}
//循环读取⽂件数据
PeoInfo info;
while (fread(&info, sizeof(PeoInfo), 1, pf))
{
SLPushBack(con, info);
}
printf("历史数据导入通讯录成功!\n");
}
//上传通讯录数据到文件
void SaveContact(contact* con) {
FILE* pf = fopen("contact.txt", "wb");
if (pf == NULL) {
perror("fopen error!\n");
return;
}
//将通讯录数据写⼊⽂件
for (int i = 0; i < con->size; i++)
{
fwrite(con->arr + i, sizeof(PeoInfo), 1, pf);
}
printf("通讯录数据保存成功!\n");
}
通讯录主函数
cpp
contactest.ccontactest.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"
#include"Seqlist.h"
void num() {
printf("*************************************\n");
printf("**** 1. 添加联系人 2. 删除联系人****\n");
printf("**** 3. 查找联系人 4. 修改联系人****\n");
printf("**** 5. 展示通讯录 0. 退出 ****\n");
printf("*************************************\n");
}
int main() {
int inputt = 0;
contact con;
InitContact(&con);
do {
num();
printf("请输入操作:\n");
scanf("%d", &inputt);
switch (inputt)
{
case 1:AddContact(&con);
break;
case 2:DelContact(&con);
break;
case 3: FindContact(&con);
break;
case 4:ModifyContact(&con);
break;
case 5:ShowContact(&con);
break;
case 0:
printf("通讯录退出中--\n");
break;
}
} while (inputt);
DestroyContact(&con);
return 0;
}
还要顺序表的代码,这里就不在赘述。
总结
上述文章讲了基于顺序表为主要框架来实现通讯录的功能,希望对你有所帮助。