C语言手撕通讯录(静态、动态双版本)——万字实战详解

传统艺能😎

小编是双非本科大一菜鸟不赘述,欢迎大佬指点江山(QQ:1319365055)
此前博客点我!点我!请搜索博主 【知晓天空之蓝】
乔乔的gitee代码库(打灰人欢迎访问,点我!

过渡区🤣

现在是北京时间13:30,大年初四的,本来整个人还是一个歇菜状态,有的人卷到我了我不说是谁,上岗!营业!在这里插入图片描述

正片开始👀

这里为了方便对照,我搬出整个程序的前后修改版本,并分别作为静态和动态版本,实际差距并不大,提供出来只供君参考

🤔🤔动机🤔🤔

为什么要写一个通讯录?
1.当然是一部分原因是看了b站上的资源自己比较感兴趣

2.其次就是在C语言实际应用上可以深化和巩固,其实都看得出来我中间断更了好久的数据结构与算法的博客,主要想法还是想把C语言从里到外不遗余力的杀穿,又走了一遍底层原理,不过我相信费时是值得的

3.在学习数据结构和算法这板块,需要C语言基础高度的掌握,所以这部分算对前边理论部分的一个实战项目,数据结构数据结构,无非就是数据的增删查改,这里我们提前热身一下也不错。

静态版本👏

头文件( phonebook.h)

我们这里依旧使用之前写扫雷的分装思想,将这个通讯录分为 头文件,接口,功能三个部分。

首先我们写出头文件,就是我们需要用到什么,给他整出来,我们简单粗暴给命名为“ phonebook.h ”,展示为下面三个部分:

#pragma once
# define _CRT_SECURE_NO_WARNINGS 
# include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>
#define max 1000
#define x 30
#define y 30
#define z 20
typedef struct num
{
   
	char name[x];
	int age;
	char sex[y];
	char addr[y];
	char num[z];
}num;
typedef struct book
{
   
	num data[max];
	int count;
}book;
enum conmenu
{
   
	退出,
	增添,
	删减,
	查找,
	修改,
	排序,
	全览,
};
void start(book* p); //初始化通讯录
void add(book* p);//增添信息
void show(const book* p);//展示信息
void delete(book* p);//删除信息
int search(book* p,char name[]);//库中搜寻要查找信息
void find(book* p);//查找信息
void modify(book* p);//修改信息
void sort(book* p);//排序信息

整个一坨掰成三瓣就是为了方便理解,从上到下分别是菜单(展示必要),自定义类型变量(结构体,枚举类型),需要实现的功能函数名。

为什么结构体变量有两个,book结构体是我们整个通讯录的骨骼,包含count(成员数量)和data(成员数据),这里就相当于模拟了一个数组出来,更方便管理; num 结构体则是存放各个成员数据的细节成分(姓名,年龄,性别……)。

接口(test.c)

设置接口的目的就相当于是设置了一个大门,就是一个统揽全局的作用,我们把菜单,和功能模块在这里作展示作用,代码的实现我们会放在功能板块实现。

#include"phonebook.h"
void menu()
{
   
	printf("-----------------------------\n");
	printf("----    欢迎使用通讯录   ----\n");
	printf("-----------------------------\n");
	printf("----- 1.增添  |   2.删减-----\n");
	printf("----- 3.查找  |   4.修改-----\n");
	printf("----- 5.排序  |   6.全览-----\n");
	printf("-----       0.退出      -----\n");
	printf("-----------------------------\n");
}
int main()
{
   
	int input;
	book con;
	start(&con);
	do
	{
   	
		menu();
		printf("请选择:\n");
		scanf("%d", &input);
		switch (input)
		{
   
		case 增添:
			add(&con);
			break;
		case 删减:
			delete(&con);
			break;
		case 查找:
			find(&con);
			break;
		case 修改:
			modify(&con);
			break;
		case 排序:
			sort(&con);
			break;
		case 全览:
			show(&con);
			break;
		case 退出:
			break;
		default:
			printf("錯誤输入!\n");
			return 0;
		}
	} while (input);
	return 0;
}     

抛开菜单部分,do-while 语句就是对应了菜单给出的功能遥控器,需要什么点什么。

为什么我们需要一个枚举类型,其原因就是为了对应上面菜单中的功能(枚举类型成员在未赋值情况下,第一个成员默认值为 0 ,其下依次递增,从而实现一一对应),我们作为设计者,主要是为了方便我们自己写代码,switch-case 语句中,case 条件我们一眼瞄过去如果是 1,2,3 的数字,我们在完善时就可能云里雾里,还要去查目录,就很麻烦,所以我们用枚举类型来避免这种小尴尬。

功能板块(phonebook.c)

我们在通讯录中需要达到的目的有基本的增删查改,以及作为称得上完美通讯录的全览,排序和退出,下面我们 一 一 实现:

1. 初始化

void start(book* p)
{
   
	assert(p);
	p->count = 0;
	memset(p->data, 0, sizeof(p->data));
}

初识化首先就要避免空指针和随机数,所以这里安排一手 assert 和 置0 就够了。

2. 增添

void add(book* p)
{
   
	assert(p);
	if (p->count == max)
	{
   
		printf("已满,请先进行删除\n");
		return;
	}
	else
	{
   
		printf("请输入姓名:");
		scanf("%s", p->data[p->count].name);
		printf("请输入年龄:");
		scanf("%d", &(p->data[p->count].age));
		printf("请输入性别(F\\M):");
		scanf("%s", p->data[p->count].sex);
		printf("请输入地址:");
		scanf("%s", p->data[p->count].addr);
		printf("请输入电话:");
		scanf("%s", p->data[p->count].num);
		p->count++;
		printf("\n增添成功!\n");
	}
}

增添数据我们要对应好结构体中的类型,因为年龄比较特殊,它是 %d 的形式,输入类型不是字符串,所以我们要进行取地址操作

3.查找

void find(book* p)
{
   
	assert(p);
	if (p->count == 0)
		printf("\n目录为空!\n");
	else
	{
   
		char name[max] = {
    0 };
		printf("请输入查找对象:\n");
		scanf("%s", &name);
		int i = search(p, name);
		if (i != -1)
		{
   
			printf("联系人存在,在第%d位\n", i + 1);
		}
		else
		{
   
			printf("联系人不存在!\n");
		}
	}
}

注意在开始要判断一下现在通讯录状态是否为空,空就无法查找,注意要在库中寻找我们的查找对象,我们还要需要一个对信息进行筛选比对的函数来找出该对象,因此我们引入 search 函数:

int search(book* p, char name[])
{
   
	for (int i = 0; i < p->count; i++)
	{
   
		if (strcmp(name , p->data[i].name)==0)
		{
   
			return i;
		}
		else
		{
   
			return -1;
		}

	}
}

4.删除

void delete(book* p)
{
   
	assert(p);
	if (p->count == 0)
	{
   
		printf("\n为空,无法删除!\n");
		return;
	}
	else
	{
   
		printf("请输入删除对象:\n");
		char name[max] = 
  • 57
    点赞
  • 86
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 83
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 83
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

乔乔家的龙龙

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

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

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

打赏作者

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

抵扣说明:

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

余额充值