当前位置:网站首页>[C] the C language program design, dynamic address book (order)

[C] the C language program design, dynamic address book (order)

2022-08-10 23:41:00 There are gods in the mountains

目录

动态通讯录的实现

一、实验的目的和意义

二、实验内容描述

三、功能描述

四、数据结构

1、三大模块

2、结构设计

3、动态开辟

4、文件操作

 5、主要函数

五、流程图及模块算法

1.Contacct 程序运行流程图

 2、AddContct(增加)函数流程图

 3、DelContct(删除)函数流程图

 4、SearchContct(查找)函数流程图

5、ModifyContct(修改)函数流程图

6、SortContct(排序)函数流程图

六、实验测试结果

七、实验总结

八、源代码

1、DynamicContact.h

2、DynamicContact.c

3、test.c

最后


动态通讯录的实现

一、实验的目的和意义

1、巩固和加深对C语言知识的理解

2、学会使用编译器的各种调试

3、提高解决实际问题的能力

二、实验内容描述

通讯录,是用来存放联系人的信息,它在如今电子信息发展的社会中是不可或缺的.联系人的信息主要包括名字、性别、年龄、地址等.

本次课程设计使用C语言来实现通讯录,正常的通讯录应具备以下主要功能:

增:增加联系人

删:删除联系人

查:查找联系人

改:修改联系人的某项信息

显示:显示通讯录所有联系人的信息

排序:对通讯录中的联系人进行排序

三、功能描述

通讯录的主要功能为增加联系人、删除联系人、查找联系人、修改联系人的信息等等

下面具体描述各功能的作用:

1、增加:可以添加联系人,其信息主要包括名字、性别、年龄、电话、地址

2、删除:输入想要删除联系人的名字进行删除,联系人查找存在且删除后则提示删除成功,联系人查找不存在则提示要删除的联系人不存在,或者通讯录为空则输出通讯录已空,无法删除

3、查找:输入想要查找的联系人的名字,联系人存在则打印出联系人的全部信息,否则提示联系人不存在

4、修改:输入想要修改联系人信息的名字,先对联系人查找,联系人存在则对需要修改的信息进行修改,联系人不存在则显示联系人不存在

5、显示:显示通讯录所有联系人的信息

6、排序:对通讯录中的联系人按名字、年龄进行排序,并且显示排序后通讯录中的联系人

四、数据结构

1、三大模块

通讯录大致分为三大模块,详情如下:

文件名作用
DynamicContact.h通讯录的函数声明、头文件声明及各种声明
DynamicContact.c通讯录函数接口的实现
test.c通讯录函数功能测试

2、结构设计

定义一个结构体 PeoInfo ,结构体包括名字、性别、年龄、电话、地址,另一个结构体 Contact 嵌套着 PeoInfo 这个结构体,用于创建通讯录,类似于顺序表.

typedef struct PeoInfo
{
	char name[NAME_MAX];
	char sex[SEX_MAX];
	int age;
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
}PeoInfo;

typedef struct Contact
{
	PeoInfo* data;//存放联系人的信息
	int count;//通讯录中已经保存的信息个数
	int capacity;//记录通讯录当前的最大容量
}Contact;

3、动态开辟

1、通讯录的联系人可以用数组储存,但是考虑到空间浪费的问题,就要对需要空间的多少进行动态开辟.

比如用数组进行储存,开辟了1000个空间,但实际上只用了10个空间,剩余的空间就会造成很大大的浪费.

但是使用动态开辟空间,需要多大的空间就开辟出多大的空间,对开辟的空间不会造成很大的浪费.

这时候就要动态内存函数,通讯录中使用 malloc 函数和 realloc 函数.

2、

两个内存函数的区别,想了解详细的可以去 C++ 官网查阅.

C++ 官网:cplusplus.com - The C++ Resources Networkhttp://www.cplusplus.com/


4、文件操作

通讯录结束运行后,存储好的联系人的信息也随之销毁了.

我们想要在程序结束运行后,联系人的信息依旧保存,这时候就要运用C语言文件操作相关的知识,在程序结束运行之前把联系人保存在一个文件中,这样联系人的信息就可以存储不被销毁.

Address book data is stored in binary format.

通讯录代码中使用如下两个:

如图:contact.data It is the data retained until the address book exits the program


 5、主要函数

//初始化通讯录
void InitContact(Contact* p);

//销毁通讯录
void DestroyContact(Contact* p);

//添加联系人
void AddContact(Contact* p);

//删除联系人
void DelContact(Contact* p);

//查找联系人
void SearchContact(const Contact* p);

//修改联系人信息
void ModifyContact(Contact* p);

//打印联系人
void PrintContact(const Contact* p);

//排序
void SortContact(const Contact* p);

//保存通讯录的信息到文件
void SaveContact(const Contact* pc);

//加载文件信息到通讯录中
void LoadContact(Contact* p);

五、流程图及模块算法

1.Contacct 程序运行流程图

 2、AddContct(增加)函数流程图

 3、DelContct(删除)函数流程图

 4、SearchContct(查找)函数流程图

5、ModifyContct(修改)函数流程图

6、SortContct(排序)函数流程图

 画流程图使用的工具diagrams.net (draw.io)https://www.draw.io/index.html

六、实验测试结果

声明一点,请输入字符,不要输入中文


1、通讯录代码正常运行

 2、进行添加联系人,正常运行

 3、对联系人进行删除,正常运行

 4、对联系人进行修改,正常运行

 

5、对联系人进行排序,正常运行

七、实验总结

本次课程设计我选择的是设计通讯录管理系统.

总的来说,这次的课程设计使我体会较大的是应用比理论学习难得多,它涉及到各种实际问题,但是也加深了我对知识的理解和运用,也深知只有多写代码、练习等才能写出一个好的程序.


1、

在代码方面,所有代码运行都没有问题,就排序函数无法运行,进行排序程序就会崩掉,进行一个下午的调试才找到代码误

进行排序就崩掉,显示 0xC0000005: 读取位置 xxx时发生访问冲突

看到错误提示,我已经想到指针发生越界了,调试一下午才找到错误,如图

 2、

这次课程设计也是一次很好的对自我检查,让我知道哪一个方面存在不足,对知识的了解还不够深入,对一些学过的知识没有很好的掌握.

3、

在编写代码时需要小心谨慎,否则就会写出很多的 bug.在调试上,这次课程设计加强了我对代码的调试能力.

八、源代码

源代码 gitee 上也有,需要的可以自行查看

链接Code_C语言/DynamicContact/DynamicContact · 枫叶先生/枫叶的code - 码云 - 开源中国 (gitee.com)https://gitee.com/mr-maple-leaf/maple-leaf-code/tree/master/Code_C%E8%AF%AD%E8%A8%80/DynamicContact/DynamicContact


1、DynamicContact.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS //vs 编译器需要,其他编译器不需要,可自行删去

//动态版通讯录

#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <Windows.h>

//类型声明

//PeoInit结构体所用
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
//通讯录初始状态的容量大小
#define DEFAULT_SZ 3

//枚举选项

enum Option //test函数所用的枚举
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SORT,
	PRINT
};

enum Modify //修改联系人所用的枚举
{
	EXIT0,
	NAME,
	SEX,
	AGE,
	TELE,
	ADDR
};

//结构体声明

typedef struct PeoInfo
{
	char name[NAME_MAX];
	char sex[SEX_MAX];
	int age;
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
}PeoInfo;

typedef struct Contact
{
	PeoInfo* data;//存放联系人的信息
	int count;//通讯录中已经保存的信息个数
	int capacity;//记录通讯录当前的最大容量
}Contact;


//函数声明

//初始化通讯录
void InitContact(Contact* p);

//销毁通讯录
void DestroyContact(Contact* p);

//添加联系人
void AddContact(Contact* p);

//删除联系人
void DelContact(Contact* p);

//查找联系人
void SearchContact(const Contact* p);

//修改联系人信息
void ModifyContact(Contact* p);

//打印联系人
void PrintContact(const Contact* p);

//排序
void SortContact(const Contact* p);

//保存通讯录的信息到文件
void SaveContact(const Contact* pc);

//加载文件信息到通讯录中
void LoadContact(Contact* p);

2、DynamicContact.c

#include "DynamicContact.h"

//排序所用菜单
void menu2()
{
	printf("********************************\n");
	printf("******  1.name    2.age   ******\n");
	printf("******  0.exit            ******\n");
	printf("********************************\n");
}
//修改联系人所用的菜单
void menu1()
{
	printf("********************************\n");
	printf("******  1.name    2.sex   ******\n");
	printf("******  3.age     4.tele  ******\n");
	printf("******  5.addr    0.exit  ******\n");
	printf("********************************\n");

}

//检测通讯录容量
void CheckCapacity(Contact* p)
{
	assert(p);
	if (p->capacity == p->count)
	{
		PeoInfo* tmp = (PeoInfo*)realloc(p->data, (p->capacity + 2) * sizeof(PeoInfo));
		if (p->data != NULL)
		{
			p->data = tmp;
		}
		else
		{
			perror("CheckCapacity::realloc");
			return;
		}

		p->capacity += 2;
		printf("增容成功\n");
	}
}

//初始化通讯录
void InitContact(Contact* p)
{
	assert(p);
	p->count = 0;
	p->capacity = DEFAULT_SZ;
	p->data = (PeoInfo*)malloc(p->capacity * sizeof(PeoInfo));

	if (p->data == NULL)
	{
		perror("InitContact::malloc");
		return;
	}

	memset(p->data, 0, p->capacity * sizeof(PeoInfo));//把PeoInit全部初始化为0

	//加载文件信息到通讯录中
	LoadContact(p);
}

//销毁通讯录
void DestroyContact(Contact* p)
{
	free(p->data);
	p->data = NULL;
	p->capacity = 0;
	p->count = 0;

	printf("销毁成功\n");
}

//添加联系人
void AddContact(Contact* p)
{
	//检查容量
	CheckCapacity(p);

	//录入信息
	printf("请输入名字:>");
	scanf("%s", p->data[p->count].name);
	printf("请输入性别:>");
	scanf("%s", p->data[p->count].sex);
	printf("请输入年龄:>");
	scanf("%d", &(p->data[p->count].age));
	printf("请输入电话:>");
	scanf("%s", p->data[p->count].tele);
	printf("请输入地址:>");
	scanf("%s", p->data[p->count].addr);

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

//查找,找到了返回下标,找不到返回 -1
int FindName(const Contact* p, char name[])
{
	assert(p);
	int i = 0;
	for (i = 0; i < p->count; i++)
	{
		if (0 == strcmp(p->data[i].name, name))
		{
			return i;
		}
	}
	return -1;
}

//删除联系人
void DelContact(Contact* p)
{
	assert(p);
	if (0 == p->count)
	{
		printf("通讯录已空,无法删除\n");
		return;
	}
	char name[NAME_MAX];
	printf("请输入要查找的名字:>");
	scanf("%s", name);
	int position = FindName(p, name);//查找
	if (-1 == position)
	{
		printf("要删除的联系人不存在\n\n");
		return;
	}
	//删除
	int i = 0;
	for (i = position; i < p->count - 1; i++)
	{
		p->data[i] = p->data[i + 1];
	}
	p->count--;
	printf("删除成功\n\n");
}

//查找联系人
void SearchContact(const Contact* p)
{
	assert(p);
	char name[NAME_MAX];
	printf("请输入要查找的名字:>");
	scanf("%s", name);
	int position = FindName(p, name);//查找
	if (-1 == position)
	{
		printf("要查找的联系人不存在\n\n");
		return;
	}
	printf("\n-----------------------------------------------\n");
	printf("%-10s %-5s %-5s %-12s %-30s\n", "姓名", "性别", "年龄", "电话", "地址");
	printf("%-10s %-5s %-5d %-12s %-30s\n", p->data[position].name, 
		p->data[position].sex, p->data[position].age, 
		p->data[position].tele, p->data[position].addr);
	printf("\n-----------------------------------------------\n\n");
}

//修改联系人信息
void ModifyContact(Contact* p)
{
	assert(p);
	int intput = 0;
	char name[NAME_MAX];
	printf("请输入要修改联系人的名字:>");
	scanf("%s", name);
	int position = FindName(p, name);//查找
	if (-1 != position)
	{
		printf("\n-----------------------------------------------\n");
		printf("%-10s %-5s %-5s %-12s %-30s\n", "姓名", "性别", "年龄", "电话", "地址");
		printf("%-10s %-5s %-5d %-12s %-30s\n", p->data[position].name, p->data[position].sex,
			p->data[position].age, p->data[position].tele, p->data[position].addr);
		printf("\n-----------------------------------------------\n\n");
		do
		{
			menu1();
			printf("请输入要修改的选项:>");
			scanf("%d", &intput);
			switch (intput)
			{
			case NAME:
				printf("请修改名字:>");
				scanf("%s", p->data[position].name);
				printf("修改成功\n\n");
				break;
			case SEX:
				printf("请修改性别:>");
				scanf("%s", p->data[position].sex);
				printf("修改成功\n\n");
				break;
			case AGE:
				printf("请修改年龄:>");
				scanf("%d", &(p->data[position].age));
				printf("修改成功\n\n");
				break;
			case TELE:
				printf("请修改电话号码:>");
				scanf("%s", p->data[position].tele);
				printf("修改成功\n\n");
				break;
			case ADDR:
				printf("请修改地址:>");
				scanf("%s", p->data[position].addr);
				printf("修改成功\n\n");
				break;
			case EXIT0:
				printf("退出修改\n\n");
				break;
			default:
				printf("选择错误,请重新选择\n\n");
				break;
			}
		} while (intput);
	}
	else
	{
		printf("所要修改的联系人不存在\n\n");
		return;
	}
}

//打印联系人
void PrintContact(const Contact* p)
{
	assert(p);
	int i = 0;
	printf("\n-----------------------------------------------\n");
	printf("%-10s %-5s %-5s %-12s %-30s\n", "姓名", "性别", "年龄", "电话", "地址");
	for (i = 0; i < p->count; i++)
	{
		printf("%-10s %-5s %-5d %-12s %-30s\n", p->data[i].name, p->data[i].sex,
			p->data[i].age, p->data[i].tele, p->data[i].addr);
	}
	printf("-----------------------------------------------\n\n");
}


int cmp_name(const void* e1, const void* e2)
{
	return strcmp(((struct PeoInfo*)e1)->name, ((struct PeoInfo*)e2)->name);
}

int cmp_age(const void* e1, const void* e2)
{
	return (((struct PeoInfo*)e1)->age - ((struct PeoInfo*)e2)->age);
}

//排序
void SortContact(const Contact* p)
{
	assert(p);
	int intput = 0;
	do
	{
		menu2();
		printf("请选择需要排序的选项:>");
		scanf("%d", &intput);
		switch (intput)
		{
		case 1:
			qsort(p->data, p->count, sizeof(struct PeoInfo), cmp_name);
			printf("按名字排序成功\n\n");
			break;
		case 2:
			qsort(p->data, p->count, sizeof(struct PeoInfo), cmp_age);
			printf("按年龄排序成功\n\n");
			break;
		case 0:
			printf("退出排序\n\n");
			break;
		default:
			printf("选择错误,请重新选择\n\n");
			break;
		}
	} while (intput);
	
}


//保存通讯录的信息到文件
void SaveContact(const Contact* p)
{
	//打开并创建文件
	FILE* pf = fopen("contact.data.txt", "w");//w:只写,
	if (pf == NULL)
	{
		perror("SaveContact::fopen");
		return;
	}

	//写文件
	int i = 0;
	for (i = 0; i < p->count; i++)
	{
		fwrite(p->data + i, sizeof(PeoInfo), 1, pf);
	}

	//关闭文件
	fclose(pf);
	pf = NULL;
}

//加载文件信息到通讯录中
void LoadContact(Contact* p)
{
	//打开文件
	FILE* pf = fopen("contact.data.txt", "r");//r:只读
	if (pf == NULL)
	{
		perror("LoadContact::fopen");
		return;
	}

	
	//读文件
	PeoInfo tmp = { 0 };
	while (fread(&tmp, sizeof(PeoInfo), 1, pf))
	{
		CheckCapacity(p);
		p->data[p->count] = tmp;
		p->count++;
	}

	//关闭文件
	fclose(pf);
	pf = NULL;

}


3、test.c

#include "DynamicContact.h"

void menu()
{
	printf("================================\n");
	printf("*********** Contact ************\n");
	printf("================================\n");
	printf("***     1.add     2.del      ***\n");
	printf("***     3.search  4.modify   ***\n");
	printf("***     5.sort    6.print    ***\n");
	printf("***     0.exit               ***\n");
	printf("================================\n");

}
void test()
{
	int intput = 0;
	Contact con;//创建通讯录
	InitContact(&con);//初始化通讯录
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &intput);
		switch (intput)
		{
		case ADD:
			AddContact(&con);
			break;
		case DEL:
			DelContact(&con);
			break;
		case SEARCH:
			SearchContact(&con);
			break;
		case MODIFY:
			ModifyContact(&con);
			break;
		case SORT:
			SortContact(&con);
			break;
		case PRINT:
			PrintContact(&con);
			break;
		case EXIT:
			SaveContact(&con);//销毁通讯录之前把数据存入文件中
			DestroyContact(&con);
			printf("退出通讯录\n");
			break;
		default:
			printf("输入错误,请重新输入\n\n");
			break;
		}

	} while (intput);
}
int main()
 {
	test();
	return 0;
}

最后

文章到这就结束了,希望对你有帮助,觉得文章不错就点个赞吧.

文章有什么问题可以留言,感谢支持!! 

原网站

版权声明
本文为[There are gods in the mountains]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/222/202208102322405864.html