C语言顺序表-文件操作-通讯录

k简易通讯录管理系统:C语言实现及代码详解-CSDN博客
数据结构:顺序表-CSDN博客

请先看这两个博客再看下面顺序表-通讯录

导言

通讯录主要用于集中保存和方便查找联系人的各种信息,如电话号码、邮箱地址等。它可以帮助我们快速找到并联系到想要找的人,同时支持信息分类、同步更新和一些便捷功能,极大提升了沟通效率和个人信息管理能力。

比如你要有结构的存储一个人的信息,这个时候通讯录就来了,通讯录一般有一些(增,删,查,改,排序等)。

代码(注释)

这里回套用顺序表来写这个通讯录,期间有些代码需要做改动,因为我们需要进行文件操作,这样才能保存我们通讯录的这么一个信息

接下来请看代码吧

顺序表部分
text.h头文件
#pragma once
// 头文件引用
#include<stdio.h> // 标准输入输出库
#include<stdlib.h> // 提供动态内存分配、随机数等函数
#include<assert.h> // 断言库,用于程序调试时进行条件检查
#include<string.h> // 字符串操作函数库
#include<vld.h> // Visual Leak Detector库,用于检测C/C++程序中的内存泄漏(Visual Studio环境下)
#include"Contacts.h" // 自定义的Contacts头文件

// 重复包含防止
#include<vld.h>

// 定义数据类型别名:将PeoInfo类型重命名为SLDataType
typedef PeoInfo SLDataType;

// 定义顺序表(线性表)结构体
typedef struct SeqList
{
    SLDataType* arr; // 这里直接变成结构体指针
    int size; // 记录当前顺序表的有效元素个数
    int capacity; // 记录顺序表当前可用的最大容量(即数组大小)
} SL;

// 函数声明

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

// 在顺序表头部插入元素
void Headinsertion(SL* ps, SLDataType x);

// 在顺序表尾部插入元素
void Tailinsertion(SL* ps, SLDataType x);

// 删除顺序表头部元素
void Headerremoval(SL* ps);

// 删除顺序表尾部元素
void Tailremoval(SL* ps);

// 在指定位置前插入元素
void SLInsert(SL* ps, int pos, SLDataType x);

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

// 查找数据(返回数据在顺序表中的索引位置,若不存在则返回特定值)
int SLFind(SL* ps, SLDataType x);

// 输出顺序表内容的函数
void Printff(SL* ps);

// 销毁顺序表占用的内存空间
void SLDestroy(SL* ps);
fun.c函数实现文件
#define _CRT_SECURE_NO_WARNINGS 1
#include"text.h"
#include"Contacts.h"
//扩容内存函数
void Expansion(SL *ps) {
	assert(ps);
	if (ps->size == ps->capacity)
	{
		//这边用三目运算来判断
		int now_capacity = ps->capacity == 0 ? 4 : ps->capacity*2;
		SLDataType* tmp = realloc(ps->arr, now_capacity * sizeof(SLDataType));
		if (tmp == NULL)
		{
			assert(tmp);
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = now_capacity;
	}
}

///*--顺序表初始化--*/
//void SLInit(SL* ps) {
//	
//	ps->arr = NULL;
//	ps->size = ps->capacity = 0;//连续赋值
//	//等价于
//	//ps->size = 0; ps->capacity = 0;
//}


/*文件操作需要提前申请一块空间,避免导入的时候没空间了*/
void SLInit(SL* ps) {
	ps->arr = (SLDataType*)malloc(10 * sizeof(SLDataType));
	if (ps->arr == NULL) {
		perror("SLInit failed");
		exit(EXIT_FAILURE);
	}	
	ps->size = 0;
	ps->capacity = 10 * sizeof(SLDataType);
}


/*--头部插入--*/
void Headinsertion(SL* ps, SLDataType x) {
	assert(ps);
	Expansion(ps);
	for (int i = ps->size++; i > 0; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[0] = x;//将要插入的值赋值在第一个元素
}

/*--尾部插入--*/
void Tailinsertion(SL* ps, SLDataType x) {
	assert(ps);
	Expansion(ps);
	ps->arr[ps->size++] = x;

}

/*--头部删除--*/
void Headerremoval(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 Tailremoval(SL* ps) {
	assert(ps);
	assert(ps->size);
	ps->size--;//这边直接通过下标(区间)来删除最后一个元素
}

void SLInsert(SL* ps, int pos, SLDataType x) {
	assert(ps);
	//在插入之前判断一下空间大小
	Expansion(ps);
	for (int i = ps->size; i > pos; i--)//从最后一个位置依次往后移动i位
	{
		ps->arr[i] = ps->arr[i-1];
	}
	ps->size++;
	ps->arr[pos] = x;
}

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);
//	assert(x >= 0);
//	for (int i = 0; i < ps->size; i++)
//	{
//		if (ps->arr[i] == x)
//		{
//			return i;
//		}
//	
//	}
//	return -1;
//}

void SLDestroy(SL* ps){
/*--内存销毁--*/
	free(ps->arr);
	ps->arr = NULL;
	ps->capacity = ps->size = 0;
	
}

/*输出函数*/
//void Printff(SL* ps) {
//	int count = 0;
//	for (int i = 0; i < ps->size; i++)
//	{
//		//count++;
//		printf("%d ", ps->arr[i]);
//	
//	}
//	printf("\n%d ", ps->size);//确定size的位置在元素后面
//}
顺序表部分
Contacts.h头文件
#pragma once
enum MyEnum
{
	EXIT,
	ADD,//增加
	DEL,//删除
	FIND,//查找
	MOD,//修改
	SHOW,//展示
	SORT,//排序
	SAVE,//保存
};

#define NAME_MAX 10
#define SEX_MAX 5

#define ADDR_MAX 20
typedef struct Contacts
{
	char name[NAME_MAX];//姓名
	char sex[SEX_MAX];//性别
	int age;//年龄
	int phone;//电话
	char addr[ADDR_MAX];//地址
}PeoInfo;

typedef struct SeqList contact;//区分顺序表和通讯录



//初始化
void Contacts_Init(contact* con);
//增加
void Contacts_add(contact* con);
//删除
void Contacts_del(contact* con);
//查找
void Contacts_find(contact* con);
//修改
void Contacts_mod(contact* con);
//展示
void Contacts_show(contact* con);
//排序
void Contacts_sort(contact* con);
//保存
void Contacts_save(contact* con);
//销毁
void Contacts_Destroy1con(contact* con);
Contacts.c功能实现
#define _CRT_SECURE_NO_WARNINGS 1
#include"text.h"
#include"Contacts.h"
//读取文件
 // 修正后的 Read_file 函数
void Read_file(const contact* con) {
	
	FILE* pf = fopen("contacts.txt", "rb"); // 以二进制读取
	
	if (pf == NULL) {
		perror("fopen");
		return; // 这里直接 return 让程序提前停止
	}

	PeoInfo a1;

	while (fread(&a1, sizeof(PeoInfo), 1, pf)) {

		Tailinsertion(con, a1); // 读取一个完整 PeoInfo 结构体后头部插入一个
	}

	printf("历史数据导入成功!\n");

}

//初始化
void Contacts_Init(contact* con) {
	SLInit(con);
	if (con->arr == NULL) { /* 检查是否初始化成功 */
		perror("SLInit failed");
		exit(EXIT_FAILURE);
	}
	Read_file(con);
}
//添加
void Contacts_add(contact* con) {
	PeoInfo a1;
	printf("请输入姓名>"); scanf("%s", a1.name); printf("\n");
	printf("请输入性别>"); scanf("%s", a1.sex); printf("\n");
	printf("请输入年龄>"); scanf("%d", &a1.age); printf("\n");
	printf("请输入电话>"); scanf("%d", &a1.phone); printf("\n");
	printf("请输入地址>"); scanf("%s", a1.addr); printf("\n");
	Tailinsertion(con, a1);
	printf("插入成功\n");
}
//查找下标的函数
static int Find_sub(contact* con,char arr[]) {
	for (int i = 0; i < con->size; i++)
	{
		if (strcmp(con->arr[i].name, arr) == 0) {
			return i;
		}
	}
	return -1;
}

//删除
void fun_1(contact* con) {
	char name[NAME_MAX];
	printf("请输入你要删除联系人的姓名:\n");
	scanf("%s", name);
	int find = Find_sub(con,name);
	if (find < 0)
	{
		printf("没有此人\n");
		return;
	}
	SLErase(con,find);
	printf("删除成功\n");
}
void eumn2() {
	printf("#############################\n");
	printf("####1.name  2.sex  3.age ####\n");
	printf("####4.phone 5.addr 0.exit####\n");
	printf("#############################\n");
	
}
void Contacts_del(contact* con) {
	int input = 0;
	do
	{
		eumn2();
		printf("请输入你要通过什么查找>\n");
		scanf("%d", &input);
		
		switch (input)
		{
			case 1:
				fun_1(con);
				break;
			case 0:
				break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);;

}

//查找
void Contacts_find(contact* con) {
	
	char arr[NAME_MAX];
	printf("请输入你要查找的姓名\n");
	scanf("%s", arr);
	int find = Find_sub(con,arr);
	if (find < 0)
	{
		printf("没有此人\n");
		return;
	}
	printf("查找成功!\n");
	printf("%s\t%s\t%d\t%d\t%s\n",
		con->arr[find].name,
		con->arr[find].sex,
		con->arr[find].age,
		con->arr[find].phone,
		con->arr[find].addr
	);
}

//修改
void Contacts_mod(contact* con) {
	char name[NAME_MAX];
	printf("请输入你要修改的人的姓名>"); scanf("%s", name); 
	int find = Find_sub(con, name);
	if (find < 0)
	{
		printf("没有此人\n");
		return;
	}
	printf("请输入姓名>"); scanf("%s", con->arr[find].name); printf("\n");
	printf("请输入性别>"); scanf("%s", con->arr[find].sex); printf("\n");
	printf("请输入年龄>"); scanf("%d", &con->arr[find].age); printf("\n");
	printf("请输入电话>"); scanf("%d", &con->arr[find].phone); printf("\n");
	printf("请输入地址>"); scanf("%s", con->arr[find].addr); printf("\n");
	printf("修改成功\n");
}


//排序
//--1--
int compareMyType_name( const void* a1,const void *a2) {

	return strcmp(((PeoInfo*)a1)->name, ((PeoInfo*)a2)->name);
}
//--2--
void compareMyType_age(void* a1, void* a2) {

	return ((PeoInfo*)a1)->age - ((PeoInfo*)a2)->age;
}
void Contacts_sort(contact* con) {
	printf("请选择排序的方式\n");
	printf("###########################\n");
	printf("## 1.name  2.age  0.exit ##\n");
	printf("###########################\n");
	int input = 0;
	scanf("%d", &input);
	switch (input)
	{
	case 0:
		break;
	case 1:
		qsort(con->arr, con->size, sizeof(con->arr[0]), compareMyType_name);
		break;
	case 2 :
		qsort(con->arr, con->size, sizeof(con->arr[0]), compareMyType_age);
		break;
	default:
		printf("选择错误重新选择\n");
		break;
	}
}


//保存
void Contacts_save(const contact* con) {

	FILE* pf = fopen("contacts.txt","wb");
	if (pf == NULL)
	{
		perror("fopen");
		return;
	}
	//PeoInfo a1;
	//利用循环来写入(二进制)
	for (int i = 0; i < con->size; i++)
	{
		fwrite(con->arr+i, sizeof(PeoInfo), 1, pf);

	}
	printf("保存成功\n");
	//关闭文件
	fclose(pf);
	pf = NULL;
}


//展示
void Contacts_show(contact* con) {
	printf("姓名\t性别\t年龄\t联系电话\t 地址\n");
	for (int i = 0; i < con->size; i++)
	{
		printf("%s\t%s\t%d\t%d\t%s\n",
			con->arr[i].name,
			con->arr[i].sex,
			con->arr[i].age,
			con->arr[i].phone,
			con->arr[i].addr
		);
	}
}
//销毁
void Contacts_Destroy(contact* con) {
	SLDestroy(con);
}
main.c文件
#define _CRT_SECURE_NO_WARNINGS 1
#include "text.h"
#include"Contacts.h"
//菜单
void eumn() {
	printf("****************************\n");
	printf("****1.add  2.DEL  3.FIND****\n");
	printf("****4.MOD  5.SHOW 6.SORT****\n");
	printf("****7.SAVE        0.EXIT****\n");
	printf("****************************\n");
}

int main() {
	contact con;//这是整个通讯录的结构体
	
	int input = -1;
	Contacts_Init(&con);//初始化
	
	do
	{
		eumn();
		printf("请选择您的操作:\n");
		scanf("%d", &input);
		
		switch (input)
		{
		case ADD:
			Contacts_add(&con);
			break;
		case DEL:
			Contacts_del(&con);
			break;
		case FIND:
			Contacts_find(&con);
			break;
		case MOD:
			Contacts_mod(&con);
			break;
		case SHOW:
			Contacts_show(&con);
			break;
		case SORT:
			Contacts_sort(&con);
			break;
		case SAVE:
			Contacts_save(&con);
			break;	
		case EXIT:
			Contacts_Destroy(&con);//退出后直接释放空间
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);
	
	return 0;
}

自己理解

  • 10
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

普通young man

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

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

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

打赏作者

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

抵扣说明:

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

余额充值