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

文章目录

  • 概述
  • [1. 通讯录的效果](#1. 通讯录的效果)
  • [2. SeqList.h](#2. SeqList.h)
  • [3. Contact.h](#3. Contact.h)
  • [4. SeqList.c](#4. SeqList.c)
  • [5. Contact.c](#5. Contact.c)
  • [6. test.c](#6. test.c)

概述

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

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

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

1. 通讯录的效果





至于功能6大家可以执行测试。

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

2. SeqList.h

c 复制代码
#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

c 复制代码
#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

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

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

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

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

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

相关推荐
考虑考虑1 小时前
Jpa使用union all
java·spring boot·后端
用户3721574261351 小时前
Java 实现 Excel 与 TXT 文本高效互转
java
浮游本尊2 小时前
Java学习第22天 - 云原生与容器化
java
渣哥4 小时前
原来 Java 里线程安全集合有这么多种
java
间彧4 小时前
Spring Boot集成Spring Security完整指南
java
间彧5 小时前
Spring Secutiy基本原理及工作流程
java
Java水解6 小时前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
洛小豆8 小时前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
前端小张同学8 小时前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端
ytadpole8 小时前
Spring Cloud Gateway:一次不规范 URL 引发的路由转发404问题排查
java·后端