【C语言】通讯录的简单实现

通讯录的内容

【C语言】通讯录的简单实现_第1张图片


contect.h 

#pragma once
// 包含头文件
#include 
#include 
#include 
#include 


// 使用枚举常量定义功能
enum Function
{
	quit, // 注意这是逗号,不是分号
	save,
	addition,
	delete,
	search,
	revise,
	sort,
	show // 最后一个没有逗号
};

// 人的信息
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
typedef struct People_Information
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
}People; // 通过typedef将struct People_Informtion定义为了People

// 通讯录
#define DATA_MAX 1000
typedef struct Contact
{
	People data[DATA_MAX]; // data数组里面存放的是每个人的信息
	int sz; // 用于记录通讯录中有几个人的信息
}Contact; // 通过typedef将struct Contact定义为了Contact


// 函数声明
// 初始化通讯录
void InitContact(Contact* contact);
// 增加个人信息
void AddContact(Contact* contact);
// 显示通讯录
void ShowContact(const Contact* contact);
// 删除指定信息
void DelContact(Contact* contact);
// 查找指定信息
void SeaContact(const Contact* contact);
// 修改指定联系人
void RevContact(Contact* contact);
// 排序通讯录
void SorContact(Contact* contact);

contact.c 

#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"
void menu()
{
	printf("..............................\n");
	printf("....0:quit........1:save......\n");
	printf("....2:addition....3:delete....\n");
	printf("....4:search......5:revise....\n");
	printf("....6:sort........7:show......\n");
	printf("..............................\n");
}
int main()
{
	
	// 利用do{}while();循环和switch语句进行多次选择
	int input;
	
	// 进入main函数就要创建通讯录
	Contact contact; // contact就是一个通讯录

	// 初始化通讯录
	InitContact(&contact); // 将通讯录的地址传过去,不仅节省地址,而且可以通过形参改变实参

	do
	{
		// 有哪些功能
		// 通过菜单将功能展现出来
		menu();

		printf("请输入功能序号:");
		scanf("%d", &input);
		switch (input)
		{
			// 通过枚举常量定义会更直观
		case quit:
			printf("退出通讯录!\n");
			break;
		case save:
			break;
		case addition:
			AddContact(&contact);
			break;
		case delete:
			DelContact(&contact);
			break;
		case search:
			SeaContact(&contact);
			break;
		case revise:
			RevContact(&contact);
			break;
		case sort:
			SorContact(&contact);
			break;
		case show:
			ShowContact(&contact);
			break;
		default:
			printf("无此序号,请重新输入。\n");
		}
	} while (input);
	return 0;
}

test.c 

#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"

// 初始化通讯录
void InitContact(Contact* contact)
{
	assert(contact);
	// contact->data = 0; // contact->data表示的是首元素地址
	// 初始化一块连续的内存空间可以使用memset
	memset(contact->data, 0, sizeof(contact->data));
	contact->sz = 0;
}

// 增加个人信息
void AddContact(Contact* contact)
{
	assert(contact);

	// 进入函数进行判断
	if (contact->sz == DATA_MAX)
	{
		printf("通讯录已满,无法增加个人信息!\n");
		return;
	}
	// 没有满则进行增加个人信息
	printf("请输入姓名:");
	scanf("%s", &(contact->data[contact->sz].name));
	printf("请输入年龄:");
	scanf("%d", &(contact->data[contact->sz].age));
	printf("请输入性别:");
	scanf("%s", &(contact->data[contact->sz].sex));
	printf("请输入电话:");
	scanf("%s", &(contact->data[contact->sz].tele));
	printf("请输入地址:");
	scanf("%s", &(contact->data[contact->sz].addr));

	// 增加完一条信息后sz要加1
	contact->sz++;
	printf("增加成功!\n");
}

// 显示通讯录
void ShowContact(const Contact* contact)
{
	assert(contact);

	// 进入函数进行判断
	if (contact->sz == 0)
	{
		printf("通讯录为空!\n");
		return;
	}
	// 显示信息
	// 标题
	printf("%-10s %-5s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "住址");
	for (int i = 0; i < contact->sz; i++)
	{
		printf("%-10s %-5d %-5s %-12s %-30s\n",
			contact->data[i].name,
			contact->data[i].age,
			contact->data[i].sex,
			contact->data[i].tele,
			contact->data[i].addr
		);
	}
}

// 通过名字查找联系人下标
int FindByName(const Contact* contact, char* name)
{
	assert(contact);
	for (int i = 0; i < contact->sz; i++)
	{
		if (strcmp(contact->data[i].name, name) == 0)
		{
			// 找到返回数组下标

			return i;
		}
	}
	return -1;
}

// 删除指定信息
void DelContact(Contact* contact)
{
	assert(contact);

	char name[NAME_MAX];
	if (contact->sz == 0)
	{
		printf("通讯录为空!\n");
		return;
	}
	// 通过名字查找
	printf("请输入要删除人的姓名:");
	scanf("%s", name);
	int ret = FindByName(contact, name);

	// 没找到
	if (ret == -1)
	{
		printf("要删除的人不存在!\n");
	}
	// 找到了
	// 删除这个人(其实是覆盖)
	for (int i = ret; i < contact->sz - 2; i++) // 减2这里不是很懂
	{
		contact->data[i] = contact->data[i + 1];
	}
	contact->sz--;
	printf("删除成功!\n");
	// 最后一个直接覆盖当前这个
	// 结构体类型相同可以直接赋值
	/*contact->data[ret] = contact->data[contact->sz];
	contact->sz--;*/
}

// 查找指定信息
void SeaContact(const Contact* contact)
{
	assert(contact);

	char name[NAME_MAX];
	if (contact->sz == 0)
	{
		printf("通讯录为空!\n");
		return;
	}
	// 通过名字查找
	printf("请输入要修改人的姓名:");
	scanf("%s", name);
	int ret = FindByName(contact, name);
	// 没找到
	if (ret == -1)
	{
		printf("要查找的人不存在!\n");
	}
	// 找到了
	// 显示出来
	printf("%-10s %-5s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "住址");
	printf("%-10s %-5d %-5s %-12s %-30s\n",
		contact->data[ret].name,
		contact->data[ret].age,
		contact->data[ret].sex,
		contact->data[ret].tele,
		contact->data[ret].addr
	);
}

// 修改指定联系人
void RevContact(Contact* contact)
{
	assert(contact);

	char name[NAME_MAX];
	if (contact->sz == 0)
	{
		printf("通讯录为空!\n");
		return;
	}
	// 通过名字修改
	printf("请输入要修改人的姓名:");
	scanf("%s", name);
	int ret = FindByName(contact, name);
	// 没找到
	if (ret == -1)
	{
		printf("要修改的人不存在!\n");
	}
	// 找到了
	// 修改
	printf("请输入姓名:");
	scanf("%s", &(contact->data[contact->sz].name));
	printf("请输入年龄:");
	scanf("%d", &(contact->data[contact->sz].age));
	printf("请输入性别:");
	scanf("%s", &(contact->data[contact->sz].sex));
	printf("请输入电话:");
	scanf("%s", &(contact->data[contact->sz].tele));
	printf("请输入地址:");
	scanf("%s", &(contact->data[contact->sz].addr));

	printf("修改成功!\n");
}


int compare_name(const void* x, const void* y)
{
	return strcmp((char*)x, (char*)y);
}

// 排序通讯录
void SorContact(Contact* contact)
{
	assert(contact);

	if (contact->sz == 0)
	{
		printf("通讯录为空!\n");
		return;
	}
	// 排序通讯录
	qsort(contact, contact->sz, sizeof(contact->data[0]), compare_name);
	// 显示信息
	// 标题
	printf("%-10s %-5s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "住址");
	for (int i = 0; i < contact->sz; i++)
	{
		printf("%-10s %-5d %-5s %-12s %-30s\n",
			contact->data[i].name,
			contact->data[i].age,
			contact->data[i].sex,
			contact->data[i].tele,
			contact->data[i].addr
		);
	}
}

  注意:

传址还是传值

通讯录初始化涉及到传递参数,那我们到底是传址还是传值呢?

InitContact(&contact);  // 传递的是地址

// 传址:因为更节省内存空间(地址只占4/8个字节),而且可以通过形参来改变实参;

// 传值:所需的内存空间更大,并且改变形参并不会影响实参;


memset初始化连续空间

// 这里使用的是memset初始化数组,也可以通过循环将数组一个一个制成0;

【C语言】通讯录的简单实现_第2张图片

memset的用法

 【C语言】通讯录的简单实现_第3张图片


存在的缺陷

初始设计的通讯录所存在的缺陷

1、录入的信息,只要一退出程序,数据就会丢失,因为数据是存放在内存中的;

解决方案就是:文件存储、数据存储

2、通讯录开辟的空间是固定的,如果存放的信息多空间就小了;如果存放的信息少空间就大了;

解决方案就是:动态内存管理

你可能感兴趣的:(c语言,开发语言)