数据结构——顺序表实现通讯录

目录

前言

一、基于动态顺序表实现通讯录

二、代码具体实现

[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;
}

还要顺序表的代码,这里就不在赘述。


总结

上述文章讲了基于顺序表为主要框架来实现通讯录的功能,希望对你有所帮助。

相关推荐
Yan.love16 分钟前
开发场景中Java 集合的最佳选择
java·数据结构·链表
冠位观测者26 分钟前
【Leetcode 每日一题】2545. 根据第 K 场考试的分数排序
数据结构·算法·leetcode
就爱学编程1 小时前
重生之我在异世界学编程之C语言小项目:通讯录
c语言·开发语言·数据结构·算法
ALISHENGYA2 小时前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(实战项目二)
数据结构·c++·算法
DARLING Zero two♡3 小时前
【优选算法】Pointer-Slice:双指针的算法切片(下)
java·数据结构·c++·算法·leetcode
波音彬要多做4 小时前
41 stack类与queue类
开发语言·数据结构·c++·学习·算法
Noah_aa5 小时前
代码随想录算法训练营第五十六天 | 图 | 拓扑排序(BFS)
数据结构
KpLn_HJL5 小时前
leetcode - 2139. Minimum Moves to Reach Target Score
java·数据结构·leetcode
AC使者11 小时前
5820 丰富的周日生活
数据结构·算法