利用动态内存开辟技术和文件存储开发一个简易的通讯录

目录

1.test.c

2.contatc.h

3.contact.c

4.总结


简介:学习C也有很长时间了,现在我从刚开始连hello world 都不明白咋打印的那个C小白,到现在已经写了几个项目,刷了几百道题,整理了万字以上的笔记,并能随心的调试写代码的入门小白,这期间经历了很多,但又很少,现在我把我认为是我目前C语言最高成就的项目给大家展示出来————通讯录。


一、test.c

#define _CRT_SECURE_NO_WARNINGS 1
//练习:——完成
//通讯录——VS项目——Contact(通讯录)
//
//需求:
//1.能够存放1000个人的信息
//信息包含:年龄、名字、性别、电话、地址、电子邮件、职业
//2.增加联系人
//3.删除联系人
//4.修改联系人信息
//5.查找联系人信息
//6.排序通讯录的信息
// 7.显示打印信息
// 8.退出程序
//
//实现思路:
//contact.h——类型的定义,函数的声明
//contact.c——函数的实现
//test.c——测试模块
#include "contact.h"

void menu()
{
	printf("*****************************************\n");
	printf("*********    通讯录管理系统    **********\n");
	printf("*****************************************\n");
	printf("*******          0.exit           *******\n");
	printf("*******   1.add          2.del    *******\n");
	printf("*******   3.search       4.revise *******\n");
	printf("*******   5.sort         6.print  *******\n");
	printf("*******   7.cls          8.del all  *****\n");
	printf("*****************************************\n");
	printf("*****************************************\n");
}

enum op
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	REVISE,
	SORT,
	PRINT,
	CLS,
	DELALL
};

//在栈上开辟的空间太大了,动态内存开辟学完之后记得转移到堆上面

//已改造——动态增长

//学习完文件之后记得把数据存储到数据库或文件中
//已修改

int main()
{
	int input = 0;
	//创建通讯录
	Contact con;
	//初始化通讯录——加载文件
	//将使用动态内存开辟技术进行初始化
	Initcontact(&con);
	do
	{
		menu();
		printf("请选择:\n");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			//添加联系人
			ADD_PEOPLE(&con);//修改,增容
			break;
		case DEL:
			//删除联系人
			bekghDEL_PEOPLE(&con);
			break;
		case SEARCH:
			//查找联系人
			SEARCH_PEOPLE(&con);
			break;
		case REVISE:
			//修改联系人
			REVISE_PEOPLE(&con);
			break;
		case SORT:
			//排序联系人
			SORT_PEOPLE(&con);
			break;
		case PRINT:
			//打印联系人
			PRINT_PEOPLE(&con);
			break;
		case EXIT:
			//保存信息到文件
			Save_Contct(&con);
			//销毁通讯录
			Destory_Contact(&con);
			//退出程序
			printf("退出程序\n");//修改,动态释放
			break;
		case CLS:
			//清屏
			system("cls");
			break;
		case DELALL:
			//删除所有联系人
			DEL_Contact(&con);
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}

	} while (input);
	return 0;
}

二、contact.h

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
//包含的头文件
#include <string.h>		
#include <stdio.h>
#include <stdlib.h>

//类型的定义
// 
//定义联系人信息
//#define MAX_NUM 1000//静态
#define MAX_NAME 20
#define	MAX_SEX 10
#define	MAX_AGE 10
#define	MAX_NUMBER 12
#define	MAX_ADDR 30
#define MAX_SZ 3//起始最大容量
#define DEFAULT_SZ 2//默认增长容量



typedef struct contact_informationn
{
	char name[MAX_NAME];
	char sex[MAX_SEX];
	int age[MAX_AGE];
	char number[MAX_NUMBER];
	char addr[MAX_ADDR];
}contact_informationn;

//静态版本
//typedef struct Contact
//{
//	contact_informationn data[MAX_NUM];//存放联系人信息
//	int sz;//记录通讯录的有效联系人个数
//}Contact;

//动态版本
typedef struct Contact
{
	contact_informationn* data;//指向动态申请的空间,用来存放联系人信息
	int sz;//记录通讯录的有效联系人个数
	int capacity;//记录当前通讯录的最大容量
}Contact;

//函数的声明
//
//初始化通讯录
void Initcontact(Contact* pc);

//添加联系人
void ADD_PEOPLE(Contact* pc);

//打印联系人
void PRINT_PEOPLE(const Contact* pc);

//删除联系人
void bekghDEL_PEOPLE(Contact* pc);

//查找联系人
void SEARCH_PEOPLE(const Contact* pc);

//修改联系人
void REVISE_PEOPLE(Contact* pc);

//排序联系人
void SORT_PEOPLE(const Contact* pc);

//销毁通讯录
void Destory_Contact(Contact* pc);

//保存信息到文件
void Save_Contct(Contact* pc);

//加载文件
void Load_Contact(Contact* pc);

//考虑增容问题
void cheak_contact(Contact* pc);

//删除所有联系人
void DEL_Contact(Contact* pc);

三、contact.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
int count = 0;//存储联系人个数
初始化通讯录——静态版本
//void Initcontact(Contact* pc)
//{
//	pc->sz = 0;
//	memset(pc->data, 0, sizeof(pc->data));
//}

//加载文件
void Load_Contact(Contact* pc)
{
	//打开文件
	FILE* p = fopen("Contact.txt", "r");
	if (p == NULL)
	{
		perror("Load_Contact");
		return;
	}
	//读文件
	contact_informationn tmp = { 0 };
	while (fread(&tmp, sizeof(contact_informationn), 1,p ))
	{
		//判断是否需要增容
		cheak_contact(pc);
		pc->data[pc->sz] = tmp;
		pc->sz++;
		count++;
	}
	//关闭文件
	fclose(p);
	p = NULL;
}

//初始化通讯录——动态版本
void Initcontact(Contact* pc)
{
	pc->data = (contact_informationn*)malloc(DEFAULT_SZ * sizeof(contact_informationn));
	if (pc->data == NULL)
	{
		perror("Initcontact");
		return;
	}
	pc->sz = 0;//初始化后默认为0
	pc->capacity = DEFAULT_SZ;

	//加载文件
	Load_Contact(pc);
}

//静态版本
//添加联系人
//void ADD_PEOPLE(Contact* pc)
//{
//	//判断通讯录是否存满
//	if (pc->sz == MAX_NUM)
//	{
//		printf("通讯录已满,添加失败\n");
//		return;
//	}
//
//	//增加一个联系人
//	printf("请输入姓名\n");
//	scanf("%s", pc->data[pc->sz].name);
//	printf("请年龄\n");
//	scanf("%s", &(pc->data[pc->sz].age));
//	printf("请输入性别\n");
//	scanf("%s", pc->data[pc->sz].sex);
//	printf("请输入手机号码\n");
//	scanf("%s", pc->data[pc->sz].number);
//	printf("请输入住址\n");
//	scanf	("%s", pc->data[pc->sz].addr);
//
//	pc->sz++;
//	printf("添加成功\n");
//}

void cheak_contact(Contact* pc)
{
	//判断通讯录是否存满
	if (pc->sz == pc->capacity)
	{
		//增容
		contact_informationn* ptr = (contact_informationn*)realloc(pc->data, (pc->capacity + DEFAULT_SZ) * sizeof(contact_informationn));
		if (ptr == NULL)
		{
			//增容失败
			perror("ADD_PEOPLE");
			printf("增加联系人失败\n");
			return;
		}
		else
		{
			//增容成功
			pc->data = ptr;
			pc->capacity += DEFAULT_SZ;
			printf("增容成功\n");//方便观察动态内存是否进行自增容
		}
	}
}

//动态版本
void ADD_PEOPLE(Contact* pc)
{
	cheak_contact(pc);

	//增加一个联系人
	printf("请输入姓名\n");
	scanf("%s", pc->data[pc->sz].name);
	printf("请年龄\n");
	scanf("%s", &(pc->data[pc->sz].age));
	printf("请输入性别\n");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入手机号码\n");
	scanf("%s", pc->data[pc->sz].number);
	printf("请输入住址\n");
	scanf("%s", pc->data[pc->sz].addr);

	pc->sz++;
	printf("添加成功\n");
	count++;
}

//打印联系人
void PRINT_PEOPLE(const Contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通讯录为空\n");
	}
	//打印人数
	printf("联系人个数:%d\n", count);
	//打印标题
	printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\n", "名字", "年龄", "性别", "电话", "地址");

	//打印数据
	for (int i = 0; i < pc->sz; i++)
	{
		printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\n", 
			   pc->data[i].name,
			   pc->data[i].age,
			   pc->data[i].sex,
		       pc->data[i].number, 
		       pc->data[i].addr);

	}
}

//通过姓名查找
static int Find_By_Name(Contact* pc, char name[])
{
	for (int i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			//找到了
			return i;
		}
	}
	//找不到
	return -1;
}

//删除联系人
void bekghDEL_PEOPLE(Contact* pc)
{
	//判断通讯录联系人数量是否为空
	if (pc->sz == 0)
	{
		printf("通讯录已空,无需删除\n");
		return;
	}
	char name[MAX_NAME];
	printf("请输入要删除的联系人的姓名\n");
	scanf("%s", name);
	//查找该联系人是否有要删除的联系人
	int pos = Find_By_Name(pc,name);
	//没有——停止操作
	if (pos == -1)
	{
		printf("通讯录没有该联系人,请核实后在进行该操作\n");
		return;
	}

	//有——删除
	for (int i = pos; i < pc->sz - 1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	count--;
	printf("删除成功\n");
}

//查找联系人
void SEARCH_PEOPLE(const Contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通讯录已空,无需查找\n");
		return;
	}
	char name[MAX_NAME];
	printf("请输入要查找的联系人的姓名\n");
	scanf("%s", name);
	//查找该联系人是否有要查找的联系人
	int pos = Find_By_Name(pc, name);
	//没有——停止操作
	if (pos == -1)
	{
		printf("通讯录没有该联系人,请核实后在进行该操作\n");
		return;
	}

	//有
	else
	{
	printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\n", "名字", "年龄", "性别", "电话", "地址");

	printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\n",
		pc->data[pos].name,
		pc->data[pos].age,
		pc->data[pos].sex,
		pc->data[pos].number,
		pc->data[pos].addr);

	}
}

//修改联系人
void REVISE_PEOPLE(Contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通讯录已空,无需修改\n");
		return;
	}
	char name[MAX_NAME];
	printf("请输入要修改的联系人的姓名\n");
	scanf("%s", name);
	//查找该联系人是否有要修改的联系人
	int pos = Find_By_Name(pc, name);
	//没有——停止操作
	if (pos == -1)
	{
		printf("通讯录没有该联系人,请核实后在进行该操作\n");
		return;
	}

	//有
	else
	{
		//修改一个联系人
		printf("请输入姓名\n");
		scanf("%s", pc->data[pos].name);
		printf("请年龄\n");
		scanf("%s", &(pc->data[pos].age));
		printf("请输入性别\n");
		scanf("%s", pc->data[pos].sex);
		printf("请输入手机号码\n");
		scanf("%s", pc->data[pos].number);
		printf("请输入住址\n");
		scanf("%s", pc->data[pos].addr);
		printf("修改成功\n");
	}
}

//排序联系人_未完成

//void Menu()
//{
//	printf("*****************************************\n");
//	printf("****** 1. name           2. age    *******\n");
//	printf("*****************************************\n");
//}
//
//int char_cmp(const void* p1, const void* p2)
//{
//	return strcmp(((contact_informationn*)p1)->name, ((contact_informationn *)p2)->name);
//}
//int int_cmp(const void* p1, const void* p2)
//{
//	return ((contact_informationn*)p1)->age - (( contact_informationn*)p2)->age;
//}
//
//void SORT_PEOPLE(const Contact* pc)
//{
//
//		int input;
//		do
//		{
//			Menu();
//			printf("请输入按照什么要求排序:>");
//			scanf("%d", &input);
//			switch (input)
//			{
//			case 1:
//				//qsort(pc->data->name, pc->size, sizeof(struct PeoInfo), char_cmp);
//				qsort(pc->data, pc->sz, sizeof(contact_informationn), char_cmp);//进行排序
//				printf("成功按照姓名进行排序~!\n");
//				input = 0;
//				break;
//			case 2:
//				qsort(pc->data, pc->sz, sizeof(contact_informationn), int_cmp);//进行排序
//				printf("成功按照年龄进行排序~!\n");
//				input = 0;
//				break;
//			default:
//				printf("输入错误,请重新输入~!\n");
//				break;
//			}
//		} while (input);
//	}

//排序——已完成
int compar1(const void* a, const void* b)
{
	return strcmp(((contact_informationn*)a)->name, ((contact_informationn*)b)->name);
}

int compar2(const void* a, const void* b)
{
	return ((contact_informationn*)b)->age - ((contact_informationn*)a)->age;
		
}

void SORT_PEOPLE(Contact* pc)
{
	int input = 0;
	do
	{
		printf("请选择要排序的类型:\n");
		printf("1.名字大小排序   2.年龄大小排序   0.退出排序\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			qsort(pc->data, pc->sz, sizeof(contact_informationn), compar1);
			printf("名字大小排序成功\n");
			break;
		case 2:
			qsort(pc->data, pc->sz, sizeof(contact_informationn), compar2);
			printf("年龄大小排序成功\n");
			break;
		case 0:
			printf("退出排序\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}
		break;
	} while (input);
}



//销毁通讯录
void Destory_Contact(Contact* pc)
{
	free(pc->data);
	pc->data = NULL;
	pc->sz = 0;
	pc->capacity = 0;
	printf("信息已保存\n");//便于测试
}

//保存信息到文件
void Save_Contct(Contact* pc)
{
	//打开文件
	FILE* p = fopen("Contact.txt", "w");
	if (p == NULL)
	{
		perror("Save_Contct");
		return;
	}
	//写文件
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		fwrite(pc->data + i, sizeof(contact_informationn), 1, p);
	}
	//关闭文件
	fclose(p);
	p = NULL;
}

//删除所有联系人
void DEL_Contact(Contact* pc)
{
	//参照单个删除但无需查找姓名,增加警示询问。
	//判断通讯录联系人数量是否为空
	if (pc->sz == 0)
	{
		printf("通讯录已空,无需删除\n");
		return;
	}
	//警示
	int tmp = 0;
	printf("确定要清空所有联系人吗?\n");
	printf("1.yes   2.no\n");
	scanf("%d", &tmp);
	if (tmp == 1)
	{
		//删除
		pc->data = 0;
		pc->sz = 0;
		printf("删除成功\n");
		count = 0;
	}
	else
	{
		printf("已撤销删除\n");
	}
}

四、总结

其实这个小项目让我做了一天才搞出来,归根结底还是太菜了,但我想说的是咱并不会效率低就放弃编程的兴趣,我坚信有努力不一定会有收获,但不努力一定不会有收获,加油奥利给!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
在Linux系统下,可以通过以下步骤为CSV文件开辟动态内存: 1. 使用C语言中的文件操作函数打开CSV文件。 2. 使用C语言中的内存分配函数(如malloc)为CSV文件数据结构分配内存。 3. 读取CSV文件中的数据,并将其存储在动态分配的内存中。 4. 对动态分配的内存进行处理,如排序、查找、修改等操作。 5. 使用C语言中的内存释放函数(如free)释放动态分配的内存。 以下是一个示例代码,用于演示如何为CSV文件开辟动态内存: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_ROWS 1000 #define MAX_COLS 100 typedef struct { int num_rows; int num_cols; char **data; } CsvFile; CsvFile *read_csv_file(const char *filename) { CsvFile *csv_file = (CsvFile *) malloc(sizeof(CsvFile)); if (csv_file == NULL) { return NULL; } csv_file->num_rows = 0; csv_file->num_cols = 0; csv_file->data = (char **) malloc(MAX_ROWS * sizeof(char *)); if (csv_file->data == NULL) { free(csv_file); return NULL; } FILE *fp = fopen(filename, "r"); if (fp == NULL) { free(csv_file->data); free(csv_file); return NULL; } char line[MAX_COLS * 10]; while (fgets(line, sizeof(line), fp) != NULL) { char *ptr = strtok(line, ","); int col_idx = 0; while (ptr != NULL) { if (csv_file->num_cols < col_idx + 1) { csv_file->num_cols = col_idx + 1; } if (csv_file->num_rows == 0) { csv_file->data[col_idx] = (char *) malloc(MAX_ROWS * sizeof(char)); if (csv_file->data[col_idx] == NULL) { free_csv_file(csv_file); return NULL; } } if (col_idx >= csv_file->num_cols || csv_file->num_rows >= MAX_ROWS) { free_csv_file(csv_file); return NULL; } csv_file->data[col_idx][csv_file->num_rows] = *ptr; ptr = strtok(NULL, ","); col_idx++; } csv_file->num_rows++; } fclose(fp); return csv_file; } void free_csv_file(CsvFile *csv_file) { if (csv_file != NULL) { if (csv_file->data != NULL) { for (int i = 0; i < csv_file->num_cols; i++) { free(csv_file->data[i]); } free(csv_file->data); } free(csv_file); } } int main() { CsvFile *csv_file = read_csv_file("example.csv"); if (csv_file != NULL) { // process csv_file free_csv_file(csv_file); } return 0; } ``` 在上述代码中,read_csv_file函数从指定的CSV文件中读取数据,并将其存储在动态分配的内存中。CsvFile结构体定义了CSV文件的数据结构,包括行数、列数和数据。free_csv_file函数用于释放动态分配的内存。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

微风拂尘~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值