暴力数据结构之使用顺序表实现通讯录

1.代码展示

1.1 test.c
#define _CRT_SECURE_NO_WARNINGS
#include"SeqList.h"
#include"Contact.h"


void TsetContact01()
{
	Contact con;
	ContactInit(&con);
	ContactAdd(&con);
	ContactDestroy(&con);
}

void menu()
{
	printf("*************通 讯 录*************\n");
	printf("********1.添加   2.删除***********\n");
	printf("********3.修改   4.展示***********\n");
	printf("********5.查找   0.退出***********\n");
	printf("**********************************\n");
}
int main()
{
	//SLTest01();
	//SLTest02();
	//TsetContact01();
	Contact con;
	ContactInit(&con);
	int op = -1;
	do {
		menu();
		printf("请选择您的操作:");
		scanf("%d", &op);

		switch(op)
		{
		case 1:
			ContactAdd(&con);
			break;
		case 2:
			ContactDel(&con);
			break;
		case 3:
			ContactModify(&con);
			break;
		case 4:
			ContactShow(&con);
			break;
		case 5:
			ContactFind(&con);
			break;
		case 0:
			printf("退出通讯录!\n");
			exit(0);
			break;
		default:
			printf("请输入正确的数字:\n");
			break;
		}
	} while (op != 0);

	ContactDestroy(&con);
	return 0;
}
1.2 Contact.c
#include"Contact.h"
#include"SeqList.h"



//通讯录的初始化
void ContactInit(Contact* con)
{
	SLInit(con);
}

//销毁
void ContactDestroy(Contact* con)
{
	SLDestroy(&con);
}

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


//添加
void ContactAdd(Contact* con)
{
	peoInfo info;

	printf("请输入联系人的姓名:");
	scanf("%s", info.name);

	printf("请输入联系人的性别:");
	scanf("%s", info.gender);

	printf("请输入联系人的年龄:");
	scanf("%d", &info.age);

	printf("请输入联系人的电话:");
	scanf("%s", info.tel);

	printf("请输入联系人的住址:");
	scanf("%s", info.add);

	//插入数据

	SeqListPushBack(con, info);

}

//删除
void ContactDel(Contact* con)
{
	char name[NAME_MAX];
	printf("请输入要删除的联系人:");
	scanf("%s", name);

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

//展示
void ContactShow(Contact* con)
{
	printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");
	for (int i = 0; i < con->size; i++)
	{
		printf("%3s %4s %4d %4s %4s\n",
			con->arr[i].name,
			con->arr[i].gender,
			con->arr[i].age,
			con->arr[i].tel,
			con->arr[i].add
		);
	}
}

//修改
void ContactModify(Contact* con) 
{
	char name[NAME_MAX];
	printf("请输入要修改的联系人:");
	scanf("%s", name);

	int find = FindByname(con, name);
	if (find < 0)
	{
		printf("要修改的联系人不存在!\n");
		return;
	}
	printf("请输入新的联系人名:");
	scanf("%s", con->arr[find].name);

	printf("请输入新的联系人性别:");
	scanf("%s", con->arr[find].gender);

	printf("请输入新的联系年龄:");
	scanf("%d", con->arr[find].age);

	printf("请输入新的联系电话:");
	scanf("%s", con->arr[find].tel);

	printf("请输入新的联系住址:");
	scanf("%s", con->arr[find].add);

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



//查找
void ContactFind(Contact* con)
{
	char name[NAME_MAX];
	printf("请输入要查找的联系人:");
	scanf("%s", name);

	int find = FindByname(&con, name);
	if (find < 0)
	{
		printf("要查找的联系人不存在!\n");
		return;
	}

	printf("请输入新的联系人名:");
	scanf("%s", con->arr[find].name);

	printf("请输入新的联系人性别:");
	scanf("%s", con->arr[find].gender);

	printf("请输入新的联系年龄:");
	scanf("%d", con->arr[find].age);

	printf("请输入新的联系电话:");
	scanf("%s", con->arr[find].tel);

	printf("请输入新的联系住址:");
	scanf("%s", con->arr[find].add);
}
1.3 Contact.h
#define _CRT_SECURE_NO_WARNINGS
#pragma once

#define NAME_MAX 20
#define GENDER_MAX 20
#define TEL_MAX 20
#define ADD_MAX 100

typedef struct personInfo
{

	char name[NAME_MAX];
	char gender[GENDER_MAX];
	int age;
	char tel[TEL_MAX];
	char add[ADD_MAX];

}peoInfo;


typedef struct SeqList Contact;

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

//销毁
void ContactDestroy(Contact* con);

//添加
void ContactAdd(Contact* con);

//删除
void ContactDel(Contact* con);

//修改
void ContactModify(Contact* con);

//查找
void ContactFind(Contact* con);

//展示
void ContactShow(Contact* con);
1.4 SeqList.c
#include"SeqList.h"
void SLInit(SL *ps)
{
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

//顺序表的销毁
void SLDestroy(SL *ps)
{
	if (ps->arr) //等价于if(ps->arr != NULL)
	{
		free(ps->arr);
	}
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

//判断函数
void SLCheckCapacity(SL *ps)
{
	//插入前判断空间是否充足
	if (ps->size == ps->capacity)
	{
		//申请空间
		//三目表达式
		int NewCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		SLDataType* tmp = (SLDataType*)realloc(ps->arr, NewCapacity * sizeof(SLDataType));
		//申请内存空间
		if (tmp == NULL)
		{
			perror("realloc failed");
			exit(1);//空间申请失败,直接退出程序
		}
		//空间申请成功
		ps->arr = tmp;
		ps->capacity = NewCapacity;
	}
}


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


//尾插函数
void SeqListPushBack(SL* ps, SLDataType x)
{
	assert(ps);
	SLCheckCapacity(ps);
	ps->arr[ps->size++] = x;
}

//头插函数
void SeqListPushFront(SL* ps, SLDataType x)
{
	assert(ps);
	SLCheckCapacity(ps);
	//首先将顺序表现有数字后移一位
	for (int i = ps->size; i > 0; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[0] = x;
	ps->size++;
}

//尾删函数
void SeqListPopBack(SL* ps)
{
	assert(ps);
	assert(ps->size);
	--ps->size;
}


//头删函数
void SeqListPopFront(SL* ps)
{
	assert(ps);
	assert(ps->size);

	for (int 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);
	//在指定位置之前插入数据
	//判断空间大小,不够增容
	SLCheckCapacity(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--;
}

//顺序表查找
//void SLFind(SL* ps, SLDataType x)
//{
//	assert(ps);
//	for (int i = 0; i < ps->size; i++)
//	{
//		if (ps->arr[i] == x)
//		{
//			return i;
//		}
//	}
//	//没有找到
//	return -1;
//}
1.5 SeqList.h
#define _CRT_SECURE_NO_WARNINGS
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include"Contact.h"

//#define  N 100
静态顺序表
//struct SeqList
//{
//	int arr[N];
//	int size;
//};

//typedef int SLDataType;
typedef peoInfo SLDataType;

//动态顺序表
struct SeqList
{
	SLDataType *arr;
	int size;      //有效数据个数
	int capacity;  //空间大小
};

typedef struct SeqList SL;

//增删查改等接口函数
void SLInit(SL *ps);

//尾插函数
void SeqListPushBack(SL* ps, SLDataType x);
//头插函数
void SeqListPushFront(SL* ps, SLDataType x);
//尾删函数
void SeqListPopBack(SL* ps);
//头删函数
void SeqListPopFront(SL* ps);

//打印函数
void SLPrint(SL s);
//销毁函数
void SLDestroy(SL* ps);

//指定位置插入函数
void SLInsert(SL* ps, int pos, SLDataType x);
//删除指定位置数据
void SLErase(SL* ps, int pos);
//顺序表查找
void SLFind(SL* ps, SLDataType x);


2.模块详解

2.1 test.c

 该源文件只用来做菜单等测试用例的测试,运行后的界面如图所示


2.2 通讯录的初始化

 

//通讯录的初始化
void ContactInit(Contact* con)
{
	SLInit(con);
}
void SLInit(SL *ps)
{
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

初始化实质上就是将第一个数组置为 NULL 空指针,将其余变量初始化为 0 


2.3 销毁
//销毁
void ContactDestroy(Contact* con)
{
	SLDestroy(&con);
}
//顺序表的销毁
void SLDestroy(SL *ps)
{
	if (ps->arr) //等价于if(ps->arr != NULL)
	{
		free(ps->arr);
	}
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

销毁就是首先判断是否为空,若不为空则释放当前的空间,然后进行初始化 


2.4 添加
//添加
void ContactAdd(Contact* con)
{
	peoInfo info;

	printf("请输入联系人的姓名:");
	scanf("%s", info.name);

	printf("请输入联系人的性别:");
	scanf("%s", info.gender);

	printf("请输入联系人的年龄:");
	scanf("%d", &info.age);

	printf("请输入联系人的电话:");
	scanf("%s", info.tel);

	printf("请输入联系人的住址:");
	scanf("%s", info.add);

	//插入数据

	SeqListPushBack(con, info);

}
//判断函数
void SLCheckCapacity(SL *ps)
{
	//插入前判断空间是否充足
	if (ps->size == ps->capacity)
	{
		//申请空间
		//三目表达式
		int NewCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		SLDataType* tmp = (SLDataType*)realloc(ps->arr, NewCapacity * sizeof(SLDataType));
		//申请内存空间
		if (tmp == NULL)
		{
			perror("realloc failed");
			exit(1);//空间申请失败,直接退出程序
		}
		//空间申请成功
		ps->arr = tmp;
		ps->capacity = NewCapacity;
	}
}


//尾插函数
void SeqListPushBack(SL* ps, SLDataType x)
{
	assert(ps);
	SLCheckCapacity(ps);
	ps->arr[ps->size++] = x;
}

我们这里用到的是尾插,即判断是否满足插入条件,满足则直接插入数据,反之报错,用断言assert来做限制。 


2.5 修改
//修改
void ContactModify(Contact* con) 
{
	char name[NAME_MAX];
	printf("请输入要修改的联系人:");
	scanf("%s", name);

	int find = FindByname(con, name);
	if (find < 0)
	{
		printf("要修改的联系人不存在!\n");
		return;
	}
	printf("请输入新的联系人名:");
	scanf("%s", con->arr[find].name);

	printf("请输入新的联系人性别:");
	scanf("%s", con->arr[find].gender);

	printf("请输入新的联系年龄:");
	scanf("%d", con->arr[find].age);

	printf("请输入新的联系电话:");
	scanf("%s", con->arr[find].tel);

	printf("请输入新的联系住址:");
	scanf("%s", con->arr[find].add);

	printf("修改成功!\n");
}
int FindByname(Contact * con,char name[])
{
	for(int i = 0; i < con->size; i++)
	{
		if (strcmp(con->arr[i].name, name))
		{
			return i;
		}
	}
	return -1;
}

这里先使用 FindByName 函数判断所查联系人是否存在,若存在则返回 i,反之返回 -1。然后将返回值作为修改条件成立与否的判断,之后就可以进行数据的修改。 


2.6 删除
//删除
void ContactDel(Contact* con)
{
	char name[NAME_MAX];
	printf("请输入要删除的联系人:");
	scanf("%s", name);

	int find = FindByname(con, name);
	if (find < 0)
	{
		printf("要删除的联系人不存在!");
		return;
	}
	SLErase(con, find);
	printf("删除成功!\n");
}
//删除指定位置数据
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--;
}

 先通过 FindByName 函数判断数据是否存在,随即使用 SLErase 删除函数删除数据,底层逻辑是判断所删除数据是否在数组的头尾之间,若在那么直接将下一个数据覆盖到当前位置,即完成一个删除动作。


2.7 展示 
//展示
void ContactShow(Contact* con)
{
	printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");
	for (int i = 0; i < con->size; i++)
	{
		printf("%3s %4s %4d %4s %4s\n",
			con->arr[i].name,
			con->arr[i].gender,
			con->arr[i].age,
			con->arr[i].tel,
			con->arr[i].add
		);
	}
}

 展示就是把数组中存储的数据依次打印出来即可。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值