C语言实现通讯录管理系统(文件操作版本)

目录

1. 需求分析

2. 程序架构

3. 代码实现(分函数呈现)

(1)主函数代码实现

(2)菜单函数的实现

(3)初始化功能实现

(4)添加联系人功能实现

(5)删除通讯录中的信息

(6)查找通讯录中联系人的信息

(7)查找函数实现

(8)修改联系人的信息

(9)打印通讯录中联系人的信息

(10)对通讯录中联系人的信息进行排序

(11)清空通讯录中联系人的信息

(12)销毁通讯录

(13)保存通讯录中的信息

4. 代码呈现(分文件实现)

(1)test.c

(2)contact.h

(3)contact.c


1. 需求分析

通过C语言实现简单的通讯录管理系统,要求实现的功能有:增加联系人信息、删除联系人信息、查找联系人信息、修改联系人信息、清空联系人信息、对联系人的信息进行排序、显示联系人信息,同时要求使用动态内存分配和文件管理,实现通讯录的保存与对读取。

2. 程序架构

程序分为test.c、contact.c两个源文件和contact.h一个头文件。

test.c:主函数接口引入。

contact.c:函数主要实现

contact.h:头文件引入、函数声明、结构体声明。

3. 代码实现(分函数呈现)

(1)主函数代码实现

//测试函数的功能
int main()
{
	//创建通讯录
	struct contact con;//con就是通讯录,里面包含:data指针和size,capacity
	//初始化通讯录
	Init_Contact(&con);
	int input = 0;
	int size = 0;//记录当前有多少人
	do
	{
		menu();
		printf("请选择->");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			//增加
			Add_Contacter(&con);
			break;
		case DEL:
			//删除
			Del_Contacter(&con);
			break;
		case SEARCH:
			//查找
			Find_Contacter(&con);
			break;
		case MODIFY:
			//修改
			Mod_Contacter(&con);
			break;
		case SHOW:
			//打印
			Print_Contacter(&con);
			break;
		case CLEAR:
			//清空
			Clear_Contacter(&con);
			break;
		case SORT:
			//排序
			Sort_Contacter(&con);
			break;
		case EXIT:
		    //退出并销毁通讯录
			Save_Contact(&con);
			Destory_Contact(&con);
			printf("退出通讯录!\n");
			break;
		case 8:
			//保存通讯录
			Save_Contact(&con);
			break;
		default:
			printf("选择错误,请重新输入!\n");
		}
	} while (input);
	return 0;
}

分析:主要是引入函数的接口,此处用了常见的do while循环,并且将input变量作为while()后面括号中的条件,此处是一个极其巧妙的运用,当input变量为0时循环结束,程序终止,此时也与前面的switch和case进行了一一对应。这个版本的通讯录管理系统与之前的通讯录管理系统略有区别。此处的区别在于创建通讯录的时候,此处创建的是一个结构体变量con,而不是像之前一样建立的是一个结构体数组,此处结构体变量中存储的一方面有通讯录中所有人的信息即data,这些信息打包成了一个数组,同时还有两个整型变量,size存储的是当前已经有的元素个数,而capacity存储的是当前通讯录的最大容量。相比之前的动态管理版本,此处增加了保存选项,同时在退出通讯录之前都会默认进行一次保存,以防用户在退出之前对通讯录的信息忘记进行保存。

(2)菜单函数的实现

void menu()
{
	printf("************************************\n");
	printf("****  1.add         2.del       ****\n");
	printf("****  3.search      4.modify    ****\n");
	printf("****  5.show        6.clear     ****\n");
	printf("****  7.sort        8.save      ****\n");
	printf("*********     0.exit      **********\n");
	printf("************************************\n");
}

分析:简单运用printf将菜单进行输出,通过*来使输出形式更加清晰简洁美观。

(3)初始化功能实现

//加载文件中的信息到通讯录中
void Load_Contact(struct contact* ps)
{
	
	FILE* pfRead = fopen("contact.dat", "rb");
	if (pfRead== NULL)
	{
		printf("Load_Contact::%s", strerror(errno));
		return;
	}
	//读取文件存放到通讯录中
	struct PeoInfo tmp = { 0 };
	while (fread(&tmp,sizeof(tmp),1,pfRead))
	{
		CheckCapacity(ps);
		ps->data[ps->size] = tmp;
		ps->size++;
		printf("读取成功!\n");
	}
	
	//关闭文件
	fclose(pfRead);
	pfRead = NULL;
}

//初始化通讯录中的信息
void Init_Contact(struct contact* ps)
{
	ps->data = (struct PeoInfo*)malloc(sizeof(struct PeoInfo) * 3);
	if (ps->data == NULL)
	{
		return;
	}
	ps->size = 0;//设置通讯录最初只有0个元素
	ps->capacity = DEFAULT_SZ;
	//把文件中已经存放的信息加载到通讯录中
	Load_Contact(ps);
}

分析:在此处就体现了和之前通讯录管理系统的不同,此处增加了一个加载函数,是将之前文件中联系人的信息加载到通讯录中来,使用了文件操作函数fread()函数来对文件中的信息进行读取,此处使用了fread()函数的返回值,即成功读取的数据的数目,因为每次只读取一个联系人的数据,所以如果成功读取就返回1,如果读取失败就返回0,当数据读取完时即会读取失败,此时通过while()循环进行控制,同时使用fopen()和fclose()函数进行控制文件的打开和关闭。

读取时要注意一个问题,就是当我们动态开辟的空间不够时,我们就要使用我们的CheckCapacity()函数对容量进行检查,如果容量不够就要进行扩容。

(4)添加联系人功能实现

void CheckCapacity(struct contact* ps)
{
	if (ps->size == ps->capacity)
	{
		//增容
		struct PeoInfo* ptr= realloc(ps->data, (ps->capacity + 2)*sizeof(struct PeoInfo));
		if (ptr != NULL)
		{
			ps->data = ptr;
			ps->capacity += 2;
			printf("增容成功!\n");
		}
		else
		{
			printf("增容失败!\n");
		}
	}
}
//添加通讯录中的信息
void Add_Contacter(struct contact* ps)
{
	//检测当前通讯录的容量
	//1、如果满了,就增加空间
	//2、如果不满,啥事都不干
	CheckCapacity(ps);
	//增加数据
	printf("请输入名字:");
	scanf("%s", &ps->data[ps->size].name);
	printf("请输入年龄:");
	scanf("%d", &ps->data[ps->size].age);
	printf("请输入性别:");
	scanf("%s", &ps->data[ps->size].sex);
	printf("请输入电话:");
	scanf("%s", &ps->data[ps->size].phone);
	printf("请输入地址:");
	scanf("%s", &ps->data[ps->size].address);

	ps->size++;
	printf("添加成功!\n");
}

分析:在进行添加时要注意进行分情况讨论,首先就是当联系人数目满了的话就必须对其进行扩容,此处检查容量运用的是CheckCapacity函数,每次扩容可以增加两个联系人的信息,通过realloc函数进行实现,扩容后,容量加2。只有当联系人数目未满的时候才能继续添加,添加后,要将记录联系人数目的变量size进行加一;如果当前通讯录没有满,就什么都不干,即进行正常的添加通讯录联系人的信息就好。此处并不需要每一次在添加联系人信息后

(5)删除通讯录中的信息

//删除通讯录中的信息
void Del_Contacter(struct contact* ps)
{
	char name[MAX_NAME];
	printf("请输入你要删除的联系人的姓名:");
	scanf("%s", name);
	//查找要删除的人所在的位置
	//找到了返回名字所在元素的下标,没找到就返回-1
	int pos = Find_byName(ps,name);
	if (pos==-1)//删除的人不存在
	{
		printf("要删除的人不存在!\n");
	}
	else//删除
	{
		int j = 0;
		for (j = pos; j < ps->size-1; j++)
		{
			ps->data[j] = ps->data[j + 1];
		}
		ps->size--;
		printf("删除成功!\n");
	}
}

分析:删除操作并不复杂,就是先查找到我们想要删除的那个联系人,然后将这个联系人后面的信息逐个向前进行覆盖,同时将记录联系人数目的变量size的值进行减1。

(6)查找通讯录中联系人的信息

//查找通讯录中的信息
void Find_Contacter(const struct contact* ps)
{
	char name[MAX_NAME];
	printf("请输入你要查找的联系人的姓名:");
	scanf("%s", name);
	int pos = Find_byName(ps, name);
	if (pos==-1)//查找的人不存在
	{
		printf("要查找的人不存在!\n");
	}
	else
	{
		printf("%-20s\t%-4s\t%-5s\t%-12s\t%-20s\n", "姓名", "年龄", "性别", "电话", "地址");
		printf("%-20s\t%-4d\t%-5s\t%-12s\t%-20s\n", ps->data[pos].name,
			ps->data[pos].age,
			ps->data[pos].sex,
			ps->data[pos].phone,
			ps->data[pos].address);
	}
}

分析:首先先通过查找函数将我们想要查找到的联系人找到,然后通过printf函数打印联系人的信息。

(7)查找函数实现

static int Find_byName(const struct contact* ps, char name[MAX_NAME])
{
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		if (0 == strcmp(ps->data[i].name, name))
		{
			return i;
		}
	}
	return -1;
}

分析:此处查找函数是通过遍历联系人中的信息进行实现的,当我们想查找的联系人的信息与某个联系人的信息一致时就停止下来,如果能够找到就返回其对应的下标,如果找不到就返回-1。

(8)修改联系人的信息

//修改通讯录中的信息
void Mod_Contacter(struct contact* ps)
{
	char name[MAX_NAME];
	printf("请输入你要修改的联系人的姓名:");
	scanf("%s", name);
	int pos = Find_byName(ps, name);
	if (pos==-1)//修改的人不存在
	{
		printf("要修改的人不存在!\n");
	}
	else
	{
		printf("请输入名字:");
		scanf("%s", &ps->data[pos].name);
		printf("请输入年龄:");
		scanf("%d", &ps->data[pos].age);
		printf("请输入性别:");
		scanf("%s", &ps->data[pos].sex);
		printf("请输入电话:");
		scanf("%s", &ps->data[pos].phone);
		printf("请输入地址:");
		scanf("%s", &ps->data[pos].address);
		printf("修改成功!\n");
	}
}

分析:修改联系人的信息与上面其实类似,首先是找到我们想要修改的联系人的信息,然后再进行修改。

(9)打印通讯录中联系人的信息

//打印通讯录中的信息
void Print_Contacter(const struct contact* ps)
{
	if (ps->size == 0)
	{
		printf("通讯录为空!\n");
	}
	else
	{
		//标题
		printf("%-20s\t%-4s\t%-5s\t%-12s\t%-20s\n",  "姓名", "年龄", "性别", "电话", "地址");
		int i = 0;
		while (i < ps->size)
		{
			//数据
			printf("%-20s\t%-4d\t%-5s\t%-12s\t%-20s\n", ps->data[i].name, 
				ps->data[i].age, 
				ps->data[i].sex, 
				ps->data[i].phone, 
				ps->data[i].address);
			i++;
		}
	}
}

分析:这个功能并不难实现,就是设置一个循环变量i,然后从头开始对通讯录信息进行遍历,当i小于size的时候将对应联系人的信息打印出来。

(10)对通讯录中联系人的信息进行排序

//对通讯录中的信息进行排序
//排序函数
//1.按照姓名进行排序
int Conpare_ByName(const void *e1,const void *e2)
{
	return strcmp(((struct PeoInfo*)e1)->name, ((struct PeoInfo*)e2)->name);
}
//2.按照年龄进行排序
int Conpare_ByAge(const void* e1, const void* e2)
{
	return ((struct PeoInfo*)e1)->age-((struct PeoInfo*)e2)->age;
}
//3.按照住址进行排序
int Conpare_ByAddress(const void* e1, const void* e2)
{
	return strcmp(((struct PeoInfo*)e1)->address, ((struct PeoInfo*)e2)->address);
}
void Sort_Contacter(struct contact* ps)
{
	printf("请选择你想排序的方式:\n");
	printf("1.姓名\n2.年龄\n3.住址\n");
	int input = 0;
	scanf("%d", &input);
	switch (input)
	{
	case 1:
		qsort(ps->data,ps->size,sizeof(ps->data[0]),Conpare_ByName);
		printf("排序成功\n");
		break;
	case 2:
		qsort(ps->data, ps->size, sizeof(ps->data[0]), Conpare_ByAge);
		printf("排序成功\n");
		break;
	case 3:
		qsort(ps->data, ps->size, sizeof(ps->data[0]), Conpare_ByAddress);
		printf("排序成功\n");
		break;
	}
}

分析:此处运用了qsort快速排序的函数,此处的关键就是设定好自己想要排序的依据,比如我们想根据年龄或者名字进行排序,此处要求掌握快速排序函数的使用。

(11)清空通讯录中联系人的信息

//清空通讯中的信息
void Clear_Contacter(struct contact* ps)
{
	memset(ps->data, 0, sizeof(ps->data));
	ps->size = 0;
	printf("清空成功!\n");
}

分析:此处其实类似于初始化联系人的信息,就是将那段内存空间中的数据使用memset函数全部设置为0,然后将记录联系人数目的变量size设定为0。

(12)销毁通讯录

//销毁通讯录
void Destory_Contact(struct contact* ps)
{
	free(ps->data);
	ps->data = NULL;
}

(13)保存通讯录中的信息

//保存通讯录的信息
void Save_Contact(struct contact* ps)
{
	FILE* pfWrite = fopen("contact.dat", "wb");
	if (pfWrite == NULL)
	{
		printf("Save_Contact::%s", strerror(errno));
		return;
	}
	//将通讯录中的数据到文件中
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		fwrite(&(ps->data[i]), sizeof(struct PeoInfo), 1, pfWrite);
	}
	printf("保存成功!\n");
	//关闭文件
	fclose(pfWrite);
	pfWrite = NULL;
}

分析:保存通讯录中的信息,使用的是fwrite()函数,即将通讯录中的数据写入到文件中去,同时使用了fopen()和fclose()进行关闭文件。值得注意的是:最后要将文件指针置为空指针。

4. 代码呈现(分文件实现)

(1)test.c

#include"contact.h"
enum Option
{
	EXIT,//0
	ADD,//1
	DEL,//2
	SEARCH,//3
	MODIFY,//4
	SHOW,//5
	CLEAR,//6
	SORT,//7
	SAVE
};
void menu()
{
	printf("************************************\n");
	printf("****  1.add         2.del       ****\n");
	printf("****  3.search      4.modify    ****\n");
	printf("****  5.show        6.clear     ****\n");
	printf("****  7.sort        8.save      ****\n");
	printf("*********     0.exit      **********\n");
	printf("************************************\n");
}
//测试函数的功能
int main()
{
	//创建通讯录
	struct contact con;//con就是通讯录,里面包含:data指针和size,capacity
	//初始化通讯录
	Init_Contact(&con);
	int input = 0;
	int size = 0;//记录当前有多少人
	do
	{
		menu();
		printf("请选择->");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			//增加
			Add_Contacter(&con);
			break;
		case DEL:
			//删除
			Del_Contacter(&con);
			break;
		case SEARCH:
			//查找
			Find_Contacter(&con);
			break;
		case MODIFY:
			//修改
			Mod_Contacter(&con);
			break;
		case SHOW:
			//打印
			Print_Contacter(&con);
			break;
		case CLEAR:
			//清空
			Clear_Contacter(&con);
			break;
		case SORT:
			//排序
			Sort_Contacter(&con);
			break;
		case EXIT:
		    //退出并销毁通讯录
			Save_Contact(&con);
			Destory_Contact(&con);
			printf("退出通讯录!\n");
			break;
		case 8:
			//保存通讯录
			Save_Contact(&con);
			break;
		default:
			printf("选择错误,请重新输入!\n");
		}
	} while (input);
	return 0;
}

(2)contact.h

#pragma once
#define MAX_NAME 20
#define MAX_PHONE 12
#define MAX_SEX 5
#define MAX_ADDRESS 30
#define _CRT_SECURE_NO_WARNINGS 1
#define DEFAULT_SZ 3
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<errno.h>
struct PeoInfo
{
	char name[MAX_NAME];
	char phone[MAX_PHONE];
	char sex[MAX_SEX];
	char address[MAX_ADDRESS];
	int age;
};
struct contact
{
	struct PeoInfo* data;
	int size;//记录当前已经有的元素个数
	int capacity;//记录当前通讯录的最大容量
};
//声明函数
//初始化通讯录的函数
void Init_Contact(struct contact* ps);
//增加一个信息到通讯录
void Add_Contacter(struct contact* ps);
//删除指定的联系人
void Del_Contacter(struct contact* ps);
//查找指定人的信息
void Find_Contacter(const struct contact* ps);
//修改指定人的信息
void Mod_Contacter(struct contact* ps);
//打印通讯录中的信息
void Print_Contacter(const struct contact* ps);
//对通讯录中的联系人进行排序
void Sort_Contacter(struct contact* ps);
//清空通讯录中的信息
void Clear_Contacter(struct contact* ps);
//销毁通讯录
void Destory_Contact(struct contact*ps);
//保存通讯录的信息
void Save_Contact(struct contact* ps);
//加载文件中的信息到通讯录中
void Load_Contact(struct contact* ps);

(3)contact.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"
//实现函数的功能
static int Find_byName(const struct contact* ps, char name[MAX_NAME])
{
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		if (0 == strcmp(ps->data[i].name, name))
		{
			return i;
		}
	}
	return -1;
}
void CheckCapacity(struct contact*);
//加载文件中的信息到通讯录中
void Load_Contact(struct contact* ps)
{
	
	FILE* pfRead = fopen("contact.dat", "rb");
	if (pfRead== NULL)
	{
		printf("Load_Contact::%s", strerror(errno));
		return;
	}
	//读取文件存放到通讯录中
	struct PeoInfo tmp = { 0 };
	while (fread(&tmp,sizeof(tmp),1,pfRead))
	{
		CheckCapacity(ps);
		ps->data[ps->size] = tmp;
		ps->size++;
		printf("读取成功!\n");
	}
	
	//关闭文件
	fclose(pfRead);
	pfRead = NULL;
}

//初始化通讯录中的信息
void Init_Contact(struct contact* ps)
{
	ps->data = (struct PeoInfo*)malloc(sizeof(struct PeoInfo) * 3);
	if (ps->data == NULL)
	{
		return;
	}
	ps->size = 0;//设置通讯录最初只有0个元素
	ps->capacity = DEFAULT_SZ;
	//把文件中已经存放的信息加载到通讯录中
	Load_Contact(ps);
}
void CheckCapacity(struct contact* ps)
{
	if (ps->size == ps->capacity)
	{
		//增容
		struct PeoInfo* ptr= realloc(ps->data, (ps->capacity + 2)*sizeof(struct PeoInfo));
		if (ptr != NULL)
		{
			ps->data = ptr;
			ps->capacity += 2;
			printf("增容成功!\n");
		}
		else
		{
			printf("增容失败!\n");
		}
	}
}
//添加通讯录中的信息
void Add_Contacter(struct contact* ps)
{
	//检测当前通讯录的容量
	//1、如果满了,就增加空间
	//2、如果不满,啥事都不干
	CheckCapacity(ps);
	//增加数据
	printf("请输入名字:");
	scanf("%s", &ps->data[ps->size].name);
	printf("请输入年龄:");
	scanf("%d", &ps->data[ps->size].age);
	printf("请输入性别:");
	scanf("%s", &ps->data[ps->size].sex);
	printf("请输入电话:");
	scanf("%s", &ps->data[ps->size].phone);
	printf("请输入地址:");
	scanf("%s", &ps->data[ps->size].address);

	ps->size++;
	printf("添加成功!\n");
}
//删除通讯录中的信息
void Del_Contacter(struct contact* ps)
{
	char name[MAX_NAME];
	printf("请输入你要删除的联系人的姓名:");
	scanf("%s", name);
	//查找要删除的人所在的位置
	//找到了返回名字所在元素的下标,没找到就返回-1
	int pos = Find_byName(ps,name);
	if (pos==-1)//删除的人不存在
	{
		printf("要删除的人不存在!\n");
	}
	else//删除
	{
		int j = 0;
		for (j = pos; j < ps->size-1; j++)
		{
			ps->data[j] = ps->data[j + 1];
		}
		ps->size--;
		printf("删除成功!\n");
	}
}
//查找通讯录中的信息
void Find_Contacter(const struct contact* ps)
{
	char name[MAX_NAME];
	printf("请输入你要查找的联系人的姓名:");
	scanf("%s", name);
	int pos = Find_byName(ps, name);
	if (pos==-1)//查找的人不存在
	{
		printf("要查找的人不存在!\n");
	}
	else
	{
		printf("%-20s\t%-4s\t%-5s\t%-12s\t%-20s\n", "姓名", "年龄", "性别", "电话", "地址");
		printf("%-20s\t%-4d\t%-5s\t%-12s\t%-20s\n", ps->data[pos].name,
			ps->data[pos].age,
			ps->data[pos].sex,
			ps->data[pos].phone,
			ps->data[pos].address);
	}
}
//修改通讯录中的信息
void Mod_Contacter(struct contact* ps)
{
	char name[MAX_NAME];
	printf("请输入你要修改的联系人的姓名:");
	scanf("%s", name);
	int pos = Find_byName(ps, name);
	if (pos==-1)//修改的人不存在
	{
		printf("要修改的人不存在!\n");
	}
	else
	{
		printf("请输入名字:");
		scanf("%s", &ps->data[pos].name);
		printf("请输入年龄:");
		scanf("%d", &ps->data[pos].age);
		printf("请输入性别:");
		scanf("%s", &ps->data[pos].sex);
		printf("请输入电话:");
		scanf("%s", &ps->data[pos].phone);
		printf("请输入地址:");
		scanf("%s", &ps->data[pos].address);
		printf("修改成功!\n");
	}
}
//打印通讯录中的信息
void Print_Contacter(const struct contact* ps)
{
	if (ps->size == 0)
	{
		printf("通讯录为空!\n");
	}
	else
	{
		//标题
		printf("%-20s\t%-4s\t%-5s\t%-12s\t%-20s\n",  "姓名", "年龄", "性别", "电话", "地址");
		int i = 0;
		while (i < ps->size)
		{
			//数据
			printf("%-20s\t%-4d\t%-5s\t%-12s\t%-20s\n", ps->data[i].name, 
				ps->data[i].age, 
				ps->data[i].sex, 
				ps->data[i].phone, 
				ps->data[i].address);
			i++;
		}
	}
}
//对通讯录中的信息进行排序
//排序函数
//1.按照姓名进行排序
int Conpare_ByName(const void *e1,const void *e2)
{
	return strcmp(((struct PeoInfo*)e1)->name, ((struct PeoInfo*)e2)->name);
}
//2.按照年龄进行排序
int Conpare_ByAge(const void* e1, const void* e2)
{
	return ((struct PeoInfo*)e1)->age-((struct PeoInfo*)e2)->age;
}
//3.按照住址进行排序
int Conpare_ByAddress(const void* e1, const void* e2)
{
	return strcmp(((struct PeoInfo*)e1)->address, ((struct PeoInfo*)e2)->address);
}
void Sort_Contacter(struct contact* ps)
{
	printf("请选择你想排序的方式:\n");
	printf("1.姓名\n2.年龄\n3.住址\n");
	int input = 0;
	scanf("%d", &input);
	switch (input)
	{
	case 1:
		qsort(ps->data,ps->size,sizeof(ps->data[0]),Conpare_ByName);
		printf("排序成功\n");
		break;
	case 2:
		qsort(ps->data, ps->size, sizeof(ps->data[0]), Conpare_ByAge);
		printf("排序成功\n");
		break;
	case 3:
		qsort(ps->data, ps->size, sizeof(ps->data[0]), Conpare_ByAddress);
		printf("排序成功\n");
		break;
	}
}
//清空通讯中的信息
void Clear_Contacter(struct contact* ps)
{
	memset(ps->data, 0, sizeof(ps->data));
	ps->size = 0;
	printf("清空成功!\n");
}
//销毁通讯录
void Destory_Contact(struct contact* ps)
{
	free(ps->data);
	ps->data = NULL;
}
//保存通讯录的信息
void Save_Contact(struct contact* ps)
{
	FILE* pfWrite = fopen("contact.dat", "wb");
	if (pfWrite == NULL)
	{
		printf("Save_Contact::%s", strerror(errno));
		return;
	}
	//将通讯录中的数据到文件中
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		fwrite(&(ps->data[i]), sizeof(struct PeoInfo), 1, pfWrite);
	}
	printf("保存成功!\n");
	//关闭文件
	fclose(pfWrite);
	pfWrite = NULL;
}
C语言编写的通讯录管理程序设计 #include"stdio.h" #include"stdlib.h" #include"string.h" #include"conio.h" #define HEADER1"------------------------------------------MESSAGE MENU--------------------------------------------------------------\n" #define HEADER2" | num | name | phonenumber | address |\n" #define HEADER3" |-------------------------------------------------------------------|\n" #define FORMAT " | %-10s %-10s %-15s %-20s |\n" #define DATA p->num,p->name,p->phonenum,p->address #define END " ------------------------------------------------------------------------------------------------------------------\n" #define N 100 int saveflag=0; /*是否需要存盘的标志变量*/ typedef struct record /*标记为record*/ { char num[4]; /*编号*/ char name[10]; /*姓名*/ char phonenum[15]; /*电话*/ char address[20]; /*地址*/ } RECORD; RECORD tele[N]; void menu(); void Disp(); void Qur(); void Modify(); void SelectSort(); void Wrong(); void Save(); void main() { RECORD tele[N]; /*定义RECOED结构体*/ FILE *fp; /*文件指针*/ int select; /*保持内选择结果变量*/ char ch; /*保存y,Y,n,N*/ int count=0; /*保存文件中的记录条数(或元素个数)*/ fp=fopen("C:\\record.txt","a+"); /*以追加方式打开文本文件c;\record,可读可写,若此文件不存在,会创建此文件*/ if(fp==NULL) { printf("\n=>Can not open file!\n"); exit(0); } while(!feof(fp)) { if(fread(&tele[count],sizeof(RECORD),1,fp)==1) /*一次从文件中读取一条通讯记录*/ count++; } fclose(fp); /*关闭文件*/ printf("\n=>Open file success,the total records number is:%d.\n",count); getchar(); menu(); while(1) { system("cls"); menu(); cprintf("\n Please input your choice(0-8):"); /*显示提示信息*/ ch=getch(); if(ch=='0') { if(saveflag==1) /*若对数组的数据有修且未进行存盘操作,则此标志为1*/ { getchar(); printf("\n==>Whether save the modified record to file?(y/n):"); scanf("%c",&ch); if(ch=='y'||ch=='Y') Save(tele,count); } printf("\n=>Thank you for useness!"); getchar(); break ; } switch(ch) { case'0':break; case'1':count=Add(tele,count);break; /*增加通讯记录*/ case'2':system("cls");Disp(tele,count);break; /*显示通讯记录*/ case'3':count=Del(tele,count) ;break; /*删除通讯记录*/ case'4':Qur(tele,count);break; /*查询通讯记录*/ case'5':Modify(tele,count);break; /*修改通讯记录*/ case'6':count=Insert(tele,count);break; /*插入通讯记录*/ case'7':SelectSort(tele,count);break;/*排序通讯记录*/ case'8':Save(tele,count);break; /*保存通讯记录*/ default: Wrong();getchar();break; /*按键有误,必需为0~8*/ } } } void menu() { system("cls"); /*调用DOS命令清屏,与clrscr()功能相同*/ textcolor(63); /*在文本模式中选择新的字符颜色*/ gotoxy(10,5); /*在文本窗口中设置光标*/ printf(" The communication management system\n"); gotoxy(10,8); printf(" ****Menu**** \n"); gotoxy(10,9); printf("\n"); gotoxy(10,10); printf("\* 1. Add record\n"); /*增加*/ gotoxy(10,11); printf("\* 2. Display record\n"); /*展览*/ gotoxy(10,12); printf("\* 3. Delete record\n"); /*删除*/ gotoxy(10,13); printf("\* 4. Search record\n"); /*查找*/ gotoxy(10,14); printf("\* 5. Modify record\n"); /*更改*/ gotoxy(10,15); printf("\* 6. Insert record\n"); /*插入*/ gotoxy(10,16); printf("\* 7. Sort record\n"); /*整理*/ gotoxy(10,17); printf("\* 8. Save record\n"); /*保存*/ gotoxy(10,18); printf("\* 0 Quit system\n"); /*退出*/ gotoxy(10,19); printf(" ************ \n"); /*cprintf()送格式话输出至文本窗口屏幕中*/ } /*格式化输出表头*/ void printheader() { printf(HEADER1); printf(HEADER2); printf(HEADER3); } /*格式化输出表中数据*/ void printdata(RECORD q) { RECORD *p; p=&q; printf(FORMAT,DATA); } void Disp( RECORD temp[],int n) /*显示数组temp[]中存储的通讯记录,内容为record结构中定义的内容*/ { int i; if(n==0) /*表示没有通讯记录*/ { printf("\n=>No menu record!\n"); getchar(); return ; } printf("\n\n"); printheader(); /*输出表格头部*/ i=0; while(i<n) /*逐条输出数组中存储的通讯记录*/ { printdata(temp[i]); i++; printf(HEADER3); } getchar(); } void Wrong() /*输出按键错误信息*/ { printf("\n\n\n\n\n**********Error:input has wrong! press any key to continue***********\n"); getchar(); } void Nofind() /*输出未查找到此记录的信息*/ { printf("\n=>Not find this menu record!\n"); } int Locate(RECORD temp[],int n,char findmess[],char nameorphonenum[]) { int i=0; if(strcmp(nameorphonenum,"phonenum")==0) /*按电话号码查询*/ { while(i<n) { if(strcmp(temp[i].phonenum,findmess)==0) /*若找到findmess值的电话号码*/ return i; i++; } } else if(strcmp(nameorphonenum,"name")==0) /*按姓名查询*/ { while(i<n) { if(strcmp(temp[i].name,findmess)==0) /*若找到findmess值的姓名*/ return i; i++; } } return -1; /*若未找到,返回一个整数-1*/ } void stringinput(char *t,int lens,char *notice) { char n[255]; do { printf(notice); /*显示提示信息*/ scanf("%s",n); /*输入字符串*/ if(strlen(n)>lens) printf("\n Exceed the required length! \n"); /*进行长度检测,超过lens值重新输入*/ } while(strlen(n)>lens); strcpy(t,n); /*将输入发字符串拷贝到字符串t中*/ } int Add(RECORD temp[],int n) /*增加通讯记录*/ { char ch,num[10]; int i,flag=0; system("cls"); Disp(temp,n); /*先打印出已有的通讯录信息*/ while(1) /*一次可输入多条记录,直至输入编号为0的记录才结束添加操作*/ { while(1) /*输入记录编号,保证该编号没有被使用,若输入编号为0,则退出添加记录操作*/ { stringinput(num,10,"Input number(press '0' return menu):"); /*格式化输入编号并检验*/ flag=0; if(strcmp(num,"0")==0) /*输入为0,则退出添加操作,返回主界面*/ { return n; } i=0; while(i<n) /*产寻该编号是否已经存在,若存在则要求重新输入一个未被占用的编号*/ { if(strcmp(temp[i].num,num)==0) { flag=1; break; } i++; } if(flag==1) /*提示拥护是否重新输入*/ { getchar(); printf("==>The number %s is existing,try again?(y/n):",num); scanf("%c",&ch); if(ch=='y'||ch=='Y') continue; else return n; } else {break;} } strcpy(temp[n].num,num); /*将字符串num拷贝到temp[n].num中*/ stringinput(temp[n].name,15,"Name:\n"); stringinput(temp[n].phonenum,15,"Telephone:\n"); stringinput(temp[n].address,15,"Address:\n"); saveflag=1; n++; } return n; } void Qur(RECORD temp[],int n) /*按编号或姓名查询通讯记录*/ { int select; /*按1:按姓名查,2:按电话号码查,其他:返回住界面(菜单)*/ char searchinput[20]; /*包寻用户输入的查询内容*/ int p=0; if(n<=0) /*若数组为空*/ { system("cls"); printf("\n=>No menu record!\n"); getchar(); return ; } system("cls"); printf("\n =>1 Search by name =>2 Search by telephonenumber\n"); printf(" Please choice[1,2]:"); scanf("%d",&select); if(select==1) /*按姓名查询*/ { stringinput(searchinput,10,"Input the existing name:"); p=Locate(temp,n,searchinput,"name"); /*在数组temp中查找编号为searchinput值的元素,并返回该数组元素的下标值*/ if(p!=-1) /*若找到该记录*/ { printheader(); printdata(temp[p]); printf(END); printf("Press any key to return"); getchar(); } else Nofind(); getchar(); } else if(select==2) /*按电话号码查询*/ { stringinput(searchinput,15,"Input the existing telephone number:"); p=Locate(temp,n,searchinput,"phonenum"); if(p!=-1) { printheader(); printdata(temp[p]); printf(END); printf("Press any key to return"); getchar(); } else Nofind(); getchar(); } else Wrong(); getchar(); } int Del(RECORD temp[],int n) { int sel; char findmess[20]; int p=0,i=0; if(n<=0) { system("cls"); printf("\n=>No menu record!\n"); getchar(); return n; } system("cls"); Disp(temp,n); printf("\n =>1 Delete by name =>2 Delete by telephonenumber\n"); printf(" Please choice[1,2]:"); scanf("%d",&sel); if(sel==1) { stringinput(findmess,10,"Input the existing name:"); p=Locate(temp,n,findmess,"name"); getchar(); if(p!=-1) { for(i=p+1;i<n;i++) /*删除此记录,后面记录向前移*/ { strcpy(temp[i-1].num,temp[i].num); strcpy(temp[i-1].name,temp[i].name); strcpy(temp[i-1].phonenum,temp[i].phonenum); strcpy(temp[i-1].address,temp[i].address); } printf("\n=>Delete success!\n"); n--; getchar(); saveflag=1; } else Nofind(); getchar(); } else if(sel==2) /*先按电话号码查询到该记录所在的数组元素的下标值*/ { stringinput(findmess,15,"Input the existing telephone number:"); p=Locate(temp,n,findmess,"phonenum"); getchar(); if(p!=-1) { for(i=p+1;i<n;i++) /*删除此记录,后面的记录向前移*/ { strcpy(temp[i-1].num,temp[i].num); strcpy(temp[i-1].name,temp[i].name); strcpy(temp[i-1].phonenum,temp[i].phonenum); strcpy(temp[i-1].address,temp[i].address); } printf("\n=>Delete success!\n"); n--; getchar(); saveflag=1; } else Nofind(); getchar(); } return n; } void Modify(RECORD temp[],int n) { char findmess[20]; int p=0; if(n<=0) { system("cls"); printf("\n=>No menu record!\n"); getchar(); return ; } system("cls"); printf("modify menu book recorder"); Disp(temp,n); stringinput(findmess,10,"Input the existing name:"); /*输入并检验该姓名*/ p=Locate(temp,n,findmess,"name"); /*查询到该数组元素,并返回下标值*/ if(p!=-1) /*若p!=-1,表明已经找到该数组元素*/ { printf("Number:%s,\n",temp[p].num); printf("Name:%s,",temp[p].name); stringinput(temp[p].name,15,"Input new name:"); printf("Name:%s,",temp[p].phonenum); stringinput(temp[p].name,15,"Input new telephone:"); printf("Name:%s,",temp[p].address); stringinput(temp[p].address,30,"Input new address:"); printf("\n=>modify success!\n");getchar(); Disp(temp,n); getchar();saveflag=1; } else { Nofind(); getchar(); } return ; } int Insert(RECORD temp[],int n) { char ch,num[10],s[10]; /*s[]保存插入点位置之前的记录编号,num[]保存输入的新记录的编号*/ RECORD newinfo; int flag=0,i=0,m=0; system("cls"); Disp(temp,n); while(1) { stringinput(s,10,"Please input insert location after the Number:"); flag=0;i=0; while(i<n) /*查询该编号是否存在,flag=1表示该编号存在*/ { if(strcmp(temp[i].num,s)==0) { m=i; flag=1; break; } i++; } if(flag==1) break; /*若编号存在,则进行插之前的新记录输入操作*/ else { getchar(); printf("\n=>The number is not existing,try again?(y\n):",s); scanf("%c",&ch); if(ch=='y'||ch=='Y') { continue; } else { return n; } } } /*以下新记录的输入操作与Add()相同*/ while(1) { stringinput(num,10,"Input new Number:"); flag=0;i=0; while(i<n) /*查询该编号是否存在,flag=1表示该编号存在*/ { if(strcmp(temp[i].num,num)==0) { flag=1; break; } i++; } if(flag==1) { getchar(); printf("\n=>Sorry,The number %s is existing,try again?(y\n):",num); scanf("%c",&ch); if(ch=='y'||ch=='Y') { continue; } else { return n; } } else break; } strcpy(newinfo.num,num); /*将字符串num拷贝到newinfo.num中*/ stringinput(newinfo.name,15,"Name:"); stringinput(newinfo.phonenum,15,"Telephone:"); stringinput(newinfo.address,15,"Address:"); saveflag=1; /*在main()中有对该全局变量的判断,若为1,则进行存盘操作*/ for(i=n-1;i>m;i--) /*从最后一个组织元素开始往前移一个元素位置*/ { strcpy(temp[i+1].num,temp[i].num); strcpy(temp[i+1].name,temp[i].name); strcpy(temp[i+1].phonenum,temp[i].phonenum); strcpy(temp[i+1].address,temp[i].address); } strcpy(temp[m+1].num,newinfo.num); strcpy(temp[m+1].name,newinfo.name); strcpy(temp[m+1].phonenum,newinfo.phonenum); strcpy(temp[m+1].address,newinfo.address); n++; Disp(temp,n); printf("\n\n");getchar(); return n; } void SelectSort(RECORD temp[],int n) { int i=0,j=0,flag=0,indexmin,select; char charflag[10]; RECORD newinfo; if(n<=0) { system("cls"); printf("\n=>Not record!\n"); getchar(); return ; } system("cls"); Disp(temp,n); /*显示排序前的所有记录*/ printf("\n =>1 SORT by num =>2 SORT by another way \n"); printf(" Please choice[1,2]:"); scanf("%d",&select); if(select==1) /*按记录编号排序*/ { for(i=0;i<n-1;i++) { flag=32767; indexmin=0; for(j=i;j<n;j++) { if(atoi(temp[j].num)<flag) { flag=atoi(temp[j].num); indexmin=j; } } strcpy(newinfo.num,temp[i].num); /*利用结构变量nesinfo实现数组元素的交换*/ strcpy(newinfo.name,temp[i].name); strcpy(newinfo.phonenum,temp[i].phonenum); strcpy(newinfo.address,temp[i].address); strcpy(temp[i].num,temp[indexmin].num); strcpy(temp[i].name,temp[indexmin].name); strcpy(temp[i].phonenum,temp[indexmin].phonenum); strcpy(temp[i].address,temp[indexmin].address); strcpy(temp[indexmin].num,newinfo.num); strcpy(temp[indexmin].name,newinfo.name); strcpy(temp[indexmin].phonenum,newinfo.phonenum); strcpy(temp[indexmin].address,newinfo.address); } Disp(temp,n); /*显示排序后的所有记录*/ saveflag=1; printf("\n=>Sort complete!\n");getchar(); return; } else if(select==2) { for(i=0;i<n-1;i++) { charflag[0]=255; indexmin=0; strcpy(newinfo.num,temp[i].num); /*利用结构变量nesinfo实现数组元素的交换*/ strcpy(newinfo.name,temp[i].name); strcpy(newinfo.phonenum,temp[i].phonenum); strcpy(newinfo.address,temp[i].address); strcpy(temp[i].num,temp[indexmin].num); strcpy(temp[i].name,temp[indexmin].name); strcpy(temp[i].phonenum,temp[indexmin].phonenum); strcpy(temp[i].address,temp[indexmin].address); strcpy(temp[indexmin].num,newinfo.num); strcpy(temp[indexmin].name,newinfo.name); strcpy(temp[indexmin].phonenum,newinfo.phonenum); strcpy(temp[indexmin].address,newinfo.address); } Disp(temp,n); /*显示排序后的所有记录*/ saveflag=1; printf("\n=>Sort complete!\n");getchar(); return; } else { Wrong(); getchar(); getchar(); return; } } void Save(RECORD temp[],int n) { int i=0; FILE *fp; fp=fopen("c:\\record.txt","w"); /*以只写方式打开文本文件*/ if(fp==NULL) /*打开文件失败*/ { printf("\n=>Open file error!\n"); getchar(); return; } for(i=0;i<n;i++) { if(fwrite(&temp[i],sizeof(RECORD),1,fp)==1) /*每次写一条记录或一个结构数组元素至文件*/ { continue; } else { break; } } if(i>0) { getchar(); printf("\n\n=>Save file complete,total saved's record number is:%d\n",i); getchar(); saveflag=0; } else { system("cls"); printf("The current link is empty,no menu record is saved!\n"); getchar(); } fclose(fp); /*关闭此文件*/ }
评论 36
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

鹿九丸

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

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

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

打赏作者

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

抵扣说明:

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

余额充值