【数据结构项目】通讯录

个人主页点这里~

原文件在gitee里~


通讯录的实现

基于动态顺序表实现通讯录项目

准备:结构体、动态内存管理、顺序表、文件操作

1、功能要求

①能够存储100个人的通讯信息

②能够保存用户信息:名字、性别、年龄、电话、地址等

③增加、删除、查找、修改联系人

④显示联系人信息

2、代码实现

当我们将程序关闭时我们可以使用文件流的方法存储通讯录,使得通讯录信息不会丢失

我们在实现通讯录的时候,底层逻辑其实还是顺序表,我们将顺序表稍作修改,然后作为整个项目的其中一个.c文件和一个.h文件

我在实现的过程中,把顺序表相关文件命名为file,通讯录相关文件命名为List,调试文件为test,然后file就是上文顺序表中写出的代码稍加修改,本文对顺序表内容不做过多介绍,详细请参阅上文顺序表

file.h

c 复制代码
#pragma once
#define INIT_CAPACITY 4
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "List.h"
typedef PeoInfo SLDataType;
// 动态顺序表 -- 按需申请
typedef struct SeqList
{
    SLDataType* a;
    int size;     // 有效数据个数
    int capacity; // 空间容量
}SL;

//初始化和销毁
void SLInit(SL* ps);
void SLDestroy(SL* ps);
//打印
void SLPrint(SL* ps);
//扩容
void SLCheckCapacity(SL* ps);

//头部插入删除 / 尾部插入删除
void SLPushBack(SL* ps, SLDataType x);
void SLPopBack(SL* ps);
void SLPushFront(SL* ps, SLDataType x);
void SLPopFront(SL* ps);

//指定位置之前插入/删除数据
void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);
int SLFindByName(SL* ps, char* x);

file.c

c 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include "file.h"
void SLInit(SL* ps)
{
	ps->a = NULL;//将指针a置为空
	ps->capacity = 0;//指针没有指向任何数据,容量为0
	ps->size = 0;//同上,无数据,为0
}
void SLDestroy(SL* ps)
{
	if (ps->a)
	{
		free(ps->a);//释放a指向堆区的内存
		ps->a = NULL;//将a指针置为空
	}
	if (ps->capacity)
		ps->capacity = 0;
	if (ps->size)
		ps->size = 0;
}
void SLPrint(SL* ps)
{
	for (int i = 0; i < ps->size; i++)
	{
		printf("%d ", *(ps->a + i));
	}
}
void SLCheckCapacity(SL* ps)
{
	if (ps->capacity == ps->size)
	{
		int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;//ss
		//检查capacity是否为0,若为0,则开辟一块空间,若不为0,则将空间扩大一倍
		SLDataType* tmp = (SLDataType*)realloc(ps->a, newCapacity * sizeof(SLDataType));
		//使用realloc函数开辟动态内存
		if (tmp == NULL)
		{
			perror(tmp);
			return 1;
		}
		ps->a = tmp;
		ps->capacity = newCapacity;
	}
}
void SLPushFront(SL* ps, SLDataType x)
{
	if (ps->a)//确保不为空第一种方法
	{
		SLCheckCapacity(ps);
		for (int i = ps->size; i > 0; i--)
		{
			*(ps->a + i) = *(ps->a + i - 1);//从最后一位与空位开始交换,直到第一位空出来
		}
		*ps->a = x;//填补第一位
		ps->size++;
	}
}
void SLPopFront(SL* ps)
{
	if (ps->a)
	{
		for (int i = 0; i < ps->size - 2; i++)
		{
			*(ps->a + i) = *(ps->a + i + 1);
		}
		ps->size--;//将size减一最后一位就不会被访问到,将其在数组中删除
	}
}
void SLPushBack(SL* ps, SLDataType x)
{
	assert(ps);
	SLCheckCapacity(ps);
	*(ps->a + ps->size++) = x;//后置++先赋值后++,在最后一位放入x,然后size+1
}
void SLPopBack(SL* ps)
{
	assert(ps);
	assert(ps->size);
	ps->size--;//直接删除
}
void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);//确保不为空第二种方法
	assert(pos >= 0 && pos <= ps->size);
	SLCheckCapacity(ps);
	for (int i = ps->size; i > pos; i--)
	{
		*(ps->a + ps->size) = *(ps->a + ps->size - 1);
		//将要插入的数字位置后的所有数字往后移一位,然后插入
	}
	*(ps->a + pos) = x;
	ps->size++;//后置++
}
void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);
	for (int i = pos; i < ps->size-1; i++)
	{
		ps->a[i] = ps->a[i+1];
	}
	//将所有指定位置以后的数字往前一位
	ps->size--;//直接删除最后一位
}
int SLFindByName(SL* ps, char* x)
{
	for (int i = 0; i < ps->size; i++)
	{
		if (strcmp(x, ps->a[i].name) == 0) // 使用 strcmp 函数来比较字符串  
		{
			return i;
		} // 如果找到匹配项,返回其索引  
	}
	return -1; // 如果未找到,返回 -1  
}

List.h

c 复制代码
#pragma once
#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 11
#define ADDR_MAX 100
//前置声明
typedef struct SeqList contact;
//用户数据
typedef struct PersonInfo
{
	char name[20];
	char sex[20];
	int age;
	char tel[20];
	char addr[20];
}PeoInfo;//定义一个用户信息结构体并重命名为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);

List.c

c 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include "List.h"
#include "file.h"
//初始化通讯录
void InitContact(contact* con)
{
	SLInit(con);//直接调用顺序表的方法,初始化通讯录
}
//添加通讯录数据
void AddContact(contact* con)
{
	PeoInfo i;//定义一个通讯录用户
	printf("请输入联系人姓名:\n");
	scanf("%s", i.name);
	printf("请输入联系人性别:\n");
	scanf("%s", i.sex);
	printf("请输入联系人年龄:\n");
	scanf("%d", &i.age);
	printf("请输入联系人电话:\n");
	scanf("%s", i.tel);
	printf("请输入联系人地址:\n");
	scanf("%s", i.addr);
	SLPushBack(con, i);
}
//删除通讯录数据
void DelContact(contact* con)
{
	char name[NAME_MAX];
	printf("请输入要删除的联系人姓名:\n");
	scanf("%s", name);//输入一个名字
	int f = SLFindByName(con, name);//使用SLFindByName函数找出这个名字对应的下标
	if (f < 0)
	{
		printf("要删除的联系人数据不存在!\n");
		return;//找不到就退出
	}
	SLErase(con, f);//找到就将它使用指定位置删除函数
	printf("删除成功!\n");
}
//展示通讯录数据
void ShowContact(contact* con)
{
	printf("%5s %5s %5s %5s %5s\n", "姓名", "性别", "年龄", "电话", "地址");
	for (int i = 0; i < con->size; i++)
	{
		printf("%5s %5s %5d %5s %5s\n",
			con->a[i].name,
			con->a[i].sex,
			con->a[i].age,
			con->a[i].tel,
			con->a[i].addr);
	}
}
//查找通讯录数据
void FindContact(contact* con)
{
	char name[NAME_MAX];
	printf("请输入要查找的联系人:\n");
	scanf("%s", name);
	int f = SLFindByName(con, name);
	if (f < 0)
	{
		printf("不存在\n");
		return;
	}
	printf("%5s %5s %5s %5s %5s\n", "姓名", "性别", "年龄", "电话", "地址");
	printf("%5s %5s %5d %5s %5s\n",
		con->a[f].name,
		con->a[f].sex,
		con->a[f].age,
		con->a[f].tel,
		con->a[f].addr);
}
//修改通讯录数据
void ModifyContact(contact* con)
{
	char name[NAME_MAX];
	printf("请输入需要修改的联系人姓名:\n");
	scanf("%s", name);
	int f = SLFindByName(con, name);//原理同上
	if (f < 0)
	{
		printf("不存在\n");
		return;
	}
	printf("新姓名:\n");
	scanf("%s", con->a[f].name);
	printf("新性别:\n");
	scanf("%s", con->a[f].sex);
	printf("新年龄:\n");
	scanf("%d", &con->a[f].age);
	printf("新电话:\n");
	scanf("%s", con->a[f].tel);
	printf("新地址:\n");
	scanf("%s", con->a[f].addr);
	printf("修改完成!\n");
}
//销毁通讯录数据
void DestroyContact(contact* con)
{
	SLDestroy(con);//直接调用顺序表销毁
}

test.c

c 复制代码
#include "file.h"
#include "List.h"

void Test()
{
	contact con;
	InitContact(&con);
	AddContact(&con);
	ShowContact(&con);
	AddContact(&con);
	ShowContact(&con);
	AddContact(&con);
	ShowContact(&con);
	DelContact(&con);
	ShowContact(&con);
	FindContact(&con);
	ModifyContact(&con);
	ShowContact(&con);
	DestroyContact(&con);
}
int main()
{
	Test();
	return 0;
}

调试结果:

今天就分享到这里了~


相关推荐
正义的彬彬侠4 分钟前
协方差矩阵及其计算方法
人工智能·机器学习·协方差·协方差矩阵
hutaotaotao11 分钟前
c语言用户不同命令调用不同函数实现
c语言·开发语言
huangjiazhi_12 分钟前
QTcpSocket 服务端和客户端
开发语言·qt
lb363636363613 分钟前
介绍一下位操作符(c基础)
c语言·知识点
ac-er888827 分钟前
ThinkPHP中的MVC分层是什么
开发语言·php·mvc
m0_743106461 小时前
论文笔记:no pose,no problem-基于dust3r输出GS参数实现unpose稀疏重建
论文阅读·深度学习·计算机视觉·3d·几何学
shinelord明1 小时前
【再谈设计模式】建造者模式~对象构建的指挥家
开发语言·数据结构·设计模式
十七算法实验室1 小时前
Matlab实现麻雀优化算法优化随机森林算法模型 (SSA-RF)(附源码)
算法·决策树·随机森林·机器学习·支持向量机·matlab·启发式算法
黑不拉几的小白兔1 小时前
PTA部分题目C++重练
开发语言·c++·算法
写bug的小屁孩1 小时前
websocket身份验证
开发语言·网络·c++·qt·websocket·网络协议·qt6.3