拿捏 顺序表(2) ----- 实现通讯录


正文开始

前言

书接上文, 我们已经初步了解了线性表, 顺序表其实就是在数组的基础上增加了一些特有的功能, 那么顺序表有哪些应用呢? 下面我们一起使用顺序表实现通讯录的功能.

博客主页:酷酷学!!!

基于上篇的讲解, 我们继续来给顺序表添加以下三个功能

//在指定位置前插入元素
void SLInsert(SL* sp,int pos,DataType x);
//删除指定位置的元素
void SLErase(SL* sp, int pos);
//查找元素所在位置
int SLFind(SL* sp, DataType x);

上篇我们已经了解了顺序表基础的运用, 基于此我们让顺序表的功能更完善
实现代码如下:

void SLInsert(SL* sp, int pos, DataType x)
{
	assert(sp);
	assert(pos >= 0 && pos <= sp->size);
	SLCheckcapacity(sp);
	for (int i = sp->size; i>pos; i--)
	{
		sp->arr[i] = sp->arr[i - 1];//最后一次arr[pos+1] = arr[pos]
	}
	sp->arr[pos] = x;
	sp->size++;
}

void SLErase(SL* sp, int pos)
{
	assert(sp);
	assert(pos >= 0 && pos < sp->size);
	for (int i = pos; i<sp->size-1; i++)
	{
		sp->arr[i] = sp->arr[i + 1];//最后一次arr[size-2] = arr[size-1] 
	}
	sp->size--;
}

int SLFind(SL* sp, DataType x)
{
	assert(sp);
	for (int i = 0; i < sp->size; i++)
	{
		if (x == sp->arr[i])
		{
			return i;
		}
	}
	return -1;
}

上面三个函数分别对应以上三个功能, 其中查找函数只能运用于整形, 不适用于通讯录查找, 所以在实现通讯录功能时我们可以注释掉, 下面将进入本篇正题: 实现通讯录功能

一. 通讯录功能要求

1)至少少能够存储100个⼈的通讯信息
2)能够保存用户信息:名字、性别、年龄、电话、地址等
3)增加联系人信息
4)删除指定联系人
5)查找制定联系人
6)修改指定联系人
7)显示联系⼈信息

二. 实现方法

第一步:

基于顺序表我们在此之上创建两个文件, 分别为Contact.h和Contact.c用来存放通讯录的声明和方法实现

在这里插入图片描述

第二步:

#pragma once
#define MAX_NAME 20
#define MAX_GENDER 10
#define MAX_TEL 10
#define MAX_ADDRESS 100


typedef struct personInfo
{
	char name[MAX_NAME];
	char gender[MAX_GENDER];
	int age;
	char tel[MAX_TEL];
	char address[MAX_ADDRESS];
}peoInfo;


typedef struct SeqList Contact;//需要先前置声明,才能改名字

在Contact.h 头文件中声明一个通讯录的类型, 并且将顺序表改名字为Contact,这样做的目的是为了格式化统一, 但是修改前不能使用 typedef SL Contact 来修改, 因为不能重复包含头文件, 所以我们可以使用前置声明.

第三步:

#pragma once

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include"Contact.h"

typedef peoInfo DataType;

typedef struct SeqList
{
	DataType* arr;
	int size;
	int capacity;
}SL;

更改SeqList.h 头文件中的DataType类型, 使其存储的每一个元素为通讯录, 并且包含通讯录的头文件, 这里可以直接使用 typedef peoInfo SeqList 直接修改名字, 就是因为已经包含了通讯录的头文件

第四步:

实现通讯录的各种方法

现在通讯录Contact.h 文件中声明方法, 接着在Contact.c文件中进行实现

Contact.h文件


//通讯录的初始化
void ContactInit(Contact* con);
//通讯录的销毁
void ContactDestory(Contact* con);

//通讯录的插入
void ContactAdd(Contact* con);
//通讯录的删除
void ContactDel(Contact* con);

//展示通讯录
void ContactShow(Contact* con);

//通讯录的修改
void ContactModify(Contact* con);
//通讯录查找
void ContactFind(Contact* con);

以上就是我们需要完成的所以函数的声明

Contact.c文件

#include"SeqList.h"
#include"Contact.h"
void ContactInit(Contact* con) 
{
	SLInit(con);//这里其实就是顺序表的初始化
}

void ContactDestory(Contact* con)
{
	SLDestory(con);//这里也是顺序表
}

void ContactAdd(Contact* con)
{
	peoInfo info;
	printf("请输入姓名\n");
	scanf("%s", info.name);
	printf("请输入性别\n");
	scanf("%s", info.gender);
	printf("请输入年龄\n");
	scanf("%d",&info.age);
	printf("请输入电话\n");
	scanf("%s", info.tel);
	printf("请输入地址\n");
	scanf("%s", info.address);
	SLPushBack(con,info);//还是使用顺序表的方法
}

int findByName(Contact* con,char name[])//根据姓名进行函数的实现
{
	for (int i = 0; i < con->size; i++)
	{
		if (0 == strcmp(con->arr[i].name, name))
		{
			return i;
		}
	}
	return -1;
}


void ContactDel(Contact* con)
{
	char name[MAX_NAME];
	printf("请输入要删除的联系人姓名\n");
	scanf("%s", name);
	int find = findByName(con, name);
	if (find < 0)
	{
		printf("要删除的联系人不存在\n");
		return;
	}
	SLErase(con, find);//还是顺序表
	printf("删除成功\n");
}

void ContactShow(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->arr[i].name,
			con->arr[i].gender,
			con->arr[i].age,
			con->arr[i].tel,
			con->arr[i].address);
	}
}

void ContactModify(Contact* con)
{
	char name[MAX_NAME];
	printf("请输入要修改的用户姓名\n");
	scanf("%s", name);

	int find = findByName(con, name);
	if (find < 0)
	{
		printf("要修改的联系人不存在\n");
	}
	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].address);

	printf("修改成功\n");
}

void ContactFind(Contact* con)
{
	char name[MAX_NAME];
	printf("请输入要查找的姓名\n");
	scanf("%s", name);
	int find = findByName(con, name);
	if (find < 0)
	{
		printf("要查找的联系人不存在\n");
		return;
	}

	printf("%-5s %-5s %-5s %-5s %-5s\n", "姓名", "性别", "年龄", "电话", "地址");
	for (int i = 0; i < con->size; i++)
	{
		printf("%-5s %-5s %-5d %-5s %-5s\n",
			con->arr[find].name,
			con->arr[find].gender,
			con->arr[find].age,
			con->arr[find].tel,
			con->arr[find].address);
	}
}

以上为实习功能的Contact.c文件,其中我们需要包含SeqList.h文件 , 因为要使用到顺序表的方法, 并且包含Contact.h文件, 需要使用里面的声明的结构体. 代码解释请看注释, 如有其他疑惑, 欢迎评论区或者私信留言!!

三. 代码汇总

SeqList.h

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include"Contact.h"

typedef peoInfo DataType;

typedef struct SeqList
{
	DataType* arr;
	int size;
	int capacity;
}SL;

void SLInit(SL* sp);
void SLDestory(SL* sp);

//判空
void SLCheckcapacity(SL* sp);

//打印
void SLPrint(SL sp);

//尾插
void SLPushBack(SL* sp, DataType x);
//头插
void SLPushFront(SL* sp, DataType x);

//尾删
void SLPopBack(SL* sp);
//头删
void SLPopFront(SL* sp);

//在指定位置前插入元素
void SLInsert(SL* sp,int pos,DataType x);
//删除指定位置的元素
void SLErase(SL* sp, int pos);
//查找元素所在位置
int SLFind(SL* sp, DataType x);

SeqList.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"

//初始化
void SLInit(SL* sp)
{
	assert(sp);
	sp->arr = NULL;
	sp->capacity = sp->size = 0;
}

//销毁
void SLDestory(SL* sp)
{
	assert(sp);
	if (sp->arr)
	{
		free(sp->arr);
	}
	sp->arr = NULL;
	sp->capacity = sp->size = 0;
}

//打印
//void SLPrint(SL sp)
//{
//	for (int i = 0; i < sp.size; i++)
//	{
//		printf("%d ", sp.arr[i]);
//	}
//	printf("\n");
//}

//判空
void SLCheckcapacity(SL* sp)
{
	if (sp->size == sp->capacity)
	{
		int Newcapacity = sp->capacity == 0 ? 2 : sp->capacity * 2;
		DataType* tmp = (DataType*)realloc(sp->arr, Newcapacity * sizeof(DataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
		}
		sp->arr = tmp;
		tmp = NULL;
		sp->capacity = Newcapacity;
	}
}

//尾插
void SLPushBack(SL* sp, DataType x)
{
	assert(sp);
	SLCheckcapacity(sp);
	sp->arr[sp->size++] = x;
}

//头插
void SLPushFront(SL* sp, DataType x)
{
	assert(sp);
	SLCheckcapacity(sp);
	for (int i = sp->size; i>0; i--)
	{
		sp->arr[i] = sp->arr[i - 1];//最后一次arr[1] = arr[0]
	}
	sp->arr[0] = x;
	sp->size++;
}

//尾删
void SLPopBack(SL* sp)
{
	assert(sp);
	sp->size--;
}

//头删
void SLPopFront(SL* sp)
{
	assert(sp);
	for (int i = 0; i<sp->size-1; i++)
	{
		sp->arr[i] = sp->arr[i + 1]; //最后一次arr[size-2] = arr[size-1]
	}
	sp->size--;
}

void SLInsert(SL* sp, int pos, DataType x)
{
	assert(sp);
	assert(pos >= 0 && pos <= sp->size);
	SLCheckcapacity(sp);
	for (int i = sp->size; i>pos; i--)
	{
		sp->arr[i] = sp->arr[i - 1];//最后一次arr[pos+1] = arr[pos]
	}
	sp->arr[pos] = x;
	sp->size++;
}

void SLErase(SL* sp, int pos)
{
	assert(sp);
	assert(pos >= 0 && pos < sp->size);
	for (int i = pos; i<sp->size-1; i++)
	{
		sp->arr[i] = sp->arr[i + 1];//最后一次arr[size-2] = arr[size-1] 
	}
	sp->size--;
}

//int SLFind(SL* sp, DataType x)
//{
//	assert(sp);
//	for (int i = 0; i < sp->size; i++)
//	{
//		if (x == sp->arr[i])
//		{
//			return i;
//		}
//	}
//	return -1;
//}

Contact.h

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#define MAX_NAME 20
#define MAX_GENDER 10
#define MAX_TEL 10
#define MAX_ADDRESS 100


typedef struct personInfo
{
	char name[MAX_NAME];
	char gender[MAX_GENDER];
	int age;
	char tel[MAX_TEL];
	char address[MAX_ADDRESS];
}peoInfo;


typedef struct SeqList Contact;//需要先前置声明,才能改名字

//通讯录的初始化
void ContactInit(Contact* con);
//通讯录的销毁
void ContactDestory(Contact* con);

//通讯录的插入
void ContactAdd(Contact* con);
//通讯录的删除
void ContactDel(Contact* con);

//展示通讯录
void ContactShow(Contact* con);

//通讯录的修改
void ContactModify(Contact* con);
//通讯录查找
void ContactFind(Contact* con);

Contact.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
#include"Contact.h"
void ContactInit(Contact* con) 
{
	SLInit(con);
}

void ContactDestory(Contact* con)
{
	SLDestory(con);
}

void ContactAdd(Contact* con)
{
	peoInfo info;
	printf("请输入姓名\n");
	scanf("%s", info.name);
	printf("请输入性别\n");
	scanf("%s", info.gender);
	printf("请输入年龄\n");
	scanf("%d",&info.age);
	printf("请输入电话\n");
	scanf("%s", info.tel);
	printf("请输入地址\n");
	scanf("%s", info.address);
	SLPushBack(con,info);
}

int findByName(Contact* con,char name[])
{
	for (int i = 0; i < con->size; i++)
	{
		if (0 == strcmp(con->arr[i].name, name))
		{
			return i;
		}
	}
	return -1;
}


void ContactDel(Contact* con)
{
	char name[MAX_NAME];
	printf("请输入要删除的联系人姓名\n");
	scanf("%s", name);
	int find = findByName(con, name);
	if (find < 0)
	{
		printf("要删除的联系人不存在\n");
		return;
	}
	SLErase(con, find);
	printf("删除成功\n");
}

void ContactShow(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->arr[i].name,
			con->arr[i].gender,
			con->arr[i].age,
			con->arr[i].tel,
			con->arr[i].address);
	}
}

void ContactModify(Contact* con)
{
	char name[MAX_NAME];
	printf("请输入要修改的用户姓名\n");
	scanf("%s", name);

	int find = findByName(con, name);
	if (find < 0)
	{
		printf("要修改的联系人不存在\n");
	}
	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].address);

	printf("修改成功\n");
}

void ContactFind(Contact* con)
{
	char name[MAX_NAME];
	printf("请输入要查找的姓名\n");
	scanf("%s", name);
	int find = findByName(con, name);
	if (find < 0)
	{
		printf("要查找的联系人不存在\n");
		return;
	}

	printf("%-5s %-5s %-5s %-5s %-5s\n", "姓名", "性别", "年龄", "电话", "地址");
	for (int i = 0; i < con->size; i++)
	{
		printf("%-5s %-5s %-5d %-5s %-5s\n",
			con->arr[find].name,
			con->arr[find].gender,
			con->arr[find].age,
			con->arr[find].tel,
			con->arr[find].address);
	}
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"

//void test1(SL* ps)
//{
//	SLPushBack(ps, 10);
//	SLPushBack(ps, 20);
//	SLPushBack(ps, 30);
//	SLPrint(*ps);
//	SLPushFront(ps, 40);
//	SLPushFront(ps, 50);
//	SLPrint(*ps);
//	SLPopBack(ps);
//	SLPopBack(ps);
//	SLPrint(*ps);
//	SLPopFront(ps);
//	SLPrint(*ps);
//	SLInsert(ps, 0, 99);
//	SLPrint(*ps);
//	SLInsert(ps, ps->size, 100);
//	SLPrint(*ps);
//	SLInsert(ps, 2, 50);
//	SLPrint(*ps);
//	SLErase(ps, 0);
//	SLPrint(*ps);
//	SLErase(ps, ps->size - 1);
//	SLPrint(*ps);
//	printf("%d\n", SLFind(ps, 50));
//	
//}

//int main()
//{
//	SL s;
//	SLInit(&s);
//	test1(&s);
//	SLDestory(&s);
//	return 0;
//}

//void Contest1()
//{
//	Contact con;
//	ContactInit(&con);
//	ContactAdd(&con);
//	ContactAdd(&con);
//	ContactShow(&con);
//
//	ContactDel(&con);
//	ContactShow(&con);
//
//	ContactDestory(&con);
//}

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

int main()
{
	//Contest1();

	int op = -1;
	Contact con;
	ContactInit(&con);
	
	do{
		meun();
		printf("请选择\n");
		scanf("%d", &op);

		switch (op)
		{
			case 1:
				ContactAdd(&con);
				break;
			case 2:
				ContactDel(&con);
				break;
			case 3:
				ContactModify(&con);
				break;
			case 4:
				ContactFind(&con);
				break;
			case 5:
				ContactShow(&con);
				break;
			case 0:
				printf("退出通讯录......\n");
				break;
			default:
				printf("输入错误,请重新输入\n");
				break;
		}

	} while (op != 0);

	ContactDestory(&con);
	return 0;
}

四. 效果展示

界面:

在这里插入图片描述

增加联系人并且查看

在这里插入图片描述
删除联系人并且查看
在这里插入图片描述

修改查找

在这里插入图片描述

在这里插入图片描述

总结

只要掌握了顺序表的实现方法, 通讯录就是在顺序表的基础上套个壳子, 结合文件操作我们也可以把数据存储起来.


  • 49
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

酷酷学!!!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值