C语言——详细解析《通讯录实现》

通讯录实现

一、实现目的和意义

  • 1、提高解决实际问题的能力和动手能力
  • 2、巩固和加深对c怨言的理解
  • 3、练习编译器的调试

二、实现内容

用C语言去实现可以存放1000人的通讯录。

三、实现功能

实现的通讯录可以实现增加、删除、搜索、修改、展示信息内容、对电话信息进行按名字或年龄排序。

四、实现逻辑

(一)、menu菜单函数

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");
}

(二)、创建结构体并初始化

  • 创建结构体:
#define MAX 1000
#define MAX_name 20
#define MAX_sex 5
#define MAX_tel 13
#define MAX_addr 30

struct P
{
	char name[MAX_name];
	char sex[MAX_sex];
	int age;
	char tel[MAX_tel];
	char adress[MAX_addr];
};
struct Phone
{
	struct P data[MAX];
	int sz;
};

创建两个结构体,一个是存放一个人的信息,另一个是存放数组和当前人数量。人信息用宏来代替便于修改。

  • 初始化通讯录:
void InitPhone(struct Phone* pc)
{
	assert(pc);
	memset(pc->data, 0, MAX*sizeof(struct P));
	pc->sz = 0;
}

初始化时,传的是结构体Phone的地址,用结构体指针pc来接收,里面并用aasert断言一下,一以便直到是哪行出了问题,再用memset函数,把结构体P里面的信息置为0,及把sz记录当前数量置为0。

(三)、在do…while循环里面用switch创建功能函数和退出功能

(1)、创建增加函数

void AddPhone(struct Phone* pc)
{
	assert(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].tel);
	printf("输入地址:");
	scanf("%s", pc->data[pc->sz].adress);
	pc->sz++;
	printf("成功添加\n");
}

函数解析:

  • 用结构体指针变量pc接收,直接用5个打印函数,去录入信息,如名字,用pc找到数组,并用pc找到sz作为下标,再.name找到名字。
  • 里面要注意再用scanf的时候数组是数组名地址,不用加&,而整型变量要加取地址符号。
  • 最后用pc找到sz++,记录已录人数,并打印成功添加。

(2)、创建删除函数

void  DelPhone(struct Phone* pc)
{
	char name[MAX_name];
	printf("输入删除的名字:");
	scanf("%s", name);
	int ret = Find_name(pc, name);
	if (ret == -1)
	{
		printf("删除的人不存在");
	}
	else
	{
		for (int j = ret; j < pc->sz; j++)
		{
			pc->data[j] = pc->data[j + 1];
		}
		pc->sz--;
		printf("已删除改联系人\n");
	}
}

函数解析:

  • 在里面要先创建name数组,来存放要删除的名字,之后需要判断要删除的人是否存在还需创建Find_name()函数来判断,并用ret接收。此函数如下:
int Find_name(struct Phone* pc, char name[])
{
	for (int i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}

函数解析:
** 除了用pc接收,还要接收删除name的地址,在里面用for循环,遍历查找,里面再用if判断语句来判断,用strcmp比较函数来比较所输入名字和通讯录名字是否一样。
** 如果一样返回下标。没有找到返回-1。

  • 找到之后用for循环把后面的元素左移。
  • 最后人数减一。

(3)、创建搜索函数

void SearchPhone(struct Phone* pc)
{
	char name[MAX_name];
	printf("输入搜索的名字:");
	scanf("%s", name);
	int ret = Find_name(pc, name);
	if (ret == -1)
	{
		printf("搜索的人不存在");
	}
	else
	{
		printf("%-20s\t%-5s\t%-10s\t%-13s\t%-30s\n", "姓名", "性别", "年龄", "电话号码", "地址");
		printf("%-20s\t%-5s\t%-10d\t%-13s\t%-30s\n", pc->data[ret].name, pc->data[ret].sex,
			pc->data[ret].age, pc->data[ret].tel, pc->data[ret].adress);
	}
}

函数解析:

  • 前面的步骤和删除步骤一样,需要判断搜索的人是否存在,如果存在打印。
  • 为了让信息显示的更美观和直观,用对齐方式来实现且上下两个打印函数保持一致,负号表示右对齐。

(4)、创建修改函数

void ModifyPhone(struct Phone* pc)
{
	char name[MAX_name];
	printf("输入修改的名字:");
	scanf("%s", name);
	int ret = Find_name(pc, name);
	if (ret == -1)
	{
		printf("修改的人不存在");
	}
	else
	{
		printf("输入名字:");
		scanf("%s", pc->data[ret].name);
		printf("输入性别:");
		scanf("%s", pc->data[ret].sex);
		printf("输入年龄:");
		scanf("%d", &(pc->data[ret].age));
		printf("输入电话号码:");
		scanf("%s", pc->data[ret].tel);
		printf("输入地址:");
		scanf("%s", pc->data[ret].adress);
		printf("已修改改联系人\n");
	}
}

函数解析:

  • 和前面一样需要判断修改的人是否存在,存在返回下标,在此下标直接覆盖。
  • 最后打印修改联系人。

(5)、创建展示函数

void ShowPhone(struct Phone* pc)
{
	printf("%-20s\t%-5s\t%-10s\t%-13s\t%-30s\n", "姓名","性别","年龄","电话号码","地址");
	for (int i = 0; i < pc->sz; i++)
	{
		printf("%-20s\t%-5s\t%-10d\t%-13s\t%-30s\n", pc->data[i].name, pc->data[i].sex,
			pc->data[i].age, pc->data[i].tel, pc->data[i].adress);
	}
}

函数解析:

  • 还是要实现对齐保持上下一致,用for循环直接打印全部信息。

(6)、创建排序函数

int cmp_name(const void* e1,const void* e2)
{
	return strcmp(((struct P*)e1)->name ,((struct P*)e2)->name);
}
void SortPhone(struct Phone* pc)
{
	qsort(pc->data,pc->sz,sizeof(struct P),cmp_name);
}

函数解析:

  • 创建排序函数时,要知道qsort函数的用法,qsort需要传4个参数。
    第一是数组地址,第二是数组个数,第三每个个数大小(单位字节),函数指针。
  • 函数指针,也即是函数名,需要调用的函数。
  • 在此这个被调用函数里面,需要用void*指针来接收,因为不知道传的是什么类型。
  • 在里面用strcmp比较名字大小或者年龄大小。
  • 在strcmp里面需把空指针转换为结构体指针,再用这个指针找到要比较的类型名。

(7)、创建退出功能

直接打印退出功能,退出循环。

五、实现结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

六、实现源代码

(1)Phone.h

#pragma once
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
#define MAX 1000
#define MAX_name 20
#define MAX_sex 5
#define MAX_tel 13
#define MAX_addr 30

struct P
{
	char name[MAX_name];
	char sex[MAX_sex];
	int age;
	char tel[MAX_tel];
	char adress[MAX_addr];
};
struct Phone
{
	struct P data[MAX];
	int sz;
};

void InitPhone(struct Phone* pc);

void AddPhone(struct Phone* pc);
void DelPhone(struct Phone* pc);
void SearchPhone(struct Phone* pc);
void ModifyPhone(struct Phone* pc);
void ShowPhone(struct Phone* pc);
void SortPhone(struct Phone* pc);

int Find_name(struct Phone* pc, char name[]);
int cmp_name(const void* e1, const void* e2);

(2)text.c

#include"phone.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;
	struct Phone con;
	InitPhone(&con);
	do
	{
		menu();
		printf("请选择->");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			AddPhone(&con);
			break;
		case 2:
			DelPhone(&con);
			break;
		case 3:
			SearchPhone(&con);
			break;
		case 4:
			ModifyPhone(&con);
			break;
		case 5:
			ShowPhone(&con);
			break;
		case 6:
			SortPhone(&con);
			break;
		case 0:
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
	return 0;
}

(3)Phone.c

#include"phone.h"
void InitPhone(struct Phone* pc)
{
	assert(pc);
	memset(pc->data, 0, MAX*sizeof(struct P));
	pc->sz = 0;
}
void AddPhone(struct Phone* pc)
{
	assert(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].tel);
	printf("输入地址:");
	scanf("%s", pc->data[pc->sz].adress);
	pc->sz++;
	printf("成功添加\n");
}
void ShowPhone(struct Phone* pc)
{
	printf("%-20s\t%-5s\t%-10s\t%-13s\t%-30s\n", "姓名","性别","年龄","电话号码","地址");
	for (int i = 0; i < pc->sz; i++)
	{
		printf("%-20s\t%-5s\t%-10d\t%-13s\t%-30s\n", pc->data[i].name, pc->data[i].sex,
			pc->data[i].age, pc->data[i].tel, pc->data[i].adress);
	}
}
int Find_name(struct Phone* pc, char name[])
{
	for (int i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}
void  DelPhone(struct Phone* pc)
{
	char name[MAX_name];
	printf("输入删除的名字:");
	scanf("%s", name);
	int ret = Find_name(pc, name);
	if (ret == -1)
	{
		printf("删除的人不存在");
	}
	else
	{
		for (int j = ret; j < pc->sz; j++)
		{
			pc->data[j] = pc->data[j + 1];
		}
		pc->sz--;
		printf("已删除改联系人\n");
	}
}
void ModifyPhone(struct Phone* pc)
{
	char name[MAX_name];
	printf("输入修改的名字:");
	scanf("%s", name);
	int ret = Find_name(pc, name);
	if (ret == -1)
	{
		printf("修改的人不存在");
	}
	else
	{
		printf("输入名字:");
		scanf("%s", pc->data[ret].name);
		printf("输入性别:");
		scanf("%s", pc->data[ret].sex);
		printf("输入年龄:");
		scanf("%d", &(pc->data[ret].age));
		printf("输入电话号码:");
		scanf("%s", pc->data[ret].tel);
		printf("输入地址:");
		scanf("%s", pc->data[ret].adress);
		printf("已修改改联系人\n");
	}
}
int cmp_name(const void* e1,const void* e2)
{
	return strcmp(((struct P*)e1)->name ,((struct P*)e2)->name);
}
void SortPhone(struct Phone* pc)
{
	qsort(pc->data,pc->sz,sizeof(struct P),cmp_name);
}
void SearchPhone(struct Phone* pc)
{
	char name[MAX_name];
	printf("输入搜索的名字:");
	scanf("%s", name);
	int ret = Find_name(pc, name);
	if (ret == -1)
	{
		printf("搜索的人不存在");
	}
	else
	{
		printf("%-20s\t%-5s\t%-10s\t%-13s\t%-30s\n", "姓名", "性别", "年龄", "电话号码", "地址");
		printf("%-20s\t%-5s\t%-10d\t%-13s\t%-30s\n", pc->data[ret].name, pc->data[ret].sex,
			pc->data[ret].age, pc->data[ret].tel, pc->data[ret].adress);
	}
}
评论 62
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

7昂7.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值