(超详细)基于动态顺序表实现简单的通讯录项目

2024-06-16 23:36

本文主要是介绍(超详细)基于动态顺序表实现简单的通讯录项目,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言:

  我们在上一章节用c语言实现了线性表中的的动态顺序表,那么顺序表就只是顺序表吗?当然不是,使用顺序表结构可以实现很多项目,许多项目的数据结构都会用到顺序表,本章节我们就要使用顺序表实现一个简易的通讯录项目。

准备

  由于我们的通讯录是基于动态顺序表实现的,所以我们实现这个项目会用到动态顺序表的底层代码。在动态顺序表中有三个文件,分别是头文件代码SeqList.h文件,包含项目实现代码SeqList文件,和测试文件test.c文件,我们要在此基础上增加两个文件实现通讯录,分别是包含头文件的Contact.h文件,和实现代码的Contact.c文件:

     在上一期的顺序表中,我们用一个结构体代表顺序表,而里面的arr数组负责存储数据,但是它内部存储的数据都是内置类型,如int,char类型的数据,所以比较简单。在这一期,我们要使用这个数组存储自定义类型,每个自定义类型都存储了一个联系人的信息,这样我们的顺序表就开始变得复杂了起来:

通讯录实现 

  我们说顺序表里存储的不再是内置类型,而是自定义类型,那么是怎样实现的呢?我们使用一个结构体,在它内部我们定义一个人的名字,性别,年龄,电话号码,家庭地址等信息使用数组存储,为了方便更改数组的长度,使用#define定义几个常量作为它们的数组长度,这个结构体我们将它命名为ConPeoInfo,为了方便使用,我们用typedef将它改名为Info:

#define NAME_MAX 20
#define GENDER_MAX 10
#define TEL_MAX 20
#define ADDR_MAX 100typedef struct ConPeoInfo
{char name[NAME_MAX];char gender[GENDER_MAX];int age;char tel[TEL_MAX];char addr[ADDR_MAX];
}Info;

定了好了自定义类型后我们只需要将需要实现的方法一一实现即可。

通讯录初始化和销毁

通讯录的初始化和销毁我们可以直接调用我们之前在顺序表的初始化方法,所以它们实现起来非常的简单。

通讯录初始化:
void ContactInit(Contact* con)
{assert(con);SeqInit(con);
}//初始化
通讯录销毁:
void ContactDestroy(Contact* con)
{SeqDestroy(con);
}//销毁

在这里我们提一下Contact类型就是SL类型,也就是顺序表类型。那么为什么要将它改名为Contact呢?contact的中文翻译为联系人,而SL也许放在通讯录代码中多数人都不认识,只会认为它是一个顺序表,所以为了让代码的辨识度更高,我们利用前置声明将SeqList类型改为了Contact类型:

typedef struct SeqList Contact;
//前置声明
添加联系人 :

   添加联系人是通讯录中最基本的功能。我们用一个Info类型的变量去接收我们要添加的联系人信息,再使用顺序表中的尾插方法将这个变量插入通讯录中:

void ContactAdd(Contact* con)
{Info cpi;printf("请输入要添加的姓名:\n");scanf("%s", cpi.name);printf("请输入要添加的性别:\n");scanf("%s", cpi.gender);printf("请输入要添加的年龄:\n");scanf("%d", &cpi.age);printf("请输入要添加的电话:\n");scanf("%s", cpi.tel);printf("请输入要添加的地址:\n");scanf("%s", cpi.addr);SeqPushBack(con, cpi);}//添加联系人

当然我们也可以使用其他插入方法,如头插,指定位置插入。

删除联系人与通过姓名查找: 

  有添加就会有删除,删除联系人我们可以先通过查找联系人姓名来确定有没有这个人的信息,如果没有就输出没有这个联系人,如果有我们就将找到的联系人所在的下标返回,然后将这个下标的信息删除。

通过姓名查找联系人:
int FindByName(Contact* con, char name[])
{int i = 0;for (i = 0; i < con->size; i++){if (strcmp(con->arr[i].name, name) == 0){return i;}}return -1;
}
删除联系人: 
void ContactDel(Contact* con)
{char name[NAME_MAX];printf("请输入要删除的联系人姓名:\n");scanf("%s", name);int find = FindByName(con, name);if (find < 0){printf("没有要删除的联系人数据!\n");return;}SLErase(con, find);printf("删除成功!\n");
}//删除

删除联系人我们使用了顺序表中的指定位置删除,因为我们返回的下标就是我们要删除的联系人所在的下标,所以这里我们只能使用指定位置删除这个方法。

修改联系人信息: 

 修改联系人我们同样采用查找联系人姓名的方法先确定有没有我们要修改的联系人信息,如果没有就无法修改,如果有我们才执行修改操作,而修改操作与添加操作相似:

void ContactMorify(Contact* con)
{char name[NAME_MAX];printf("请输入要修改的联系人姓名:\n");scanf("%s", name);int find = FindByName(con, name);if (find < 0){printf("通讯录中没有要修改的联系人信息!\n");return;}printf("请输入新的姓名:\n");scanf("%s", con->arr[find].name);printf("请输入新的性别:\n");scanf("%s", con->arr[find].gender);printf("请输入新的年龄:\n");scanf("%d", &con->arr[find].age);printf("请输入新的电话:\n");scanf("%s",con->arr[find].tel);printf("请输入新的地址:\n");scanf("%s",con->arr[find].addr);printf("修改成功!\n");}//修改
查找联系人 :

查找联系人则比较简单,我们同样使用查找联系人姓名的方法去确定有没有这个联系人,如果有我们就把这个联系人的信息全部打印出来:

void ContactFind(Contact* con)
{char name[NAME_MAX];printf("请输入要查找的联系人姓名:\n");scanf("%s", name);int find = FindByName(con, name);if (find < 0){printf("要查找的联系人的数据不存在!\n");return;}printf("%5s  %5s  %5s  %5s %5s\n", "姓名", "性别", "年龄", "电话", "地址");printf("%s  %s  %d  %s  %s\n", con->arr[find].name,con->arr[find].gender,con->arr[find].age,con->arr[find].tel,con->arr[find].addr);
}
展示所有联系人信息:

当我们要查看所有联系人信息时,我们就可以使用这个方法,这个方法也比较简单,我们只需要将整个顺序表遍历一遍并将每个联系人的信息全部打印出来:

void ContactShow(Contact* con)
{int i = 0;printf("%5s  %5s  %5s  %5s %5s\n", "姓名", "性别", "年龄", "电话", "地址");for (i = 0; i < con->size; i++){printf("%s  %s  %d  %s  %s\n", con->arr[i].name,con->arr[i].gender,con->arr[i].age,con->arr[i].tel,con->arr[i].addr);}
}//所有联系人
 测试通讯录:

 当实现了这些方法之后,我们就可以实现通讯录的界面了,创建一个菜单函数,我们可以用指定数字来表示我们要执行的操作,比如我们要添加联系人,我们按数字1就可以开始添加联系人:

void menu()
{printf("*************通讯录************\n");printf("****1.添加联系人 2.删除联系人**\n");printf("****3.查找联系人 4.修改联系人**\n");printf("****5.全部联系人 0.退出********\n");printf("*******************************\n");}

我们来看一下菜单:

菜单里的输入数字执行操作的功能我们使用switch语句实现:

int main()
{Contact con;int op = -1;ContactInit(&con);do{menu();printf("请选择您要进行的操作:\n");scanf("%d", &op);switch (op){case 1:ContactAdd(&con);break;case 2:ContactDel(&con);break;case 3:ContactFind(&con);break;case 4:ContactMorify(&con);break;case 5:ContactShow(&con);break;default:printf("输入错误,请重新输入!\n");break;}} while (op != 0);ContactDestroy(&con);//ContactTest01();return 0;
}

到这里我们通讯录所有的代码就已经实现完成了,我们来测试一下吧:

通过测试发现我们的方法都没有什么问题,我将代码放在下面 感兴趣的小伙伴可以试一下哦。

Contact.h :

#pragma once
typedef struct SeqList Contact;
//前置声明#define NAME_MAX 20
#define GENDER_MAX 10
#define TEL_MAX 20
#define ADDR_MAX 100typedef struct ConPeoInfo
{char name[NAME_MAX];char gender[GENDER_MAX];int age;char tel[TEL_MAX];char addr[ADDR_MAX];
}Info;//初始化
void ContactInit(Contact* con);
void ContactAdd(Contact* con);//添加
void ContactDel(Contact* con);//删除
void ContactMorify(Contact* con);//修改void ContactFind(Contact* con);//查找
void ContactShow(Contact* con);//展示
//销毁
void ContactDestroy(Contact* con);

SeqList.h :

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include"Contact.h"typedef struct ConPeoInfo SLDataType;
typedef struct SeqList
{SLDataType* arr;int size;//有效数据int capacity;//空间大小}SL;void SeqInit(SL* ps);//初始化void SeqDestroy(SL* ps);//销毁void SeqPushBack(SL* ps, SLDataType x);//尾插void SeqPushFront(SL* ps, SLDataType x);//头插void SeqPopBack(SL* ps);//尾删void SeqPopBack(SL* ps);//头删void SeqPrint(SL* ps);//打印void SLErase(SL* ps, int pos);//指定删除int SLFind(SL* ps, SLDataType x);//查找数据//指定下标前插入数据
void SLInsert(SL* ps, int pop, SLDataType x);

SeqList.c :

#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"void SeqInit(SL* ps)
{ps->arr = NULL;ps->size = ps->capacity = 0;
}//初始化void SeqCheckcapa(SL* ps)//检查内存够不够,不够则增加
{assert(ps);if (ps->capacity == ps->size){int Newcapecity = ps->capacity == 0 ? 4 : 2 * ps->capacity * sizeof(SLDataType);SLDataType* tem = (SLDataType*)realloc(ps->arr, Newcapecity  * sizeof(SLDataType));if (tem != NULL){ps->arr = tem;}}
}void SeqPushBack(SL* ps, SLDataType x)
{assert(ps);SeqCheckcapa(ps);ps->arr[ps->size++] = x;}//尾插void SeqPushFront(SL* ps, SLDataType x)
{assert(ps);SeqCheckcapa(ps);int i = 0;for (i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[0] = x;++ps->size;
}//头插void SeqPopBack(SL* ps)
{assert(ps);assert(ps->size >= 0);ps->size--;
}//尾删void SeqPopFront(SL* ps)
{assert(ps);assert(ps->size >= 0);int i = 0;for (i = 0; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;}//头删void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);SeqCheckcapa(ps);int i = 0;for (i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;++ps->size;}//指定下标前插入数据void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);int i = 0;for (i = pos; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}//指定下标删除//int SLFind(SL* ps, SLDataType x)
//{
//	assert(ps);
//	int i = 0;
//	for (i = 0; i < ps->size; i++)
//	{
//		if (ps->arr[i] == x)
//		{
//			return i;
//		}
//	}
//	return -1;
//}//查找数据
//void SeqPrint(SL* ps)
//{
//	assert(ps);
//	int i = 0;
//
//	for (i = 0; i < ps->size; i++)
//	{
//		printf("%d ", ps->arr[i]);
//	}
//	printf("\n");
//}//打印void SeqDestroy(SL* ps)
{assert(ps);free(ps->arr);if (ps->arr != NULL);{ps->arr = NULL;}ps->capacity = ps->size = 0;
}
//销毁

Contact.c :

#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
#include"Contact.h"
#include<string.h>void ContactInit(Contact* con)
{assert(con);SeqInit(con);
}//初始化
int FindByName(Contact* con, char name[])
{int i = 0;for (i = 0; i < con->size; i++){if (strcmp(con->arr[i].name, name) == 0){return i;}}return -1;
}void ContactAdd(Contact* con)
{Info cpi;printf("请输入要添加的姓名:\n");scanf("%s", cpi.name);printf("请输入要添加的性别:\n");scanf("%s", cpi.gender);printf("请输入要添加的年龄:\n");scanf("%d", &cpi.age);printf("请输入要添加的电话:\n");scanf("%s", cpi.tel);printf("请输入要添加的地址:\n");scanf("%s", cpi.addr);SeqPushBack(con, cpi);}//添加联系人void ContactDel(Contact* con)
{char name[NAME_MAX];printf("请输入要删除的联系人姓名:\n");scanf("%s", name);int find = FindByName(con, name);if (find < 0){printf("没有要删除的联系人数据!\n");return;}SLErase(con, find);printf("删除成功!\n");
}//删除void ContactMorify(Contact* con)
{char name[NAME_MAX];printf("请输入要修改的联系人姓名:\n");scanf("%s", name);int find = FindByName(con, name);if (find < 0){printf("通讯录中没有要修改的联系人信息!\n");return;}printf("请输入新的姓名:\n");scanf("%s", con->arr[find].name);printf("请输入新的性别:\n");scanf("%s", con->arr[find].gender);printf("请输入新的年龄:\n");scanf("%d", &con->arr[find].age);printf("请输入新的电话:\n");scanf("%s",con->arr[find].tel);printf("请输入新的地址:\n");scanf("%s",con->arr[find].addr);printf("修改成功!\n");}//修改
void ContactFind(Contact* con)
{char name[NAME_MAX];printf("请输入要查找的联系人姓名:\n");scanf("%s", name);int find = FindByName(con, name);if (find < 0){printf("要查找的联系人的数据不存在!\n");return;}printf("%5s  %5s  %5s  %5s %5s\n", "姓名", "性别", "年龄", "电话", "地址");printf("%s  %s  %d  %s  %s\n", con->arr[find].name,con->arr[find].gender,con->arr[find].age,con->arr[find].tel,con->arr[find].addr);
}
void ContactShow(Contact* con)
{int i = 0;printf("%5s  %5s  %5s  %5s %5s\n", "姓名", "性别", "年龄", "电话", "地址");for (i = 0; i < con->size; i++){printf("%s  %s  %d  %s  %s\n", con->arr[i].name,con->arr[i].gender,con->arr[i].age,con->arr[i].tel,con->arr[i].addr);}
}//所有联系人
void ContactDestroy(Contact* con)
{SeqDestroy(con);
}//销毁

test.c :

#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
#include"Contact.h"
void menu()
{printf("*************通讯录************\n");printf("****1.添加联系人 2.删除联系人**\n");printf("****3.查找联系人 4.修改联系人**\n");printf("****5.全部联系人 0.退出********\n");printf("*******************************\n");}
int main()
{Contact con;int op = -1;ContactInit(&con);do{menu();printf("请选择您要进行的操作:\n");scanf("%d", &op);switch (op){case 1:ContactAdd(&con);break;case 2:ContactDel(&con);break;case 3:ContactFind(&con);break;case 4:ContactMorify(&con);break;case 5:ContactShow(&con);break;default:printf("输入错误,请重新输入!\n");break;}} while (op != 0);ContactDestroy(&con);//ContactTest01();return 0;
}

这篇关于(超详细)基于动态顺序表实现简单的通讯录项目的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1067864

相关文章

python使用watchdog实现文件资源监控

《python使用watchdog实现文件资源监控》watchdog支持跨平台文件资源监控,可以检测指定文件夹下文件及文件夹变动,下面我们来看看Python如何使用watchdog实现文件资源监控吧... python文件监控库watchdogs简介随着Python在各种应用领域中的广泛使用,其生态环境也

el-select下拉选择缓存的实现

《el-select下拉选择缓存的实现》本文主要介绍了在使用el-select实现下拉选择缓存时遇到的问题及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录项目场景:问题描述解决方案:项目场景:从左侧列表中选取字段填入右侧下拉多选框,用户可以对右侧

基于Qt开发一个简单的OFD阅读器

《基于Qt开发一个简单的OFD阅读器》这篇文章主要为大家详细介绍了如何使用Qt框架开发一个功能强大且性能优异的OFD阅读器,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 目录摘要引言一、OFD文件格式解析二、文档结构解析三、页面渲染四、用户交互五、性能优化六、示例代码七、未来发展方向八、结论摘要

最新版IDEA配置 Tomcat的详细过程

《最新版IDEA配置Tomcat的详细过程》本文介绍如何在IDEA中配置Tomcat服务器,并创建Web项目,首先检查Tomcat是否安装完成,然后在IDEA中创建Web项目并添加Web结构,接着,... 目录配置tomcat第一步,先给项目添加Web结构查看端口号配置tomcat    先检查自己的to

使用Nginx来共享文件的详细教程

《使用Nginx来共享文件的详细教程》有时我们想共享电脑上的某些文件,一个比较方便的做法是,开一个HTTP服务,指向文件所在的目录,这次我们用nginx来实现这个需求,本文将通过代码示例一步步教你使用... 在本教程中,我们将向您展示如何使用开源 Web 服务器 Nginx 设置文件共享服务器步骤 0 —

Python pyinstaller实现图形化打包工具

《Pythonpyinstaller实现图形化打包工具》:本文主要介绍一个使用PythonPYQT5制作的关于pyinstaller打包工具,代替传统的cmd黑窗口模式打包页面,实现更快捷方便的... 目录1.简介2.运行效果3.相关源码1.简介一个使用python PYQT5制作的关于pyinstall

使用Python实现大文件切片上传及断点续传的方法

《使用Python实现大文件切片上传及断点续传的方法》本文介绍了使用Python实现大文件切片上传及断点续传的方法,包括功能模块划分(获取上传文件接口状态、临时文件夹状态信息、切片上传、切片合并)、整... 目录概要整体架构流程技术细节获取上传文件状态接口获取临时文件夹状态信息接口切片上传功能文件合并功能小

python实现自动登录12306自动抢票功能

《python实现自动登录12306自动抢票功能》随着互联网技术的发展,越来越多的人选择通过网络平台购票,特别是在中国,12306作为官方火车票预订平台,承担了巨大的访问量,对于热门线路或者节假日出行... 目录一、遇到的问题?二、改进三、进阶–展望总结一、遇到的问题?1.url-正确的表头:就是首先ur

C#实现文件读写到SQLite数据库

《C#实现文件读写到SQLite数据库》这篇文章主要为大家详细介绍了使用C#将文件读写到SQLite数据库的几种方法,文中的示例代码讲解详细,感兴趣的小伙伴可以参考一下... 目录1. 使用 BLOB 存储文件2. 存储文件路径3. 分块存储文件《文件读写到SQLite数据库China编程的方法》博客中,介绍了文

Redis主从复制实现原理分析

《Redis主从复制实现原理分析》Redis主从复制通过Sync和CommandPropagate阶段实现数据同步,2.8版本后引入Psync指令,根据复制偏移量进行全量或部分同步,优化了数据传输效率... 目录Redis主DodMIK从复制实现原理实现原理Psync: 2.8版本后总结Redis主从复制实