C语言程序设计:可存储的通讯录

前言:本章没有使用链表!

C语言从入门到精通(鹏哥带你C语言从入门到精通,谭浩强C语言教程C语言程序设计C语言修仙C语言考研计算机二级专升本C语言期末突软考二级C语言考研C语言C语言)_哔哩哔哩_bilibili

本文很长,看不懂可以去B站看鹏哥的,讲的非常好,但细节需要自己完善,加油💪💪

通讯录的每个联系人是由

名字、性别、年龄、电话、住址等等

再由每个联系人组成一张列表完成通讯录

注:文中都是拆分的,文尾才是源代码!!

一、基本框架

完成框架:

因为要多次操作,所以需要循环控制操作方法

通讯录的操作方法有很多(增删查改最基础)

1.增加 2.删除 3.查找 4.修改 5.排序 6.打印

所以在头文件中用枚举常量很合适,因为枚举常量可以对应输入数值

 然后就是主函数的框架部分

void menu()
{
	//菜单
	printf("*****************************\n");
	printf("****      通讯录v1.0    ****\n");
	printf("****   1.增加   2.删除   ****\n");
	printf("****   3.查找   4.修改   ****\n");
	printf("****   5.排序   6.打印   ****\n");
	printf("****        0.退出       ****\n");
	printf("*****************************\n");
}

int main()
{
	int input = 0;
	do
	{
		menu();					//菜单
		printf("请输入:>");
		scanf("%d", &input);
        getchar();				//吸收换行(\n)
		switch (input)
		{
		case Add:				//增加
			printf("增加\n");
			break;
		case Del:				//删除
			printf("删除\n");
			break;
		case Find:				//...
			printf("查找\n");
			break;
		case Change:
			printf("修改\n");
			break;
		case Sort:
			printf("排序\n");
			break;
		case Print:
			printf("打印\n");
			break;
		case Exit:
			printf("退出\n");
			break;
		default:
			printf("输入错误\n");
			break;
		}
	} while (input);
}

完成主要框架后,可以进行封装函数了

首先建立联系人的结构体,方便寻找成员,然后枚举几个最大值方便以后维护

然后建立通讯录结构体来存储联系人联系人个数

因为我不知道你有多少个联系人,所以采用动态开辟内存

来构造通讯录所占空间,因此通讯录中还需要存储一个变量

来确定当前通讯录的容量以便于扩容

(1) 封装第一个函数:初始化通讯录(记得在头文件声明)

因为要动态开辟内存,所以首先需要初始化通讯录函数来进行开辟空间

记得引用 <string.h>头文件

然后就可以声明通讯录并且初始化了。。

 (2)封装增加联系人函数

因为是动态开辟内存,所以可能会存满需要扩容的情况,所以

先把编写扩容函数,用于判断是否需要扩容的情况,再考虑增加

联系人。realloc 函数可以重新开辟一块空间并且可以将原空间的值

拷贝到新开辟的空间,然后释放原空间,所以重新开辟空间用这个很合适。

 接着封装增加联系人,增加一个继续增加的判断条件,这一部分整体还是很简单的。

 (3)封装打印函数

有了增加方法,那就把打印函数写出来,就可以进行查看是否写入成功

 尝试输入一个联系人

 尝试输入四个联系人

 看来,开辟空间成功了但是这个通讯录的格式很丑,全是右对齐的,

所以我全给搞成左对齐了(其实就是把"%20s"改成"%-20s")

 (4)封装删除联系人函数

删除联系人,首先你得有联系人,所以需要判断通讯录是否还有联系人

然后你还得找到你想删掉的联系人,然后将他删掉。

我加了一个判断防止不小心按到的情况。

因为需要找到联系人,但是后边修改、查找都需要寻找联系人

所以封装一个寻找联系人的函数,返回值为该联系人的下标

接着封装删除联系人函数

//删除联系人
void DeleteData(list* pc)
{
	if (pc->sz == 0)						//当通讯录没有任何联系人时,直接返回
	{
		printf("还没有联系人呢!\n");
		return;
	}
	
	char check = 0;							//判断是否误操作
	printf("确定要进行删除操作吗(N取消):>");
	scanf("%c", &check);
	CheckCapcity(pc);
	if (check != 'n' && check != 'N')
	{
		char name[MAX_NAME] = { 0 };		//获得删除的人名
		printf("请输入要删除的联系人:>");
		scanf("%s", name);
		int pos = FindContact(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--;								//让最后一位联系人不能访问
		printf("删除成功\n");
	}
	else
	{
		printf("取消删除\n");
		return;
	}

}

这是目前的通讯录,现在要把“我是例外”删除 看看能不能成功

删除成功了,那试试能不能删除“王五”,毕竟通讯录里可没有王五 

 可行!

 (5)封装查找联系人函数

查找函数前面写了,那直接找到并打印出来即可(这个最简单)

因为前面都写过了,复制过来稍微修改即可

 这是当前通讯录的人员,我现在想找到“2”,就试试

可以找到,那看看能不能找到“4”

 

看来出了一点点小问题 ,但问题不大,修改后继续。。

(6)封装修改联系人函数

要修改联系人前需要先找到要修改的联系人,然后再选择修改方式

再进行修改

//修改联系人
void ChangeData(list* pc)
{
	char check = 0;
	printf("确定要修改联系人吗(N取消):>");
	scanf("%c", &check);
	if (check == 'n' || check == 'N')
	{
		printf("取消修改\n");
		return;
	}

	//寻找联系人
	char name[MAX_NAME] = { 0 };
	printf("请输入要修改的联系人名字:>");
	scanf("%s", name);
	int pos = FindContact(pc, name);
	if (pos == -1)
	{
		printf("通讯录中没有这位\n");
		return;
	}
	//修改联系人
	int ch = 0;		//修改标志位
	printf("请输入修改类别:1.姓名 2.性别 3.年龄 4.电话 5.地址:>");
	scanf("%d", &ch);
	if (ch == 1)
	{
		printf("请输入修改后的姓名:>");
		scanf("%s", pc->data[pos].name);
	}
	else if (ch == 2)
	{
		printf("请输入修改后的性别:>");
		scanf("%s", pc->data[pos].sex);
	}
	else if (ch == 3)
	{
		printf("请输入修改后的年龄:>");
		scanf("%d",&(pc->data[pos].age));		//注意 取地址(&)
	}
	else if (ch == 4)
	{
		printf("请输入修改后的电话:>");
		scanf("%s", pc->data[pos].phone);
	}
	else if (ch == 5)
	{
		printf("请输入修改后的地址:>");
		scanf("%s", pc->data[pos].address);
	}
	else
	{
		printf("输入错误!\n");
		return;
	}
	printf("修改成功\n");

}

试试行不行

 不小心把张三性别写成女了,看看能不能修改

 看来可以修改

(7)封装排序联系人函数

排序可以按照名字排序,也可以按照性别排序,也可以按照年龄排序

也可以按照电话排序,和按照地址排序。

但这有点多(我懒),所以借助<stdlib.h>头文件中的qsort函数来排序吧

 选自:C 库函数 – qsort() | 菜鸟教程 (runoob.com)

 其中重要的就是compar(两个元素间的比较函数),其实就是用一个函数

传两个参数,返回他们的差值,观察差值是大于零还是等于零或者小于零

选择:qsort - C++ Reference (cplusplus.com) 

所以我们需要先写出5种不同的函数指针,用于比较不同的结构体成员

接着封装排序联系人函数

看看能不能行

目前通讯录,接着按名字排序

 可以看到李四跑上去了,因为strcmp是根据首字母的ASCII码值排序的。

李四的拼音首字母是“l”,王五的拼音首字母是“w”,l是小于w的,所以李四在上面

接着按性别排序

 可以看到李四跑到底下去了,是因为男的拼音首字母 “n” 是小于女的拼音首字母也是“n”

所以比较第二个字母nan中的“a”、nv中的“v”,显然a小于v

所以李四在后面。接着排序年龄

 比较整形就没什么可以说的了,那个小,那个在前面

接着比较电话

 注意不要把电话当作整形,这里设置的是字符串,所以还是按照strcmp的比较方式比较。

接着比较地址

还是按照strcmp的比较方式比较 。

到此基本完成了通讯录,剩下一些细节修修补补

比如删除联系人到多少的时候,重新开辟空间,节省空间浪费

又比如在修改联系人的时候,提示选中的是那个联系人

或者修饰一下提示语,让它更显眼。

然后。。

就是关闭时保存数据,下次启动时继续对数据操作,这才是通讯录

二、完善框架

(1)维护内存防止浪费

首先在退出程序时,释放动态开辟的内存空间,防止内存泄漏

所以写一个退出通讯录的函数

 然后是删除联系人过多时,重新开辟空间

其实就是把CheckCapcity(扩容函数)函数稍微修改一下

多加一个条件,当容量-数量>8,也就是容量空余了8个,就重新开辟一块 

空间,当然也可以增加一些宏变量方便以后维护

(2)细节修饰

先将要修改的人提示出来然后修饰

先从网上拷一点制表符

/*
┌ ─ ┐

│   │

└ ─ ┘
*/

然后将每一个有取消、没有等提示语句加上,例如

        printf("┌────────┐\n");
		printf("│取消退出│\n");
		printf("└────────┘\n");

        printf("┌───────────────┐\n");
		printf("│还没有联系人呢!│\n");
		printf("└───────────────┘\n");

 (3)退出后保存

现在程序还是运行在内存上,程序退出后,系统就会回收内存空间。

所以想要保存数据,就需要将数据转移到硬盘上去。

所以在要退出前,将数据保存到文件中,在下次初始化时读出来即可。

写入操作

 读取操作

 以下为gif演示

三、代码展示

源代码展示:

1.Contact.h 文件

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once

/******头文件定义*******/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

/******头文件定义*******/

/********全局变量*******/
enum Contact_tem
{
	MAX_NAME = 20,			//最大姓名字符数
	MAX_SEX = 10,			//最大性别字符数
	MAX_PHONE = 15,		//最大电话字符数
	MAX_ADDRESS = 20		//最大地址字符数
};


enum Input
{
	Exit,		//退出 值0
	Add,		//增加 值1
	Del,		//删除 值2
	Find,		//查找 值3
	Change,		//修改 值4
	Sort,		//排序 值5
	Print		//打印 值6
};


/********全局变量*******/

/*******结构体定义*******/
typedef struct Contact
{
	char name[MAX_NAME];		//姓名
	char sex[MAX_SEX];			//性别
	int age;					//年龄
	char phone[MAX_PHONE];		//电话
	char address[MAX_ADDRESS];	//地址
}Contact;

typedef struct PhoneBook
{
	Contact* data;				//联系人
	int sz;						//联系人个数
	int Capcity;				//当前容量
}list;

/*******结构体定义*******/

/*******函数声明********/

//初始化通讯录
void InitData(list* pc);

//增加联系人
void AddData(list* pc);

//打印
void PrintData(list* pc);

//删除联系人
void DeleteData(list* pc);

//查找联系人
void FindData(list* pc);

//修改联系人
void ChangeData(list* pc);

//排序联系人
void SortData(list* pc);

//退出通讯录
void ExitData(list* pc);

//保存数据
void SaveData(list* pc);
/*******函数声明********/






2.Contact.c 文件

#include"Contact.h"

/**************备用函数区****************/

//扩容
void CheckCapcity(list* pc)
{
	Contact* ptr = NULL;						//用于接收重新获得的空间
	if (pc->Capcity == pc->sz)
	{
		ptr = (Contact*)realloc(pc->data,(pc->Capcity + 2) * sizeof(Contact));	//重新开辟空间
		if (ptr == NULL)
		{
			perror("CheckCapcity");				//开辟失败时报错并退出
			return;
		}
		pc->data = ptr;			//没有错误时将新开辟的空间地址赋予pc->data
		pc->Capcity += 2;		//重新计算当前容量
	}
	if (pc->Capcity - pc->sz > 8)				//删除扩容
	{
		ptr = (Contact*)realloc(pc->data, (pc->sz + 2) * sizeof(Contact));		//重新开辟空间为pc->sz+2 个联系人的空间
		if (ptr == NULL)
		{
			perror("CheckCapcity");
			return;
		}
		pc->data = ptr;
		pc->Capcity = pc->sz + 2;			//重新开辟内存容量为pc->sz+2个
	}
	
}

//查找联系人       通讯录      需要寻找的联系人
int FindContact(list* pc, char* str)
{
	for (int i = 0; i < pc->sz; i++)			//遍历通讯录
	{
		if (!(strcmp(pc->data[i].name, str)))	//两个字符串对比使用strcmp函数
		{
			return i;							//存在该联系人返回i
		}
		
	}
	return -1;									//不存在返回-1

}

//结构体排序 -- 姓名
int cmp_by_name(const void* e1, const void* e2)
{
	//void*指针不能解引用操作,所以需要转换成需要的类型才能继续
	return strcmp(((Contact*)e1)->name, ((Contact*)e2)->name);		//字符串的比较方式需要用strcmp函数实现
}
//结构体排序 -- 性别
int cmp_by_sex(const void* e1, const void* e2)
{
	//void*指针不能解引用操作,所以需要转换成需要的类型才能继续
	return strcmp(((Contact*)e1)->sex, ((Contact*)e2)->sex);
}
//结构体排序 -- 年龄
int cmp_by_age(const void* e1, const void* e2)
{
	//void*指针不能解引用操作,所以需要转换成需要的类型才能继续
	return ((Contact*)e1)->age - ((Contact*)e2)->age;		//整形相减即可
}
//结构体排序 -- 电话
int cmp_by_phone(const void* e1, const void* e2)
{
	//void*指针不能解引用操作,所以需要转换成需要的类型才能继续
	return strcmp(((Contact*)e1)->phone, ((Contact*)e2)->phone);
}
//结构体排序 -- 地址
int cmp_by_address(const void* e1, const void* e2)
{
	//void*指针不能解引用操作,所以需要转换成需要的类型才能继续
	return strcmp(((Contact*)e1)->address, ((Contact*)e2)->address);
}



/**************备用函数区****************/

/*
┌ ─ ┐

│   │

└ ─ ┘
*/



/**************主要函数区****************/
//初始化通讯录
void InitData(list* pc)
{
	pc->sz = 0;												//初始化时没有联系人
	pc->Capcity = 3;										//初始容量为3
	pc->data = (Contact*)malloc(sizeof(Contact) * 3);		//开辟一块内存为3个联系人大小的通讯录
	if (pc->data == NULL)									//开辟失败返回并报错
	{
		perror("InitData");
		return;
	}

	FILE* pf = fopen("text.dat", "a+");						//将文件以可读可写的方式打开,若文件不存在,则新建一个文件
	if (pf == NULL)
	{
		perror("fopen");									//当文件打开失败时报错并退出
		return;
	}
	Contact tem = { 0 };									//定义一个变量来变相读取fread的返回值\
	//		  接收变量   变量大小     接收个数  文件流	fread每读取一次就会返回剩下多少个元素
	while (fread(&tem, sizeof(Contact), 1, pf))
	{
		CheckCapcity(pc);									//判断是否需要扩容
		pc->data[pc->sz] = tem;								//将原数据覆盖
		pc->sz++;											//元素个数增加
	}
	fclose(pf);												//关闭文件
}

/*
		printf("┌────────┐\n");
		printf("│取消增加│\n");
		printf("└────────┘\n");
*/


void AddData(list* pc)
{
	char check = 0;							//判断是否继续添加
	printf("确定要添加联系人吗(N取消):>");
	scanf("%c", &check);
	if (check == 'n' || check == 'N')
	{
		//取消添加
		printf("┌────────┐\n");
		printf("│取消增加│\n");
		printf("└────────┘\n");
		return;
	}
	//继续添加
	CheckCapcity(pc);					//判断扩容
	printf("请输入姓名:>");
	scanf("%s", pc->data[pc->sz].name);		//姓名
	printf("请输入性别:>");
	scanf("%s", pc->data[pc->sz].sex);			//性别
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pc->sz].age));		//年龄
	printf("请输入电话:>");
	scanf("%s", pc->data[pc->sz].phone);		//电话
	printf("请输入住址:>");
	scanf("%s", pc->data[pc->sz].address);		//地址
	pc->sz++;
	
}

void PrintData(list* pc)
{
	printf("%-20s %-10s %-6s %-15s %-20s\n", "姓名", "性别", "年龄", "电话", "地址");	//分类
	printf("-------------------------------------------------------------------------\n");
	for (int i = 0; i < pc->sz; i++)
	{
		printf("%-20s %-10s %-6d %-15s %-20s\n",	
			pc->data[i].name,		//姓名
			pc->data[i].sex,		//性别
			pc->data[i].age,		//年龄
			pc->data[i].phone,		//电话
			pc->data[i].address		//地址
		);
		printf("-------------------------------------------------------------------------\n");
	}
}

//删除联系人
void DeleteData(list* pc)
{
	if (pc->sz == 0)						//当通讯录没有任何联系人时,直接返回
	{
		printf("┌───────────────┐\n");
		printf("│还没有联系人呢!│\n");
		printf("└───────────────┘\n");
		return;
	}
	
	char check = 0;							//判断是否误操作
	printf("确定要进行删除操作吗(N取消):>");
	scanf("%c", &check);
	CheckCapcity(pc);
	if (check != 'n' && check != 'N')
	{
		char name[MAX_NAME] = { 0 };		//获得删除的人名
		printf("请输入要删除的联系人:>");
		scanf("%s", name);
		int pos = FindContact(pc, name);	//接收返回值
		if (pos == -1)
		{
			printf("┌──────────────────┐\n");
			printf("│通讯录中没有这位!│\n");	//检查是否存在该联系人
			printf("└──────────────────┘\n");
			return;
		}

		for (int i = pos; i < pc->sz -1; i++)	//最后一位不需要移位,防止越界访问
		{
			pc->data[i] = pc->data[i + 1];		//让后面一位覆盖前面一位
		}
		pc->sz--;								//让最后一位联系人不能访问
		printf("┌────────┐\n");
		printf("│删除成功│\n");
		printf("└────────┘\n");
	}
	else
	{
		printf("┌────────┐\n");
		printf("│取消删除│\n");
		printf("└────────┘\n");
		return;
	}

}

//查找联系人
void FindData(list* pc)
{
	char check = 0;
	printf("确定要查找联系人吗(N取消):>");
	scanf("%c", &check);
	if (check == 'n' || check == 'N')
	{
		printf("┌────────┐\n");
		printf("│取消查找│\n");
		printf("└────────┘\n");
		return;
	}

	//寻找联系人
	char name[MAX_NAME] = { 0 };
	printf("请输入要查找的联系人:>");
	scanf("%s", name);
	int pos = FindContact(pc,name);
	if (pos == -1)
	{
		printf("┌──────────────────┐\n");
		printf("│通讯录中没有这位!│\n");	//检查是否存在该联系人
		printf("└──────────────────┘\n");
		return;
	}
	//打印联系人
	printf("%-20s %-10s %-6s %-15s %-20s\n", "姓名", "性别", "年龄", "电话", "地址");	//分类
	printf("-------------------------------------------------------------------------\n");
	printf("%-20s %-10s %-6d %-15s %-20s\n",
		pc->data[pos].name,		//姓名
		pc->data[pos].sex,		//性别
		pc->data[pos].age,		//年龄
		pc->data[pos].phone,		//电话
		pc->data[pos].address		//地址
	);
	printf("-------------------------------------------------------------------------\n");

}

//修改联系人
void ChangeData(list* pc)
{
	char check = 0;
	printf("确定要修改联系人吗(N取消):>");
	scanf("%c", &check);
	if (check == 'n' || check == 'N')
	{
		printf("┌────────┐\n");
		printf("│取消修改│\n");
		printf("└────────┘\n");
		return;
	}

	//寻找联系人
	char name[MAX_NAME] = { 0 };
	printf("请输入要修改的联系人名字:>");
	scanf("%s", name);
	int pos = FindContact(pc, name);
	if (pos == -1)
	{
		printf("┌──────────────────┐\n");
		printf("│通讯录中没有这位!│\n");	//检查是否存在该联系人
		printf("└──────────────────┘\n");
		return;
	}
	printf("当前选中:  < %s >\n", pc->data[pos].name);
	//修改联系人
	int ch = 0;		//修改标志位
	printf("请输入修改类别:1.姓名 2.性别 3.年龄 4.电话 5.地址:>");
	scanf("%d", &ch);
	if (ch == 1)
	{
		printf("请输入修改后的姓名:>");
		scanf("%s", pc->data[pos].name);
	}
	else if (ch == 2)
	{
		printf("请输入修改后的性别:>");
		scanf("%s", pc->data[pos].sex);
	}
	else if (ch == 3)
	{
		printf("请输入修改后的年龄:>");
		scanf("%d",&(pc->data[pos].age));		//注意 取地址(&)
	}
	else if (ch == 4)
	{
		printf("请输入修改后的电话:>");
		scanf("%s", pc->data[pos].phone);
	}
	else if (ch == 5)
	{
		printf("请输入修改后的地址:>");
		scanf("%s", pc->data[pos].address);
	}
	else
	{
		printf("┌────────┐\n");
		printf("│输入错误│\n");
		printf("└────────┘\n");
		return;
	}
	printf("┌────────┐\n");
	printf("│修改成功│\n");
	printf("└────────┘\n");

}


//排序联系人
void SortData(list* pc)
{
	char check = 0;
	printf("确定要排序吗(N取消):>");
	scanf("%c", &check);
	if (check == 'n' || check == 'N')
	{
		printf("┌────────┐\n");
		printf("│取消排序│\n");
		printf("└────────┘\n");
		return;
	}
	//排序
	//函数指针数组,将每一个函数指针组成数组,有需要请自行百度
	int (*pf[6])(const void*, const void*) =
	{ NULL,cmp_by_name,cmp_by_sex,cmp_by_age,cmp_by_phone,cmp_by_address};
	int tmp = 0;
	printf("请选择排序方式:1.姓名 2.性别 3.年龄 4.电话 5.地址:>");
	scanf("%d", &tmp);

	//    排序位置	元素个数		单个元素字节数			元素对比方式
	qsort(pc->data, pc->sz, sizeof(pc->data[0]), pf[tmp]);	//排序函数

	printf("┌────────┐\n");
	printf("│排序成功│\n");
	printf("└────────┘\n");

}

void ExitData(list* pc)
{
	char check = 0;
	printf("确定要退出吗(N取消):>");
	scanf("%c", &check);
	if (check == 'N' || check == 'n')
	{
		printf("┌────────┐\n");
		printf("│取消退出│\n");
		printf("└────────┘\n");
		return;
	}
	free(pc->data);			//释放内存
	printf("┌────┐\n");
	printf("│退出│\n");
	printf("└────┘\n");

}

//保存数据
void SaveData(list* pc)
{
	FILE* pf = fopen("text.dat", "w");			//以只写的形式打开文件,如果文件不存在,创建一个新的文件
	if (pf == NULL)
	{
		perror("fopen");						//打开失败时报错
		return;
	}
	//		写入数据		单个数据大小	  写入多少	文件流
	fwrite(pc->data, sizeof(Contact), pc->sz, pf);


	fclose(pf);									//关闭文件
}
/**************主要函数区****************/



3.text.c 文件

#include"Contact.h"

void menu()
{
	//菜单
	printf("*****************************\n");
	printf("****      通讯录v1.0    ****\n");
	printf("****   1.增加   2.删除   ****\n");
	printf("****   3.查找   4.修改   ****\n");
	printf("****   5.排序   6.打印   ****\n");
	printf("****        0.退出       ****\n");
	printf("*****************************\n");
}

int main()
{
	int input = 0;
	list con;			//定义通讯录
	InitData(&con);		//初始化通讯录
	do
	{
		menu();					//菜单
		printf("请输入:>");
		scanf("%d", &input);
		getchar();				//吸收换行(\n)
		switch (input)
		{
		case Add:				//增加
			AddData(&con);
			break;
		case Del:				//删除
			DeleteData(&con);
			break;
		case Find:				//...
			FindData(&con);
			break;
		case Change:
			ChangeData(&con);
			break;
		case Sort:
			SortData(&con);
			break;
		case Print:
			PrintData(&con);
			break;
		case Exit:
			SaveData(&con);
			ExitData(&con);
			break;
		default:
			printf("输入错误\n");
			break;
		}
	} while (input);
}

如有错误,敬请指出,多谢🙏

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
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); /*关闭此文件*/ }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值