【初阶数据结构】通讯录项目(可用作课程设计)

概述

通讯录项目是基于顺序表这个数据结构来实现的。如果说数组是苍蝇小馆,顺序表是米其林的话,那么通讯录就是国宴。

换句话说,通讯录就是顺序表中存储结构体数据的。

那我在这里就给出所有的代码,具体细节这里就不再多说了,代码中都有注释。需要的可以自己复制粘贴。
哈哈

1. 通讯录的效果

添加数据
展示数据

修改数据
查找
删除数据
退出
至于功能6大家可以执行测试。

下面,我将分文件展示每个文件的所有代码,有需要的读者可以自行的拷贝。

文件

2. SeqList.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include"Contact.h"

typedef PeoInfo SLDataType;

typedef struct SeqList
{
	SLDataType* arr;
	int size; //有效的数据个数
	int capacity; //空间大小
}SL;

//打印顺序表中的数据
void SLPrint(SL s);

//顺序表的初始化
void SLInit(SL* ps);

//顺序表的销毁
void SLDestory(SL* ps);

//尾插
void SLPushBack(SL* ps, SLDataType x);

//头插
void SLPushFront(SL* ps, SLDataType x);

//尾删
void SLPopBack(SL* ps);

//头删
void SLPopFront(SL* ps);

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

//删除指定位置的数据
void SLErase(SL* ps ,int pos);

//找到指定位置的数据
int SLFind(SL* ps, SLDataType x);

3. Contact.h

#include<string.h>

typedef struct PersonInfo
{
	char name[NAME_MAX]; //姓名
	char gender[GENDER_MAX]; //性别
	int age; //年龄
	char tel[TEL_MAX]; //电话
	char addr[ADDR_MAX]; //住址
}PeoInfo;

//核心:要用到顺序表的相关的方法,对通讯录的操作实际上就是对顺序表的操作
// 为了方便后面的操作,我们给顺序表起个别名为contact
//前置声明
//typedef SL contact;//这样写看似没有什么问题,但是你并编译之后就会发现一堆的报错
//原因在于,此操作为前置声明,就是在还未定义该结构之前,但是我要提前使用该声明就可以使用。
//适用场景为:多文件编写,头文件之间包含关系。
typedef struct SeqList contact;

//初始化通讯录
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);
//保存通讯录数据到文件中
void SaveContact(contact* con);

4. SeqList.c

#define _CRT_SECURE_NO_WARNINGS	
#include"SeqList.h"

void SLInit(SL* ps)
{
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

void SLDestory(SL* ps)
{
	if (ps->arr) //相当于ps->arr != NULL
	{
		free(ps->arr);
	}

	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

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

void SLCheckCapacity(SL* ps)
{
	if (ps->capacity == ps->size)
	{
		//空间不够用,扩容
		SL* tmp = NULL;
		int newscapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		tmp = (SL*)realloc(ps->arr, newscapacity * sizeof(SLDataType));

		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(EXIT_FAILURE);
		}

		//扩容成功
		ps->arr = tmp;
		ps->capacity = newscapacity;
	}
}

void SLPushBack(SL* ps, SLDataType x)
{
	assert(ps);
	//在这之前得先判断,可用空间与有效数据个数之间的关系
	SLCheckCapacity(ps);

	ps->arr[ps->size++] = x;
}


void SLPushFront(SL* ps, SLDataType x)
{
	assert(ps);

	SLCheckCapacity(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 SLPopBack(SL* ps)
{
	assert(ps);
	assert(ps -> arr);

	//这里通过ps->size的关系就可以直接控制,不再访问这个数据,也就是删除了
	ps->size--;
}


void SLPopFront(SL* ps)
{
	assert(ps);
	assert(ps->arr);

	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);

	SLCheckCapacity(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(ps->arr);

	int i = 0;
	for (i = pos; i < ps->size - 1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}

	ps->size--;
}

5. Contact.c

#define _CRT_SECURE_NO_WARNINGS	
#include"SeqList.h"
#include"Contact.h"

void InitContact(contact* con)
{
	SLInit(con);
}

void AddContact(contact* con) //尾插
{
	assert(con);
	PeoInfo pefo;

	printf("请输入姓名:\n");
	scanf("%s",pefo.name);

	printf("请输入性别:\n");
	scanf("%s", pefo.gender);

	printf("请输入年龄:\n");
	scanf("%d", &pefo.age);

	printf("请输入电话:\n");
	scanf("%s", pefo.tel);

	printf("请输入住址:\n");
	scanf("%s", pefo.addr);

	//复用顺序表的方法
	SLPushBack(con,pefo);
	printf("数据已经成功添加!\n");
}

int Find(contact* con,PeoInfo pefo)
{
	int i = 0;
	for (i = 0; i < con->size; i++)
	{
		if (!strcmp(con->arr[i].tel, pefo.tel))
		{
			return i;
		}
	}

	return -1;
}

void DelContact(contact* con)
{
	assert(con);
	PeoInfo pefo;
	printf("请输入想要删除联系人的电话:\n");
	scanf("%s",pefo.tel);

	int find = Find(con, pefo);

	if (find < 0)
	{
		//没有找到
		printf("要删除的数据已经不存在\n");
		return;
	}

	//找到了
	SLErase(con,find);
	printf("数据已经删除\n");
}


void ShowContact(contact* con)
{
	printf("姓名\t性别\t年龄\t电话\t住址\n");

	for (int i = 0; i < con->size; i++)
	{
		printf("%s\t", con->arr[i].name); //姓名

		printf("%s\t", con->arr[i].gender); //性别

		printf("%d\t", con->arr[i].age); //年龄

		printf("%s\t", con->arr[i].tel); //电话

		printf("%s\t", con->arr[i].addr); //住址

		printf("\n");
	}

}


void FindContact(contact* con)
{
	PeoInfo pefo;
	printf("请输入要查找通讯人的电话:\n");
	scanf("%s",pefo.tel);

	int find = Find(con, pefo);

	if (find < 0)
	{
		printf("要查找的联系人数据不存在\n");
		return;
	}
	//找到了
	printf("姓名\t性别\t年龄\t电话\t住址\n");

	printf("%s\t", con->arr[find].name); //姓名

	printf("%s\t", con->arr[find].gender); //性别

	printf("%d\t", con->arr[find].age); //年龄

	printf("%s\t", con->arr[find].tel); //电话

	printf("%s\t", con->arr[find].addr); //住址

	printf("\n");
	
}


void ModifyContact(contact* con)
{
	assert(con);
	PeoInfo pefo;
	printf("请输入要修改联系人的姓名:\n");
	scanf("%s",pefo.name);

	int i = 0;
	for (i = 0; i < con->size; i++)
	{
		if (!strcmp(con->arr[i].name, pefo.name))
		{
			//匹配
			printf("请输入姓名:\n");
			scanf("%s", con->arr[i].name);

			printf("请输入性别:\n");
			scanf("%s", con->arr[i].gender);

			printf("请输入年龄:\n");
			scanf("%d", &con->arr[i].age);

			printf("请输入电话:\n");
			scanf("%s", con->arr[i].tel);

			printf("请输入住址:\n");
			scanf("%s", con->arr[i].addr);

			break;
		}

	}

	if (i == con->size)
	{
		printf("被修改的数据不存在\n");
	}
	
}


void DestroyContact(contact* con)
{
	assert(con);
	SLDestory(&con);
}


void SaveContact(contact* con)
{
	assert(con);
	int i = 0;
	//打开文件
	FILE* fp = fopen("contact.txt","w");
	if (fp == NULL)
	{
		perror("fopen fail");
		exit(1);
	}

	//写文件
	fprintf(fp,"姓名\t性别\t年龄\t电话\t住址\n");
	for (i = 0; i < con->size; i++)
	{
		fprintf(fp,"%s\t%s\t%d\t%s\t%s\n",
									con->arr[i].name,
									con->arr[i].gender, 
									con->arr[i].age, 
									con->arr[i].tel, 
									con->arr[i].addr );
	}

	printf("数据已经安全存储\n");
	//关闭文件
	fclose(fp);
	fp = NULL;
}

6. test.c

#include"SeqList.h"
void meun()
{
	printf("*********************************************\n");
	printf("****************   通讯录   *****************\n");
	printf("******* 1.添加联系人   2.删除联系人 *********\n");
	printf("******* 3.修改联系人   4.查找联系人 *********\n");
	printf("******* 5.展示通讯录   6.保存数据   *********\n");
	printf("*******           0.退出            *********\n");
	printf("*********************************************\n");
	

}

int main()
{
	int input = 0;
	contact con;
	InitContact(&con);
	do 
	{
		meun();

		printf("请输入你的操作:\n");
		scanf("%d", &input);

		switch (input)
		{
		case 1:
			AddContact(&con);
			break;
		case 2:
			DelContact(&con);
			break;
		case 3:
			ModifyContact(&con);
			break;
		case 4:
			FindContact(&con);
			break;
		case 5:
			ShowContact(&con);
			break;
		case 6:
			SaveContact(&con);
			break;
		case 0:
			printf("程序已安全退出!\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);


	return 0;
}

以上就是本次通讯录的全部代码了,如果又不理解的地方,可以在评论区提问。

最后,觉得本文写的不错的话,别忘了给偶点赞哦!
哈哈

  • 19
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值