超容易上手的C语言小项目,课设不再发愁


前言

此项目中我们主要完成一些通讯录的增删查改与保存。此项目我们用C语言在vs2019环境下进行。希望这个小项目能给有需要的同学带来帮助,有错误的地方也欢迎大家指正。

一、通讯录的框架

在这个项目中我们将会创建两个源文件,分别用来测试和放通讯录的主体函数;一个头文件,主要用来声明函数。
废话不多说,我们直接来看框架,也就是测试这一源文件中的代码,是我们通讯录的主要逻辑。

#define _CRT_SECURE_NO_WARNINGS 1//我们在vs2019上写C代码,
//得加上这行代码,不然会报错。
#include"contact.h"//所有要包含的头文件,及函数声明,为了方便管理,
//我们都放在了我们自己创建的头文件中。
void Menu()
{
	printf("********************************\n");
	printf("*****1.Add            2.del*****\n");
	printf("*****3.search     4.modify*****\n");
	printf("*****5.show          6.sort*****\n");
	printf("**********  0.exit   ***********\n");
	printf("********************************\n");

}
int main()
{
	int input = 0;
	contact con;//用结构体创建一个通讯录
	Init(&con);//对创建的通讯录进行初始化
	do
	{
		Menu();//菜单函数
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			Add(&con);//增加联系人
			break;
		case 2:
			Del(&con);删除联系人
			break;
		case 3:
			Search(&con);查找联系人
			break;
		case 4:
			Modify(&con);删除联系人
			breakcase 5:
			Show(&con);显示联系人
			break;
		case 6:
			Sort(&con);对联系人排序
			break;
		case 0:
			printf("退出");
			Save(&con);//保存联系人
			Destory(&con);//因为我们用malloc,realloc来开辟内存,
			//因此在程序结束前要将开辟的内存释放,防止内存泄漏。
			break;
		default :
			printf("选择错误,请重新选择:>");
			break;
		}

	} while (input);//菜单中0为退出,while循环也结束。
	return 0;
}

二、通讯录的具体实现过程

2.1 定义结构体

这个结构体中定义了我们所写通讯录中每个联系人所需输入的信息,并且为了后期方便修改,其大小我们都用#define进行了定义。
typedef struct peo_infor
{
	char name[Name_MAX];//姓名
	char sex[Sex_MAX];//性别
	char address[Address_MAX];//地址
	char numble[Num_MAX];//电话
	int age;//年龄
}peoinfor;
此结构体定义了通讯录,里面包含了上述所说描述联系人信息的结构体。并且,由上述结构体类指针定义了一个名字为data的柔性数组。(下一篇文章中我将会介绍)
typedef struct contact
{
	peoinfor* data;//人的信息
	int num;//当前联系人个数
	int capacity;//由于我们会开辟动态内存,因此此变量表示开辟容量。
}contact;

2.2 创建通讯录并进行初始化

通讯录的创建我们在框架部分已经说过,因此我们直接进行通讯录的初始化。
上代码!!!

void Init(contact* pc)
	{
	assert(pc);//判断pc是否为空指针,若是则进行截断,程序终止。
	peoinfor* ptr = (peoinfor*)calloc(DEFAULT_SZ, sizeof(peoinfor));
	//开辟DEFAULT_SZ个大小为sizeof(peoinfor)的空间,
	//并且calloc会将开辟好的空间全部初始化为0;
	if (ptr == NULL)//判断是否开辟成功
	{
		perror("Init::calloc");//若不成功,此函数将会打印出错误信息。
		return;
	}
	pc->data = ptr;//将开辟好的空间的地址交给data数组。
	pc->num = 0;//联系人个数初始化为0
	pc->capacity = DEFAULT_SZ;//一次开辟DEFAULT_SZ个空间,因此容量也为DEFAULT_SZ。
	LoadContact(pc);//加载文件到通讯录,因为此通讯录由保存信息功能,
	//因此,在初始化时要将文件中的信息加载到程序中来。
	}

2.3 将信息加载到通讯录

void LoadContact(contact* pc)
{
	//打开在contact.c中的contact.txt文件
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL)
	{
		perror("fopen");//判断文件是否打开成功,若不成功则打印出错误信息。
		return;
	}
	peoinfor tmp = { 0 };//创建一个变量来接受读到的文件数据。
	int i = 0;
	while (fread(&tmp, sizeof(peoinfor), 1, pf))//将pf指向的文件中的数据,
	//以每次读取一个,大小为sizeof(peoinfor)读取到tmp中。
	{
		check_capacity(pc);//增容。因为我们在初始化时开辟的内存有限,
		//防止在将文件中的信息加载到通讯录在内存不够,
		//我们要进行判断,若容量不够,要进行增容,此函数将会在后面讲解。
		pc->data[i] = tmp;//将tmp中的内容赋给data。
		pc->num++;
		i++;
	}
	fclose(pf);//切记在完成结束时被,若打开文件,要及时关闭文件。
	pf = NULL;//必将指针置空,以防成野指针。

}

2.4 增容

void check_capacity(contact* pc)
	{
	    assert(pc);//判断是否为空指针。
		if (pc->num == pc->capacity)//判断联系人个数是否达到容量
		{
		    //若达到,则用realloc进行扩容。将容量扩大至DEFAULT_SZ + INC_SZ个
			peoinfor* ptr = (peoinfor*)realloc(pc->data, (DEFAULT_SZ + INC_SZ) * sizeof(peoinfor));
			if (ptr == NULL)
			{
				perror("Add::realloc");//判断扩容是否成功。
				return;
			}
			pc->data = ptr;
			pc->capacity += INC_SZ;//不要忘记容量也要提升。
		}
    }

2.4 增加联系人

void Add(contact* pc)
{
	assert(pc);
	check_capacity(pc);//判断是否增容
	//增加信息
	printf("请输入姓名: ");
	scanf("%s", pc->data[pc->num].name);//字符串的变量名称就是其地址,因此不需要加&。
	printf("请输入性别: ");
	scanf("%s", pc->data[pc->num].sex);
	printf("请输入年龄: ");
	scanf("%d", &pc->data[pc->num].age);//其为int类型,因此要加&。
	printf("请输入地址: ");
	scanf("%s", pc->data[pc->num].address);
	printf("请输入电话: ");
	scanf("%s", pc->data[pc->num].numble);
	pc->num++;//不要忘记联系人个数要增加。
}

2.5 删除联系人

void Del(contact* pc)
{
	assert(pc);
	if (pc->num == 0)
	{
		printf("通讯录为空\n");
		return;
	}
	printf("请输入要删除人的姓名: ");
	char name[Name_MAX] = { 0 };
	scanf("%s", name);
	int ret=Find_name(pc,name);将输入的姓名与通讯录中的联系人对比。
	if (ret == -1)
	{
		printf("删除的人不存在\n");
		return;
	}
	for (int i = ret; i < pc->num-1; i++)
	{
		pc->data[i] = pc->data[i + 1];//因为联系人时连续存放,
		//因此删除某位联系人后要将后面的联系人都向前挪一个。
	}
	pc->num--;
	printf("删除成功\n");
}

2.6 判断名字是否相同

int Find_name(contact* pc, char* name)
{
	assert(pc);
	for (int i = 0; i < pc->num;i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)//用strcmp函数来进行比较,
		//其用法我在前面文章中有所讲解。
		{
			return i;//找到后,返回联系人下表。
		}
	}
	return -1;
}

2.7查找联系人

void Search(contact* pc)
{
	assert(pc);
	//按名字查找
	printf("请输入要查找人的姓名: ");
	char name[Name_MAX] = { 0 };
	scanf("%s", name);
	int i = Find_name(pc, name);
	//显示
	if (i == -1)
	{
		printf("要修改的人不存在");
		return;
	}
	printf("%-20s\t%-5s\t%-5s\t%-20s\t%-12s\n", "姓名", "性别", "年龄", "地址", "电话");
	printf("%-20s\t%-5s\t%-5d\t%-20s\t%-12s\n", pc->data[i].name,
		pc->data[i].sex, pc->data[i].age,
		pc->data[i].address,
		pc->data[i].numble);
}

2.8修改联系人

void menu2()
{
	printf("*****************************\n");
	printf("****1.修改姓名 2.修改性别****\n");
	printf("****3.修改年龄 3.修改地址****\n");
	printf("****4.修改电话     0.退出****\n");
	printf("*****************************\n");
}
//修改
void mod1(contact* pc, int i)
{
	
	printf("请输入要修改后的姓名:");
	scanf("%s", pc->data[i].name);
	
}
void mod2(contact* pc, int i)
{

	printf("请输入要修改后的性别:");
	scanf("%s", pc->data[i].sex);

}
void mod3(contact* pc, int i)
{

	printf("请输入要修改后的年龄:");
	scanf("%d",&pc->data[i].age);

}
void mod4(contact* pc, int i)
{

	printf("请输入要修改后的地址:");
	scanf("%s", pc->data[i].address);

}
void mod5(contact* pc, int i)
{

	printf("请输入要修改后的电话:");
	scanf("%s", pc->data[i].numble);

}

void Modify(contact* pc)
{
	    assert(pc);
	    int input;
		printf("请输入要修改人的名字:");
		char name[Name_MAX] = { 0 };
		scanf("%s", name);
		int i = Find_name(pc, name);
		//显示
		if (i == -1)
		{
			printf("要查找的人不存在\n");
			return;
		}
		menu2();
		printf("请选择:>");
		scanf("%d",&input);
		switch (input)
		{
		case 1:
			mod1(pc, i);
			break;
		case 2:
			mod2(pc, i);
			break;
		case 3:
			mod3(pc, i);
			break;
		case 4:
			mod4(pc, i);
			break;
		case 5:
			mod5(pc, i);
			break;
		case 0:
			printf("退出\n");
			break;
		default :
			printf("请重新选择:");
			break;
		}
		printf("修改成功\n");
}

2.9 显示联系人

void Show(const contact* pc)
{
	printf("%-20s\t%-5s\t%-5s\t%-20s\t%-12s\n", "姓名", "性别", "年龄", "地址", "电话");
	assert(pc);
	for (int i = 0; i < pc->num; i++)
	{
		printf("%-20s\t%-5s\t%-5d\t%-20s\t%-12s\n", pc->data[i].name,
			pc->data[i].sex, pc->data[i].age,
			pc->data[i].address,
			pc->data[i].numble);
	}
}

2.10 对联系人排序

//本代码中涉及到的qsort的使用,我在前面文章讲过,想详细了解可以去看看。
void menu3()
{
	printf("*************************\n");
	printf("1.按姓氏排序 2.按年龄排序\n");
	printf("*************************\n");

}
int compare1(const void* e1,const void* e2)
{
	return strcmp(((peoinfor*)e1)->name,((peoinfor*)e2)->name);
}
int compare2(const void* e1, const void* e2)
{
	return ((peoinfor*)e1)->age-((peoinfor*)e2)->age;
}
void Sort(contact* pc)
{
	assert(pc);
	if (pc->num == 0)
	{
		printf("通讯录为空\n");
		return;
	}
	menu3();
	int input;
	printf("请选择:");
	scanf("%d", &input);
	switch (input)
	{
	case 1:
		qsort(pc->data,pc->num,sizeof(pc->data[0]),compare1);
		break;
	case 2:
		qsort(pc->data, pc->num, sizeof(pc->data[0]), compare2);
		break;
	default :
		printf("请重新选择");
		break;
	}
	printf("排序成功\n");
	Show(pc);

}

2.11 保存联系人

void Save(contact* pc)
{
	FILE* pf = fopen("contact.txt", "wb");
	if (pf == NULL)
	{
		perror("fopen");
		return;
	}
	int i = 0;
	for (i = 0; i < pc->num; i++)
	{
		fwrite(pc->data + i, sizeof(peoinfor), 1, pf);
	}
	fclose(pf);
	pf = NULL;
	printf("保存成功");
}

2.12 销毁通讯录

void Destory(contact* pc)
{
	
	free(pc->data);
	pc->data = NULL;
	pc->capacity = 0;
	pc->num = 0;

	
}

完整代码

头文件

#include<stdio.h>
#define Name_MAX 20
#define Sex_MAX  5
#define Address_MAX 20
#define Num_MAX 12
#include<assert.h>
#include<string.h>
#include<stdlib.h>
#define DEFAULT_SZ 3
#define INC_SZ 2
typedef struct peo_infor
{
	char name[Name_MAX];
	char sex[Sex_MAX];
	char address[Address_MAX];
	char numble[Num_MAX];
	int age;
}peoinfor;
//静态
//typedef struct contact
//{
//	peoinfor data[100];
//	int num;
//}contact;
//动态
typedef struct contact
{
	peoinfor* data;
	int num;
	int capacity;
}contact;
void Init(contact* pc);
void Add(contact* pc);
void Show(const contact* pc);
void Del(contact* pc);
void Search(contact* pc);
void Modify(contact* pc);
void Sort(contact* pc);
void Destory(contact* pc);
void LoadContact(contact* pc);
void Save(contact* pc);

contact.c文件

#include"contact.h"
void Init(contact* pc)
	{
	assert(pc);
	peoinfor* ptr = (peoinfor*)calloc(DEFAULT_SZ, sizeof(peoinfor));
	if (ptr == NULL)
	{
		perror("Init::calloc");
		return;
	}
	pc->data = ptr;
	pc->num = 0;
	pc->capacity = DEFAULT_SZ;
	//加载文件到通讯录
	LoadContact(pc);
	}
	void check_capacity(contact* pc)
	{
		assret(pc);
		if (pc->num == pc->capacity)
		{
			peoinfor* ptr = (peoinfor*)realloc(pc->data, (DEFAULT_SZ + INC_SZ) * sizeof(peoinfor));
			if (ptr == NULL)
			{
				perror("Add::realloc");
				return;
			}
			pc->data = ptr;
			pc->capacity += INC_SZ;
		}
    }
void Add(contact* pc)
{
	assert(pc);
	check_capacity(pc);
	//增加信息
	printf("请输入姓名: ");
	scanf("%s", pc->data[pc->num].name);
	printf("请输入性别: ");
	scanf("%s", pc->data[pc->num].sex);
	printf("请输入年龄: ");
	scanf("%d", &pc->data[pc->num].age);
	printf("请输入地址: ");
	scanf("%s", pc->data[pc->num].address);
	printf("请输入电话: ");
	scanf("%s", pc->data[pc->num].numble);
	pc->num++;
}
void Show(const contact* pc)
{
	printf("%-20s\t%-5s\t%-5s\t%-20s\t%-12s\n", "姓名", "性别", "年龄", "地址", "电话");
	assert(pc);
	for (int i = 0; i < pc->num; i++)
	{
		printf("%-20s\t%-5s\t%-5d\t%-20s\t%-12s\n", pc->data[i].name,
			pc->data[i].sex, pc->data[i].age,
			pc->data[i].address,
			pc->data[i].numble);
	}
}
int Find_name(contact* pc, char* name)
{
	assert(pc);
	for (int i = 0; i < pc->num;i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}
void Del(contact* pc)
{
	assert(pc);
	if (pc->num == 0)
	{
		printf("通讯录为空\n");
		return;
	}
	printf("请输入要删除人的姓名: ");
	char name[Name_MAX] = { 0 };
	scanf("%s", name);
	int ret=Find_name(pc,name);
	if (ret == -1)
	{
		printf("删除的人不存在\n");
		return;
	}
	for (int i = ret; i < pc->num-1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->num--;
	printf("删除成功\n");
}
void Search(contact* pc)
{
	assert(pc);
	//按名字查找
	printf("请输入要查找人的姓名: ");
	char name[Name_MAX] = { 0 };
	scanf("%s", name);
	int i = Find_name(pc, name);
	//显示
	if (i == -1)
	{
		printf("要修改的人不存在");
		return;
	}
	printf("%-20s\t%-5s\t%-5s\t%-20s\t%-12s\n", "姓名", "性别", "年龄", "地址", "电话");
	printf("%-20s\t%-5s\t%-5d\t%-20s\t%-12s\n", pc->data[i].name,
		pc->data[i].sex, pc->data[i].age,
		pc->data[i].address,
		pc->data[i].numble);
}
void menu2()
{
	printf("*****************************\n");
	printf("****1.修改姓名 2.修改性别****\n");
	printf("****3.修改年龄 3.修改地址****\n");
	printf("****4.修改电话     0.退出****\n");
	printf("*****************************\n");
}
//修改
void mod1(contact* pc, int i)
{
	
	printf("请输入要修改后的姓名:");
	scanf("%s", pc->data[i].name);
	
}
void mod2(contact* pc, int i)
{

	printf("请输入要修改后的性别:");
	scanf("%s", pc->data[i].sex);

}
void mod3(contact* pc, int i)
{

	printf("请输入要修改后的年龄:");
	scanf("%d",&pc->data[i].age);

}
void mod4(contact* pc, int i)
{

	printf("请输入要修改后的地址:");
	scanf("%s", pc->data[i].address);

}
void mod5(contact* pc, int i)
{

	printf("请输入要修改后的电话:");
	scanf("%s", pc->data[i].numble);

}

void Modify(contact* pc)
{
	    assert(pc);
	    int input;
		printf("请输入要修改人的名字:");
		char name[Name_MAX] = { 0 };
		scanf("%s", name);
		int i = Find_name(pc, name);
		//显示
		if (i == -1)
		{
			printf("要查找的人不存在\n");
			return;
		}
		menu2();
		printf("请选择:>");
		scanf("%d",&input);
		switch (input)
		{
		case 1:
			mod1(pc, i);
			break;
		case 2:
			mod2(pc, i);
			break;
		case 3:
			mod3(pc, i);
			break;
		case 4:
			mod4(pc, i);
			break;
		case 5:
			mod5(pc, i);
			break;
		case 0:
			printf("退出\n");
			break;
		default :
			printf("请重新选择:");
			break;
		}
		printf("修改成功\n");
}
void menu3()
{
	printf("*************************\n");
	printf("1.按姓氏排序 2.按年龄排序\n");
	printf("*************************\n");

}
int compare1(const void* e1,const void* e2)
{
	return strcmp(((peoinfor*)e1)->name,((peoinfor*)e2)->name);
}
int compare2(const void* e1, const void* e2)
{
	return ((peoinfor*)e1)->age-((peoinfor*)e2)->age;
}
void Sort(contact* pc)
{
	assert(pc);
	if (pc->num == 0)
	{
		printf("通讯录为空\n");
		return;
	}
	menu3();
	int input;
	printf("请选择:");
	scanf("%d", &input);
	switch (input)
	{
	case 1:
		qsort(pc->data,pc->num,sizeof(pc->data[0]),compare1);
		break;
	case 2:
		qsort(pc->data, pc->num, sizeof(pc->data[0]), compare2);
		break;
	default :
		printf("请重新选择");
		break;
	}
	printf("排序成功\n");
	Show(pc);

}
void Destory(contact* pc)
{
	
	free(pc->data);
	pc->data = NULL;
	pc->capacity = 0;
	pc->num = 0;

	
}
void Save(contact* pc)
{
	FILE* pf = fopen("contact.txt", "wb");
	if (pf == NULL)
	{
		perror("fopen");
		return;
	}
	int i = 0;
	for (i = 0; i < pc->num; i++)
	{
		fwrite(pc->data + i, sizeof(peoinfor), 1, pf);
	}
	fclose(pf);
	pf = NULL;
	printf("保存成功");
}

void LoadContact(contact* pc)
{
	//打开文件
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL)
	{
		perror("fopen");
		return;
	}
	peoinfor tmp = { 0 };
	int i = 0;
	while (fread(&tmp, sizeof(peoinfor), 1, pf))
	{
		//增容
		check_capacity(pc);
		pc->data[i] = tmp;
		pc->num++;
		i++;
	}
	fclose(pf);
	pf = NULL;

}

test.c文件

#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"
void Menu()
{
	printf("********************************\n");
	printf("*****1.Add            2.del*****\n");
	printf("*****3.search     4.modify*****\n");
	printf("*****5.show          6.sort*****\n");
	printf("**********  0.exit   ***********\n");
	printf("********************************\n");

}
int main()
{
	int input = 0;
	//创建
	contact con;
	//初始化
	Init(&con);
	do
	{
		Menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			Add(&con);
			break;
		case 2:
			Del(&con);
			break;
		case 3:
			Search(&con);
			break;
		case 4:
			Modify(&con);
			break;
		case 5:
			Show(&con);
			break;
		case 6:
			Sort(&con);
			break;
		case 0:
			printf("退出");
			Save(&con);
			Destory(&con);
			break;
		default :
			printf("选择错误,请重新选择:>");
			break;
		}

	} while (input);
	return 0;
}

总结

提示:这里对文章进行总结:

例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

进击的1++

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

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

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

打赏作者

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

抵扣说明:

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

余额充值