首页 > 其他分享 >通讯录----顺序表版本

通讯录----顺序表版本

时间:2024-04-07 20:58:28浏览次数:10  
标签:ps arr void 联系人 ---- 通讯录 版本 printf con

1.通讯录的实现逻辑

对于通讯录,我们做的无非就是初始化,销毁。添加联系人数据,修改联系人数据,删除联系人数据,查找联系人数据,展示联系人数据;

这个不就和我们的顺序表的逻辑如出一辙吗,顺序表实现的功能不就是数据的初始化,修改,删除(头删和尾删),添加(头插和尾插),顺序表的打印,这些我们是可以直接进行使用的;

我们的顺序表是整形的数据的删除,插入等等,那么我们的通讯录不是对整形数据进行相关的操作了,而是对联系人的信息进行相应的操作,我们把联系人及其相关的信息放到一个结构体里面,我们联系人的信息包括姓名性别年龄,电话以及地址这5项信息;

2.通讯录实现

(1)一些前期的准备

我们要在顺序表的基础上进行相应的操作,所以我们的解决方案在原来的seqlist.c---seqlist.h----test.c这三个基础上加上contact.c---contact.h这两个表示的是通讯录的源文件和头文件;

我们在通讯录的同文件里面定义结构体以及相关的函数的声明:

这里我们使用宏定义结构体里面数组(名字性别电话),方便我们对数组的大小进行相应的修改;

我们同时要把顺序表的头文件里面的int修改为我们联系人对应的结构体类型的数据,这个时候要包含通讯录对应的头文件;

通讯录的头文件要使用应该是对于顺序表进行初始化(实际上是对通讯录进行初始化),我们对顺序表进行初始化contactinit(sl* sl1),这个里面的sl就是我们的顺序表重定义之后的名字,sl1是形参,但是我们明明是要对通讯录进行初始化,参数确是顺序表这让人很难理解,我们于是写作contactinit(contact* con)这样就会很直观,但是两个头文件之间不能重复的包含,我们进行前置声明重定义:

因为我们的顺序表头文件里面的数据类型不是int ,我们的测试文件插入数据应该注释掉;顺序表的源文件里面打印整形数据,查找整形数据应该也注释掉,否则会报错

(2)通讯录的初始化和销毁

(3)添加联系人数据

我们定义一个结构体类型的变量:info把添加的信息写入到对应的成员里面去;

最后我们调用尾插函数插入到通讯录里面(也可以是头插函数);

(4)删除联系人数据

我们首先要判断删除的联系人是否存在,存在才能删除,不存在无法进行相应的操作;

我们后续进修改联系人数据的时候,也要进行判断我们想要修改的联系人是否存在,我们可以根据姓名进行判断是否存在,这个时候我们行定义一个函数fingbyname,因为是输入的联系人姓名和我们的通讯录里面的联系人姓名这两个字符串进行比较看是否相同,我们需要遍历整个通讯录,使用strcmp函数将我们输入的姓名和通讯录里面的姓名,进行比较,存在就返回0,不存在函数就返回-1;

我们最后是调用顺序表里面的slerase函数实现在指定的位置进行删除的操作,我们要传入通讯录和指定位置的下标;

(5)修改联系人数据

和删除的逻辑一样,先进行判断修改的联系人是否存在,调用findbyname函数根据返回值进行判断,最后输入新的联系人的相关的信息;

(6)查找联系人数据

和删除的逻辑一样,先进行判断查找的联系人是否存在,调用findbyname函数根据返回值进行判断,最后输出新的联系人的相关的信息;我们不使用展示是因为展示的是全部的,查找的时候只会展示我们想要查找的联系人的相关的信息,这个和展示的代码基本相同,只需要把数组对应的下标修改为我们的findbyname函数的返回值了;

(7)展示联系人数据

先打印表头栏目,在把我们的联系人的信息对应表头打印出来;

(8)项目的完善

作为一个项目,我们不能停留在测试功能上面,我们打印菜单栏,让用户可以自己选择相应的的功能进行实现,我们把所有的可以实现的功能放在菜单栏里面供用户进行选择:

我们的函数都已经实现了,所以设置switch循环的时候,直接调用就可以了;

3.完整代码

(1)seqlist.h

#pragma once
#include"contact.h"
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef perinfo sldatatype;

typedef struct seqlist
{
	sldatatype* arr;
	int size;
	int capacity;
}sl;

//顺序表的初始化
void slinit(sl* ps);

//顺序表的销毁
void sldestory(sl* ps);

//顺序表的尾部插入数据
void slpushback(sl* ps, sldatatype x);

//顺序表的数组元素的打印
void slprint(sl s);

//顺序表的头部插入数据
void slpushfront(sl* ps, sldatatype x);

//顺序表的尾删
void slpopback(sl* ps);

//顺序表的头删
void slpopfront(sl* ps);

//顺序表的打印
void slprint(sl s);

//顺序表的指定插入
void slinsert(sl* ps, int pos, sldatatype x);

//顺序表的指定删除
void slerase(sl* ps, int pos);

//顺序表的数据的查找
int slfind(sl* ps, sldatatype x);

(2)seqlist.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"seqlist.h"
void check(sl* ps)
{
	if (ps->size == ps->capacity)
	{
		//我们插入数据,需要增大空间,动态内存开辟空间
		int newcapacity = ps->arr == 0 ? 4 : 2 * ps->capacity;
		sldatatype* temp = realloc(ps->arr, newcapacity * 2 * sizeof(sldatatype));
		if (temp == NULL)
		{
			perror("realloc");
			exit(1);//直接退出,不再继续执行
		}
		ps->arr = temp;
		ps->capacity = newcapacity;
	}
}
//顺序表的初始化
void slinit(sl* ps)
{
	ps->arr = NULL;
	ps->size = 0;
	ps->capacity = 0;
}
//顺序表的销毁
void sldestory(sl* ps)
{
	if (ps->arr != NULL)
	{
		free(ps->arr);
	}
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}
//顺序表的尾部插入数据
void slpushback(sl* ps, sldatatype x)
{
	//对传进来的指针进行断言
	assert(ps);
	//判断数组大小和空间的容量是否相同
	check(ps);
	ps->arr[ps->size] = x;
	ps->size++;
}
//顺序表的头部插入数据
void slpushfront(sl* ps, sldatatype x)
{
	assert(ps);
	check(ps);
	for (int i = ps->size; i > 0; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[0] = x;
	ps->size++;
}
//顺序表的打印
//void slprint(sl s)
//{
//	for (int i = 0; i < s.size; i++)
//	{
//		printf("%d ", s.arr[i]);
//	}
//	printf("\n");
//}
//顺序表的尾删
void slpopback(sl* ps)
{
	assert(ps);
	assert(ps->size);//如果我们顺序表本来就没有数据,我们进行减减就会变为-1了,显然不对,进行断言
	ps->size--;//渐渐就减少了范围,直接把最后的元素删除,就相当于最后一个元素不属于顺序表了
}
//顺序表的头删
void slpopfront(sl* ps)
{
	assert(ps);
	assert(ps->size);
	for (int i = 0; i < ps->size - 1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];//最后是arr[size-2]=arr[size-1];
	}
	ps->size--;
}

//顺序表的指定位置之前插入
void slinsert(sl* ps, int pos, sldatatype x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	check(ps);
	for (int 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);
	for (int i = pos; i < ps->size-1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}

//顺序表的数据的查找
//int slfind(sl* ps, sldatatype x)
//{
//	assert(ps);
//	for (int i = 0; i < ps->size; i++)
//	{
//		//找到了
//		if (ps->arr[i] == x)
//		{
//			return i;
//		}
//	}
//	//没有找到
//	return -1;//无效的下标
//}

(3)contact.h

#pragma once
#define name_max 20
#define gender_max 10
#define tel_max 20
#define addr_max 20
typedef struct personinfo
{
	char name[name_max];
	char gender[gender_max];
	int age;
	char tel[tel_max];
	char addr[addr_max];
}perinfo;

typedef struct seqlist contact;
//通讯录初始化
void contactinit(contact* con);
//通讯录销毁
void contactdestory(contact* con);
//通讯录添加联系人数据
void contactadd(contact* con);
//通讯录删除联系人数据
void contactdel(contact* con);
//通讯录修改联系人数据
void contactmodify(contact* con);
//通讯录查找联系人数据
void contactfind(contact* con);
//通讯录展示联系人数据
void contactshow(contact* con);

(4)contact.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"
#include"seqlist.h"
void contactinit(contact* con)
{
	slinit(con);
}

void contactdestory(contact* con)
{
	sldestory(con);
}

void contactadd(contact* con)
{
	perinfo 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.addr);

	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[name_max];
	printf("请输入要删除的联系人的姓名:\n");
	scanf("%s", name);

	int find = findbyname(con, name);
	if (find < 0)
	{
		printf("要删除的联系人的数据不存在\n");
		return;
	}
	//删除的联系人的数据存在
	slerase(con, find);
	printf("删除成功 !\n");
}

void contactmodify(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("查找成功\n");

	printf("%s  %s  %s  %s  %s\n", "姓名", "性别", "年龄", "电话", "地址");
	for (int i = 0; i < con->size; i++)
	{
		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)
{
	printf("%s  %s  %s  %s  %s\n", "姓名", "性别", "年龄", "电话", "地址");
	for (int 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);
	}
}

(5)test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"seqlist.h"
//void sltest01()
//{
//	sl sl1;
//
//	//顺序表的初始化
//	slinit(&sl1);
//
//	//顺序表的尾部插入数据
//	slpushback(&sl1, 8);
//	slpushback(&sl1, 9);
//	slpushback(&sl1, 10);
//	slpushback(&sl1, 11);
//
//	//尾部插入之后打印
//	slprint(sl1);
//
//	//顺序表的头部插入数据
//	slpushfront(&sl1, 5);
//	slpushfront(&sl1, 6);
//
//	//头部插入之后打印
//	slprint(sl1);
//
//	//顺序表的尾删
//	slpopback(&sl1);
//	slprint(sl1);
//
//	//顺序表的头删
//	slpopfront(&sl1);
//	slprint(sl1);
//
//	//顺序表的指定位置之前插入
//	slinsert(&sl1, 1, 0);
//	slprint(sl1);
//
//	//顺序表的指定删除
//	slerase(&sl1, 1);
//	slprint(sl1);
//
//	//顺序表的数据的查找
//	int ret = slfind(&sl1, 100);
//	if (ret < 0)
//	{
//		printf("没有找到\n");
//	}
//	else
//	{
//		printf("找到了,下标是%d\n", ret);
//	}
//	//顺序表的销毁
//	sldestory(&sl1);
//}

//void contacttest01()
//{
//	contact con;
//	contactinit(&con);
//
//	contactadd(&con);
//	contactadd(&con);
//	contactshow(&con);
//
//	contactdel(&con);
//	contactshow(&con);
//
//	contactmodify(&con);
//	contactshow(&con);
//
//	contactfind(&con);
//
//
//	contactdestory(&con);
//}

void menu()
{
	printf("*************通讯录*************\n");
	printf("*****1、添加用户 2、删除用户****\n");
	printf("*****3、修改用户 4、查找用户****\n");
	printf("*****5. 展示用户 0.退出通讯录***\n");
	printf("********************************\n");
}
int main()
{
	//顺序表的功能测试函数
	//sltest01();
	/*contacttest01();*/
	int input = -1;
	contact con;
	contactinit(&con);
	do
	{
		menu();
		printf("请选择");
		scanf("%d", &input);
		switch (input)
		{
		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 (input);
	contactdestory(&con);
	return 0;
}

标签:ps,arr,void,联系人,----,通讯录,版本,printf,con
From: https://blog.csdn.net/binhyun/article/details/137460370

相关文章

  • 【Frida】【Android】 07_爬虫之网络通信库HttpURLConnection
    ......
  • TurnOnLamps
    贪心贪心的从下往上,对于当前位,如果这一位是任意的,那么如果它有儿子可以向上,那么当前点选择为翻转是肯定不劣的,而如果没有儿子向上,那么当前点选中一定是不优的然后数向上的儿子个数,每\(2\)个可以合并为\(1\)条路径如果一个点合并后不满足限制,则通过从当前点重新出发一条链来......
  • LittleElephantAndRGB
    计数枚举第一个区间的右端点,第二个区间的左端点,然后记录每个点前面第一个连续的\(lim\)个的位置,这个点往前连续的\(g\)的个数,对称在记录一遍然后直接统计答案,如果两个拼起来一段是可行的考虑前面选的不够,后面去到一整段之后前面和后面拼起来够,等差数列前面足够长否......
  • @SpringbootApplication注解
    @SpringBootConfiguration是一个组合注解,由@ComponentScan、@EnableAutoConfiguration和@SpringBootConfiguration组成@SpringBootConfiguration与普通@Configuration相比,唯一区别是前者要求整个app中只出现一次@ComponentScanexcludeFilters-用来在组件扫描......
  • Python基础篇-Python基础01
    Python基础-day1!!!注意:本系列所写的文章全部是学习笔记,来自于观看视频的笔记记录,防止丢失。观看的视频笔记来自于:哔哩哔哩武沛齐老师的视频:2022Python的web开发(完整版)入门全套教程,零基础入门到项目实战1.文档工具typora2.环境搭建安装Python解释器学习Python语法Python......
  • 进制之间的转换之“十六进制 转 十进制 转 二进制 方案”
    1.十六进制转十进制十六进制数为:0X1A6F根据16进制数要转十进制得到公式:F*160+6*161+A*162 +1*163 十六机制数:0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F也就是常数:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15转为常数:15 *160 +6*161 +10*162 +1*163 计......
  • Apr.7.2024小结——汇编中jmp和call的用法
    今天终于跑起来了自己OS的mbr,还是很激动人心的。学习了16位实模式下jmp和call的各种用法,来总结一下:call(near)0xabcd相对近调用后面的地址是相对的-32768~32767call[addr]间接绝对近调用地址为绝对,但是是在某个寄存器或内存中call(far)段基址:偏移直接绝对远调用跨......
  • 2-41. 制作 [SceneName] Attribute 特性
    什么是Attribute像图中SellPercentage是一个float值,为什么它会变成Slider呢?是因为我们在这个属性上面添加了[Range],这个东西就叫做Attribute为什么我们要做Attribute呢?如上图所示,我们这里的StartSceneName是手动输入的,所以有很大可能我们会写错又比方说Tel......
  • 【每周例题】蓝桥杯 C++ 鸡哥的奇特密码
    鸡哥的奇特密码题目鸡哥的奇特密码 题目分析 1.首先,我们需要想到用一个for循环去遍历整个数组,用if寻找出需要我们处理的部分2.如何处理:将重复的L丢出数组,可以运用pop_back()函数3.为了避免越界,我们可以从后往前遍历代码#include<iostream>#include<bits/stdc++.h>u......
  • 软件测试理论(2)自动化测试
    自动化测试什么时候适用自动化测试?1)可重复的、不知疲倦地运动,对于数据能进行精确的大批量的比较的;2)回归测试3)在机械化的执行和比较测试执行的问题1)自动化测试没有有效的利用,使得手工测试太多。2)测试结果的捕获没有系统性,而且没有查看或调查3)缺陷报告必须......