用c语言实现一个通信录


这个题目要求我们实现一个通讯录,该通讯录要满足以下功能(全部使用c语言知识):

1、添加联系人(姓名,性别,年龄,电话,地址);

2、删除联系人(按名字);

3、查找(按名字);

4、修改(所有属性);

5、浏览所有联系人;

6、清空联系人列表;

7、排序(按名字);

8、其容量为动态增长的,即:当通讯录已满的情况下,在你进行添加时,它会动态增长。

注意:上述某些功能还可以更为完善,比如可以按其它属性进行删查排序。

除此之外:我们知道通讯录最重要也是最主要的功能就是对信息的保存,所以这就要求我们使用文件操作,即:在每次关闭的时候将本次的所有输入保存到文件,而在每次打开时将上次关闭前保存的内容读取到通讯录。


我们先给出通讯录的完整代码,然后对其部分逻辑进行简要分析。

注意:c语言中,写大的工程时,一般将头文件、函数实现、和main函数写到不同的源文件中,这样能使结构更加清晰,也方便其它操作。


头文件部分

contact.h

//条件编译
#ifndef __CONTACT_H__
#define __CONTACT_H__

//头文件列表
#include <stdio.h>
#include <windows.h>
#include <assert.h>
#include <string.h>

//忽略警告
#pragma warning(disable:4996)

//宏
#define INITCAP 128//初始化长度
#define INCREMENT 32//自增长度
#define FILE_NAME "contact_back"//打开文件名

//声明:
//联系人结构体
typedef struct person{
	char name[32];//姓名 性别 年龄 电话 地址
	char sex[8];
	unsigned char age;
	char phone[16];
	char adds[64];
}person_t, *person_p, **person_pp;

//通讯录结构体
typedef struct contact{
	int cap;//最大长度
	int size;//当前长度
	person_p contactList;//联系人列表
}contact_t, *contact_p, **contact_pp;

//函数声明
void initContact(contact_pp c);//初始化通讯录
void addContact(contact_p c, person_p p);//添加联系人
void showContact(contact_p c);//打印联系人列表
void delContact(contact_p c, char *del_name);//删除
void emptyContact(contact_p c);//清空
void destroyContact(contact_p c);//摧毁通讯录
int  searchContact(contact_p c, char *search_name);//查找
void sortContact(contact_p c);//排序
void modContact(contact_p c);//修改
void helpContact();//帮助
void exitContact(contact_p c);//退出
int  isContactEmpty(contact_p c);//判空
int fileLoad(contact_p c);//下载到项目
int fileStore(contact_p c);//储存到文件

#endif __CONTACT_H__ 


主函数

main.c

#include "contact.h"

//菜单
static void meun(){
	printf("\n");
	printf("Welcome...\n");
	printf("-----------------------------------  CONTACTS  --------------------------------\n");
	printf("--           1.Add                                2.Delect                   --\n");
	printf("--           3.Search                             4.Edit                     --\n");
	printf("--           5.Show                               6.Empty                    --\n");
	printf("--           7.Sort                               8.Help                     --\n");
	printf("--           0.Exit                                                          --\n");
	printf("--           作者qq:248620932,ID:果冻,欢迎交流... =_=                     --\n");
	printf("-------------------------------------------------------------------------------\n");
	printf("\n");
}

//添加
static void myAdd(contact_p c){
	person_t p;

	assert(c);

	printf("Please input information<name,sex,age,phone,addr>:\n");
	scanf("%s %s %d %s %s", p.name, p.sex, &p.age, p.phone, p.adds);
	addContact(c, &p);
}

//删除
static void myDel(contact_p c){
	char del_name[32];
	int n = 0;
	assert(c);

	if(isContactEmpty(c)){
		printf("Contact is empty!\n");
		return ;
	}

	printf("Please input the name whicth you want delect:");
	scanf("%s", del_name);
	printf("\nAre you sure delect: %s ?\n", del_name);
	while(1)
	{
		printf("----------------\n");
		printf("| 1.YES | 2.NO |\n");
		printf("----------------\n");

		scanf("%d", &n);
		if( 1 == n)
		{
			delContact(c, del_name);
			return ;
		}
		else if( 2 == n )
		{
			return;
		}
		else
		{
			printf("Error ! \n");
		}
	}
	
}

//查找
static void mySearch(contact_p c)
{
	char search_name[32];
	int pos = 0;
	int i = 0;

	assert(c);

	if(isContactEmpty(c)){
		printf("Contact is empty!\n");
		return ;
	}

	printf("Please input rhe name whicth you want to search:");
	scanf("%s", search_name);
	pos = searchContact(c, search_name);
	if(-1 == pos){
		printf("Not find!\n");
	}
	else{

		printf("------------------------------------------------------------------------------\n");
		printf("| name      | sex  | age | phone           | adds                            |\n");
		printf("| %-10s| %-5s| %-4d| %-16s| %-32s|\n",c->contactList[i].name, \
		c->contactList[i].sex,c->contactList[i].age, \
		c->contactList[i].phone,c->contactList[i].adds);
		printf("------------------------------------------------------------------------------\n");
	}
}

int main()
{
	int s = -1;//选择控制变量
	contact_p myContact = NULL;//声明通讯录
	system("color 2");
	initContact(&myContact);//初始化
	while(1){ 
		meun();
		printf("Please select<0~7>:");
		fflush(stdin);
		scanf("%d", &s);
		switch(s){
		case 1:system("cls");
			myAdd(myContact);//添加联系人
			system("pause");
			break;
		case 2:system("cls");
			myDel(myContact);//删除联系人
			system("pause");
			break;
		case 3:system("cls");
			mySearch(myContact);//查找并打印联系人
			system("pause");
			break;
		case 4:system("cls");
			modContact(myContact);//修改联系人
			system("pause");
			break;
		case 5:system("cls");
			showContact(myContact);//显示联系人列表
			system("pause");
			break;
		case 6:system("cls");
			emptyContact(myContact);//清空通讯录
			system("pause");
			break;
		case 7:system("cls");
			sortContact(myContact);//排序通讯录
			system("pause");
			break;
		case 8:system("cls");
			helpContact();//帮助
			system("pause");
			break;
		case 0:system("cls");
			exitContact(myContact);//退出
			break;
		default:printf("ERROR SELECTION !!!\n");//错误选择
			system("pause");
			break;
		}
		system("cls");//清屏
	}

	return 0;
}


函数实现部分

contact.c

#include "contact.h"

//判空
//空:1
//不空:0
int isContactEmpty(contact_p c)
{
	assert(c);

	return c->size == 0 ? 1 : 0;
}

//初始化
void initContact(contact_pp c)
{
	assert(c);

	//申请通讯录空间
	*c = (contact_p)malloc(sizeof(contact_t));
	if(NULL == *c){
		perror("malloc");
		exit(1);
	}

	//申请成员空间
	(*c)->contactList = (person_p)malloc(sizeof(person_t)*INITCAP);
	if(NULL == (*c)->contactList){
		perror("malloc");
		exit(2);
	}

	//初始化长度和容量
	(*c)->cap = INITCAP;
	(*c)->size = 0;

	fileLoad(*c);
}

//从文件读取通讯录信息
int fileLoad(contact_p c)
{
	FILE *fp;
	person_t p;
	int i = 0;

	assert(c);

	//打开文件
	fp = fopen(FILE_NAME,"rb");
	if(NULL == fp){
		perror("fopen");
		return -2;
	}

	while(1){
		//读取到p
		fread(&p, sizeof(person_t), 1, fp);
		if(0 != feof(fp)){
			break;
		}
		//将读取的添加到通讯录
		addContact(c, &p);
	}
	fclose(fp);

	return 0;
}


//判满
//满:1 
//未满:0
static int isContactFull(contact_p c)
{
	assert(c);

	return c->size >= c-> cap ? 1 : 0;
}


//自增
static int incContact(contact_p c)
{
	person_p new_c = NULL;

	assert(c);

	//申请新空间
	new_c = (person_p)realloc(c->contactList, (c->cap+INCREMENT)*sizeof(person_t));
	if(NULL == new_c){
		perror("realloc");
		return 0;
	}
	
	//将新空间分配给旧空间
	c->contactList = new_c;
	c->cap += INCREMENT;
	printf("Is full, increse success!\n");
	return 1;
}

//添加联系人
void addContact(contact_p c, person_p p)
{
	assert(c);
	assert(p);

	//如果不空直接添加,如果空就先自增再添加
	if(!isContactFull(c) || incContact(c)){
		c->contactList[c->size] = *p;
		c->size++;
	}
}

//查找
//是空的:打印空
//没找到:返回 -1
//找到:返回下标
int searchContact(contact_p c, char *search_name)
{
	int i = 0;

	assert(c);
	assert(search_name);

	//通讯录是空的
	if(isContactEmpty(c)){
		printf("Contact is empty!\n");
	}

	for(i = 0; i < c->size; i++){
		if( 0 == strcmp(c->contactList[i].name, search_name) ){
			break;
		}
	}

	//没找到
	if(i == c->size)
	{
		return -1;
	}

	//找到返回下标
	return i;


}


//按名字排序
void sortContact(contact_p c)
{
	int i = 0;
	int j = 0;
	int pos = 0;
	person_t temp;

	assert(c);

	//是空的就不用排
	if(isContactEmpty(c)){
		printf("Contact is empty!\n");
		return ;
	}

	//不空用冒泡法按名字排序
	for(i = c->size-1; i>0; i--){
		for(j = 0; j<i; j++){
			if(1 == strcmp(c->contactList[j].name, c->contactList[j+1].name)){
				temp = c->contactList[j];
				c->contactList[j] = c->contactList[j+1];
				c->contactList[j+1] = temp;
				pos = 1;
			}
		}
		if(0 == pos)
		{

			break;
		}
	}

	printf("Done...\n");
}

//修改联系人
void modContact(contact_p c)
{
	char name[32];
	int i = 0;
	char key_mod[8];

	assert(c);


	if(isContactEmpty(c)){
		printf("Contact is empty!\n");
		return ;
	}

	//输入要修改的人的名字
	printf("Please input the name whicth you want to modify:");
	scanf("%s", name);

	//查找要修改人的下标
	i = searchContact(c, name);
	if(-1 == i)
	{
		printf("Not find!\n");
		return ;
	}

	//打印信息
	printf("------------------------------------------------------------------------------\n");
	printf("| name      | sex  | age | phone           | adds                            |\n");
	printf("| %-10s| %-5s| %-4d| %-16s| %-32s|\n",c->contactList[i].name, \
	c->contactList[i].sex,c->contactList[i].age, \
	c->contactList[i].phone,c->contactList[i].adds);
	printf("------------------------------------------------------------------------------\n");

	//输入要修改的关键字
	printf("Please input the infor whicth you want to modify:");
	fflush(stdin);
	scanf("%s", key_mod);
	
	//寻找要修改的关键字

	//如果要修改名字
	if(0 == strcmp("name", key_mod)){
		printf("Please input new name:");
		fflush(stdin);//注意要清空输入缓冲区
		scanf("%s", c->contactList[i].name);
		printf("Done...\n");
		return ;
	}

	//如果要修改性别
	if(0 == strcmp("sex", key_mod)){
		printf("Please input new sex:");
		fflush(stdin);
		scanf("%s", c->contactList[i].sex);
		printf("Done...\n");
		return ;
	}

	//如果要修改年龄
	if(0 == strcmp("age", key_mod)){
		printf("Please input new age:");
		fflush(stdin);
		scanf("%d", &c->contactList[i].age);
		printf("Done...\n");
		return ;
	}

	//如果要修改电话号码
	if(0 == strcmp("phone", key_mod)){
		printf("Please input new phone:");
		fflush(stdin);
		scanf("%s", c->contactList[i].phone);
		printf("Done...\n");
		return ;
	}

	//如果要修改地址
	if(0 == strcmp("adds", key_mod)){
		printf("Please input new adds:");
		fflush(stdin);
		scanf("%s", c->contactList[i].adds);
		printf("Done...\n");
		return ;
	}
	
	//没有找到要修改的关键字
	printf("ERROR!!\n");
}

//删除
void delContact(contact_p c, char *del_name)
{
	int i = 0;
	int j = 0;
	assert(c);
	
	i = searchContact(c, del_name);
	if(-1 == i)
	{
		printf("Not find!\n");
		return ;
	}
	
	//将后面的成员前移
	for(j = i;j<c->size; j++){
		c->contactList[j] = c->contactList[j+1];
	}

	c->size--;
	printf("Done...\n");
}

//清空通讯录
void emptyContact(contact_p c)
{
	assert(c);

	//直接将当前大小置0
	c->size = 0;
	printf("Done...\n");
}

//打印信息
void showContact(contact_p c)
{
	int i = 0;

	assert(c);

	if(isContactEmpty(c)){
		printf("Contact is empty!\n");
		return ;
	}

	printf("\ntotal:%d\n", c->size);//打印总人数

	//打印详细信息
	printf("------------------------------- contacts -------------------------------------\n");
	printf("| name      | sex  | age | phone           | adds                            |\n");
	printf("------------------------------------------------------------------------------\n");
	for(; i < c->size; i++){
		printf("| %-10s| %-5s| %-4d| %-16s| %-32s|\n",c->contactList[i].name, \
		c->contactList[i].sex,c->contactList[i].age, \
		c->contactList[i].phone,c->contactList[i].adds);
	}
	printf("------------------------------------------------------------------------------\n\n");
}
 
//帮助(使用手册)
void helpContact()
{
	printf("\n");
	printf("-----------------------------------  HELP  -----------------------------------\n");
	printf("| You could use this app store up some information about your friends.       |\n");
	printf("| 1、you can add information by choose ( 1 ).                                |\n");
	printf("| 2、you can delect someone by choose ( 2 ).                                 |\n");
	printf("| 3、you can search someone by choose ( 3 ).                                 |\n");
	printf("| 4、you can change some's information by choose ( 4 ).                      |\n");
	printf("| 5、you can show information list by choose ( 5 ).                          |\n");
	printf("| 6、you can empty all information by choose ( 6 ).                          |\n");
	printf("| 7、you can sort people by choose ( 7 ).                                    |\n");
	printf("------------------------------------------------------------------------------\n\n");
}



//储存到文件
int fileStore(contact_p c)
{
	FILE *fp;
	int i = 0;

	assert(c);

	//打开文件
	fp = fopen(FILE_NAME,"wb");
	if(NULL == fp){
		perror("fopen");
		return -1;
	}

	//一次储存一个人大小的内容
	for(; i<c->size; i++){
		fwrite(c->contactList+i, sizeof(person_t), 1, fp);
	}

	fclose(fp);

	return 0;
}

//摧毁通讯录
void destroyContact(contact_p c)
{
	assert(c);

	fileStore(c);//写入到文件
	free(c->contactList);//释放联系人列表
	c->contactList = NULL;
	free(c);//释放整体
	c = NULL;
}

//退出
void exitContact(contact_p c)
{
	int n = 0;
	printf("\nAre you sure quit ?\n");
	while(1)
	{
		printf("----------------\n");
		printf("| 1.YES | 2.NO |\n");
		printf("----------------\n");

		scanf("%d", &n);
		if( 1 == n)
		{
			destroyContact(c);
			exit(0);
		}
		else if( 2 == n )
		{
			return;
		}
		else
		{
			printf("Error ! \n");
		}
	}
	
}


以下对部分代码做简要分析:


在头文件中我们应该有一个表示联系人的结构体,如下所示:

//联系人结构体
typedef struct person{
	char name[32];//姓名 性别 年龄 电话 地址
	char sex[8];
	unsigned char age;
	char phone[16];
	char adds[64];
}person_t, *person_p, **person_pp;
注意:我们给他typedef了三个名字,分别是结构体类型、结构体一级指针、结构体二级指针,定义指针的目的是在后面声明时避免写更多的 * 


其次我们应该有一个通讯录的结构体,它里面应该保存联系人列表,当前长度以及容量,如下所示:

//通讯录结构体
typedef struct contact{
	int cap;//容量
	int size;//当前长度
	person_p contactList;//联系人列表
}contact_t, *contact_p, **contact_pp;



在初始化传参时需要注意的问题:

void initContact(contact_pp c)
{
	assert(c);

	//申请通讯录空间
	*c = (contact_p)malloc(sizeof(contact_t));
	if(NULL == *c){
		perror("malloc");
		exit(1);
	}

	//申请成员空间
	(*c)->contactList = (person_p)malloc(sizeof(person_t)*INITCAP);
	if(NULL == (*c)->contactList){
		perror("malloc");
		exit(2);
	}

	//初始化长度和容量
	(*c)->cap = INITCAP;
	(*c)->size = 0;

	fileLoad(*c);
}

注意初始化传参时一定要使用二级指针,原因是:malloc返回一个指向所申请到的空间的指针,若使用一级指针传参,则申请到的空间将给形参,该形参在该函数结束时会释放,所以申请到的空间也将丢失,更重要的是,malloc申请到的空间需用free释放,然而你所申请到的空间已经丢失,也就没法释放了,这会造成严重的内存泄漏问题,在一个较大的工程中出现这样的问题是极其严重的,在你不知情的情况下,该程序一直吃你的内存,造成不可预知的后果。使用二级指针可以避免这样的问题,原因是:二级指针保存的是你一级指针的地址,通过二级指针我们可以访问到一级指针所指向的那片空间,这就类似于我们之前在交换两个数的内容时,使用一级指针(要交换的两个数的指针)传参一样。

文件操作——从文件读取信息

//从文件读取通讯录信息
int fileLoad(contact_p c)
{
	FILE *fp;
	person_t p;
	int i = 0;

	assert(c);

	//打开文件
	fp = fopen(FILE_NAME,"rb");
	if(NULL == fp){
		perror("fopen");
		return -2;
	}

	while(1){
		//读取到p
		fread(&p, sizeof(person_t), 1, fp);
		if(0 != feof(fp)){
			break;
		}
		//将读取的添加到通讯录
		addContact(c, &p);
	}
	fclose(fp);

	return 0;
}

文件操作——将信息写入文件

//写入到文件
int fileStore(contact_p c)
{
	FILE *fp;
	int i = 0;

	assert(c);

	//打开文件
	fp = fopen(FILE_NAME,"wb");
	if(NULL == fp){
		perror("fopen");
		return -1;
	}

	//一次储存一个人大小的内容
	for(; i<c->size; i++){
		fwrite(c->contactList+i, sizeof(person_t), 1, fp);
	}

	fclose(fp);

	return 0;
}

注意:几个文件操作函数,下面给出它的原型:

FILE *fopen( const char *filename, const char *mode );

filename为将要打开的文件的名字,mode为打开方式,“rb”:以二进制只读方式打开, “rw”:以二进制只写方式打开,它返回打开文件的地址。


size_t fwrite( const void *buffer, size_t size, size_tcount, FILE *stream );

buffer为被写入的内容,size为被写入信息的大小,count为写入信息的个数,stream为写入的文件,即该函数将buffer中的内容以size大小为单位,每次写入count个,写到stream中;


size_t fread( void *buffer, size_t size, size_t count, FILE *stream );

该函数与fwrite函数类似;


int feof( FILE *stream );

该函数从stream中读取内容,若读取到文件结尾,则返回一个非零值,否则返回0;


int fclose( FILE *stream );

关闭stream文件(流);


通讯录在每次初始化完成后读取文件中的信息,每次释放通讯录前,将通讯录中的信息写到文件中,这样就完成了对联系人的保存。


总结:该通讯录使用c语言中基础的循环结构、选择结构,数组等知识,如:if()else; for(;;)switch()case  :

还有结构体、内存管理、指针、文件操作等知识。


该通讯录是实现中肯定存在错误或者不完美的地方,欢迎大家讨论交流。  >_<


成于坚持,败于止步!


【作者:果冻 http://blog.csdn.net/jelly_9

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值