C语言实现静态版通讯录的示例代码

目录
  • 前言
  • 通讯录需求分析
  • 功能介绍
  • 实现思路
  • 代码实现
    • test.c
    • contact.c
    • contact.h
  • 效果图

前言

大家好~今天要实现一个非常有意思的东西–通讯录。

通讯录需求分析

为了实现通讯录管理系统,为此,要保证实现以下的功能:

能够存放1000个联系人的信息、每个人的信息包含:名字、年龄、性别、电话、地址、除此之外,还是实现:增加人的信息、删除人的信息、修改指定人的信息、查找指定人的信息、清空联系人的信息、显示联系人的信息、排序通讯录的信息.

功能介绍

1.增加联系人信息

2.删除联系人信息

3.查找联系人信息

4.修改联系人信息

5.显示联系人信息

6.排序联系人信息

7.清空联系人信息

实现思路

静态版本的通讯录首先声明一个结构体类型(struct PeoInfo)用来描述一个人的联系人的各种信息;

然后再声明一个结构体类型(struct Contact)用来描述通讯录,成员使用数组开辟1000个联系人的内存空间实现通讯录,数组的类型为struct PeoInfo
最后就是对存放联系人信息数组的一系列访问操作,封装各个函数实现各部分功能!

代码实现

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"

void menu()
{
	printf("*******************************\n");
	printf("***** 1.add      2.del    *****\n");
	printf("***** 3.search   4.modify *****\n");
	printf("***** 5.sort     6.print  *****\n");
	printf("***** 7.clear    0.exit   *****\n");
	printf("*******************************\n");
}

enum Option
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SORT,
	PRINT,
	CLEAR
};

int main()
{
	int input = 0;
	//创建通讯录,结构体类型在头文件中定义的,所以要引头文件,MAX的定义在头文件或者该源文件内定义都是可以的,因为包含了头文件
	//但是如果把数组和数组元素个数sz定义成一个结构体,就要去头文件中定义,那边就需要MAX,如果MAX在test.c中定义的话,contact.h中就会报错
	//既然这样,就直接把MAX定义在contact.h中去,即可。

	//PeoInfo data[MAX] = { 0 };//不完全初始化
	//通讯录中当前有几个元素:
	//int sz = 0;

	//创建通讯录
	Contact con;
	//con就是通讯录,也可以直接进行初始化,但是为了更好的体现模块化,就对初始化通讯录封装一个函数。
   //如果想把其中的一部分初始化为0,就必须使用函数来做了。
   //初始化通讯录
	InitContact(&con);
	//初始化通讯录的时候要对通讯录中的内容进行修改,如果传值调用的话,不会修改实参中的内容,而且效率低,所以要传址调用。

	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
			case ADD:
				//增加联系人信息
				AddContact(&con);
				//要把数组和数组元素个数都进行传参,会比较麻烦,把两者定义成一个新的结构体
				break;
			case DEL:
				//删除联系人信息
				DelContact(&con);
				break;
			case SEARCH:
				//查找联系人信息
				SearchContact(&con);
				break;
			case MODIFY:
				//修改联系人信息
				ModifyContact(&con);
				break;
			case SORT:
				//排序联系人信息
				SortContact(&con);
				break;
			case PRINT:
				//虽然只是打印信息,不会改变实参的信息,但是考虑的效率的话,还是使用传址调用比较好,结构体传参最好传地址。
				PrintContact(&con);
				break;
			case CLEAR:
				//清空所有联系人信息
				ClearContact(&con);
				break;
			case EXIT:
				printf("退出通讯录\n");
				break;
			default:
				printf("选择错误,请重新选择:>");
				break;
		}
	} while (input);
	//如果有同名的,一律操作第一个出现该名字的那个成员,因为遍历是从前往后遍历的,在这里不考虑同名的情况。
	return 0;
}

contact.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"

//初始化通讯录
void InitContact(Contact* pc)
{
	assert(pc);
	//内存设置函数 — memset() - 内存设置
	(pc->sz) = 0;
	memset(pc->data, 0, sizeof(pc->data));
	//pc->data 就相当于找到了整个数组,而整个数组可以使用数组名来表示,所以可以使用data来表示整个数组
	//即:pc->data  ===  data   ,,,数组名在第一个参数中没有&和sizeof,代表的是数组首元素的地址,第二个参数是把
	//每一个字节都设置成0,十进制的0,转为十六进制表示形式就是0x 00,,pc->data === data,数组名单独放在
	//sizeof中,代表的是整个数组,计算的是整个数组的大小,单位是字节也可以写成:MAX * sizeof(Contact)
}

//增加联系人
void AddContact(Contact* pc)
{
	assert(pc);
	if (pc->sz == MAX)
	{
		printf("通讯录已满、无法添加新的联系人\n");
		return; //返回类型是void,也可以写return,但是不能带出去返回值。
	}
	//通讯录未满,可以添加新成员,增加一个人的信息
	printf("请输入名字:>");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pc->sz].age));
	printf("请输入性别:>");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入电话:>");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入地址:>");
	scanf("%s", pc->data[pc->sz].addr);
	pc->sz++;
	printf("增加联系人成功\n");
	//在这里,[ ]的优先级等于->,,但是,data和[ ]是不可以先进行结合的,因为,这是在一个调用函数中,形参那部分接受到的只有指针变量pc
	//也就是说,如果后两者进行结合的话,系统根本就不知道data是什么东西,所以它结合出来是错误的,即,即使[ ]的优先级等于->,但是后两者不能
	//进行结合会出错,又因结合性从左到右所以,还是先让data和->进行结合,即先进行pc->data的操作,所以在结构体成员变量中找到了整个数组data
	//而整个数组可以使用数组名进行表示,知道了数组名就可以再通过下标对数组元素进行访问了。

}

//显示联系人信息
void PrintContact(const Contact* pc)
{
	assert(pc);
	//打印出所有人的信息,即sz个人的信息。
	int i = 0;
	//打印标题
	printf("%-10s\t%-5s\t%-5s\t%-12s\t%-50s\n", "名字", "年龄", "性别", "电话", "地址");// \t === tab
	//打印数据
	for (i = 0; i < (pc->sz); i++)
	{
		printf("%-10s\t%-5d\t%-5s\t%-12s\t%-50s\n", pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].tele,
			pc->data[i].addr);
	}

	//通过pc->data[i]找到数组data中下标为i的元素,即找到了一个变量,再通过点来访问该人的姓名等,,由于姓名是一个数组,找到的就是整个数组,整个
	//数组又可以使用数组名来表示,即:pc->data[i].name === name ,没有sizeof和&,代表数组首元素的地址,再通过%s进行打印字符串,除了年龄是一个变量,其他的都是数组,和name同理。

}

//因为该函数只是为了满足删除,查找,修改功能的需要,而这三个功能对应的函数的实现都会在该 .c 文件内进行实现,所以,对于这个函数
//只需要在该 .c 文件内执行即可,不许要暴露给别人,,所以,在前面加上static,就固定了该函数只在目前所在的 .c 文件内进行工作即可。
//static 修饰函数,本质上是改变了函数的链接属性。
static int Find_By_Name(const Contact* pc, char name[])//数组形式接收,数组形式接受的话就不考虑const的使用了。
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)//相等
	//第一个参数先找到整个数组,可以使用数组名来表示,不是特例,即代表数组首元素的地址,第二个参数也不是特例,也是数组首元素的地址。
		{
			return i;
		}
	}
	return -1;
}
//删除联系人信息
void DelContact(Contact* pc)
{
	assert(pc);
	char name[MAX_NAME] = { 0 };
	if (pc->sz == 0)
	{
		printf("通讯录为空、不可以再进行删除操作\n");
		return;
	}
	//删除某个人的信息
	printf("请输入要删除人员的姓名:>");
	scanf("%s", name);
	//1、查找要删除的人
	//不管是删除还是查找还是修改,都需要使用到查找这个功能,所以就单独把该功能拿出来封装一个函数;
	int pos = Find_By_Name(pc, name);//一级指针传参和数组名传参
	//不存在该人
	if (pos == -1)
	{
		printf("要删除的人员不存在\n");
		return;
	}
	//2、存在该人员,要进行删除,把数组该位置上的人员删除之后,数组后面的人员依次往前移动一个位置。
	int i = 0;
	for (i = pos; i < (pc->sz - 1); i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	//pc->sz -= 1;
	pc->sz--;
	//如果想删除最后一个,是删除不掉的,因为,如果10个元素,最后一个下标为9,判断条件是<9,,所以不进入循环,但是
	//循环后面还有pc->sz--,,成员个数少了1,再显示人员信息的时候,访问不到最后一个人员了,,即使没删掉,也访问不掉,
	//最后的结果和删掉最后一个人员的效果是一样的。
	//假设MAX=3,把最后一个元素删除,本质上并没有从数组中删除掉,而是因为sz减1,打印的时候不访问最后一个元素,看起来和删除的效果是一样的,现在由于
	//看起来删了,本质上没删去,如果再添加新元素会怎么样呢?
	//因为删除完之后,元素个数就会减去1,由原来的3变成了2,,再添加新元素的时候,就会直接把新元素的内容放在下标为2的位置上,这样的话,即使之前的最后一个元素
	//没删去,也会被新的元素覆盖掉,添加完之后元素个数加1,再打印出来就是添加成员后的信息,是对的。
	printf("删除联系人员成功\n");
}

//查找联系人信息
void SearchContact(const Contact* pc)
{
	assert(pc);
	char name[MAX_NAME] = { 0 };
	//查找某个人的信息
	printf("请输入要查找人员的姓名:>");
	scanf("%s", name);
	int pos = Find_By_Name(pc, name);
	//要查找的人员不存在
	if (pos == -1)
	{
		printf("要查找的人员不存在\n");
		return;
	}

	//2、存在该人员,找出之后并打印出该成员的信息
	//打印标题
	printf("%-10s\t%-5s\t%-5s\t%-12s\t%-50s\n", "名字", "年龄", "性别", "电话", "地址");// \t === tab
	//打印数据
	printf("%-10s\t%-5d\t%-5s\t%-12s\t%-50s\n",
		pc->data[pos].name,
		pc->data[pos].age,
		pc->data[pos].sex,
		pc->data[pos].tele,
		pc->data[pos].addr);

}

//修改指定联系人的信息
void ModifyContact(Contact* pc)
{
	assert(pc);
	char name[MAX_NAME] = { 0 };
	//修改某个人的信息
	printf("请输入要修改人员的姓名:>");
	scanf("%s", name);
	int pos = Find_By_Name(pc, name);
	//要修改的人员不存在
	if (pos == -1)
	{
		printf("要修改的人员不存在\n");
		return;
	}
	else
	{
		printf("请输入修改后人员的名字:>");
		scanf("%s", pc->data[pos].name);
		printf("请输入修改后人员的年龄:>");
		scanf("%d", &(pc->data[pos].age));
		printf("请输入修改后人员的性别:>");
		scanf("%s", pc->data[pos].sex);
		printf("请输入修改后人员的地址:>");
		scanf("%s", pc->data[pos].addr);
		printf("请输入修改后人员的电话:>");
		scanf("%s", pc->data[pos].tele);
		printf("修改联系人员信息成功\n");
	}
}

int cmp_Per_by_name(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}

void SortContact(Contact* pc)
{
	assert(pc);
	qsort(pc->data, pc->sz, sizeof(PeoInfo), cmp_Per_by_name);
	PrintContact(pc);
}

void ClearContact(Contact* pc)
{
	assert(pc);
	InitContact(pc);
	printf("清空成功\n");
}

contact.h

#pragma once

//类型的定义、通讯录中要放1000个人的信息,
//每个人的信息要包括名字、年龄、性别、电话、地址等,
//所以要定义成一个结构体,而该结构体要在两个源文件中使用,
//所以最好定义在头文件中,这样只需要包含一下头文件就可以频繁的使用了

//头文件的包含
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>

//定义结构体类型
#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_TELE 12
#define MAX_ADDR 30
#define MAX 1000

typedef struct PeoInfo
{
	//char name[20];
	//直接写成固定值就写死了,不方便后期的修改,
	//所以使用#define 来定义一个常量,后期直接改变#define中的内容即可。
	char name[MAX_NAME];
	char sex[MAX_SEX];
	int age;
	char tele[MAX_TELE];
	char addr[MAX_ADDR];
}PeoInfo;//使用typedef对结构体类型重命名为:PeoInfo

//结构体嵌套
//通讯录
typedef struct Contact//重命名
{
	PeoInfo data[MAX];//存放添加进去的联系人的信息
	int sz;//记录当前通讯录中有效信息的个数
}Contact;

//初始化通讯录
void InitContact(Contact* pc);

//增加联系人
void AddContact(Contact* pc);

//打印信息
void PrintContact(const Contact* pc);

//删除联系人信息
void DelContact(Contact* pc);

//查找联系人信息
void SearchContact(const Contact* pc);

//修改指定联系人的信息
void ModifyContact(Contact* pc);

//排序联系人的信息
void SortContact(Contact* pc);

//清空所有联系人的信息
void ClearContact(Contact* pc);

效果图

以上就是C语言实现静态版通讯录的示例代码的详细内容,更多关于C语言静态通讯录的资料请关注我们其它相关文章!

(0)

相关推荐

  • C语言静态动态两版本通讯录实战源码

    目录 正片开始 静态版本 头文件( phonebook.h) 接口(test.c) 功能板块(phonebook.c) 1. 初始化: 2. 增添: 3.查找 4.删除 5.修改 6.排序 7.全览 静态版全部代码 test.c(接口) phonebook.h(头文件) phonebook.c(功能) 动态版 动态初始化: 扩容函数 动态版全部代码 test.c phonebook.h 正片开始 这里为了方便对照,我搬出整个程序的前后修改版本,并分别作为静态和动态版本,实际差距并不大,提供出来只

  • 基于C语言实现静态通讯录的示例代码

    目录 一.项目要求 二.Contact.h 三.Contact.c 1.静态函数 2.初始化通讯录 3.打印 4.增加联系人信息 5.通过名字查找 6.删除联系人信息 7.修改信息 8.排序通讯录 9.清空通讯录 四.text.c 五.动图展示 一.项目要求 实现一个通讯录 通讯录可以用来存储100个人的信息,每个人的信息包括:姓名.性别.年龄.电话.住址 提供方法: 添加联系人信息 删除指定联系人信息 查找指定联系人信息 修改指定联系人信息 显示所有联系人信息 清空所有联系人 以名字排序所有联

  • C语言静态与动态通讯录的实现流程详解

    目录 静态通讯录 contact.h contact.c test.c 动态通讯录 contact.h contact.c qsort.c test.c 本次通讯录的代码已经放到我的Gitee仓库中,感兴趣的小伙伴可以去看看 Gitee 静态通讯录 在我们学习完C语言的结构体.指针以及动态内存管理之后,我们就可以实现一些有意思的小项目了,通过这些小项目可以加深我们对于相关知识的理解. 静态通讯录主要要求有 静态大小,可以记录10个人的信息(大小自己定) 记录的信息如下:名字.性别.年龄.电话.住

  • C语言动态与静态分别实现通讯录详细过程

    目录 前言: 一.静态通讯录的实现 1.环境的分工逻辑 2.待实现的功能 3.contact.h 4.contact.c 5.test.c 6.实现效果 二.通讯录动态的实现 1.contact.h 2.contact.c 3.test.c 前言: 通讯录相信每一个人都了解过 它的功能包括简单包括:增删查改 这一期就来实现一个C语言实现的通讯录 续上次所聊到的--动态内存的分配 那么我会从标题所给的两个方式来实现 一.静态通讯录的实现 1.环境的分工逻辑 由于过程有点长,便于理解,所以一共会用到

  • C语言示例讲解动态/文件/静态功能版本的通讯录实现

    目录 一.代码展示 test.c contact.c contact.h 二.效果展示 静态版本基本功能的实现 动态版本扩容功能的实现 文件版本保存本地功能实现 一.代码展示 test.c 使用枚举类型,使得菜单部分的代码可读性更强,便于理解 #define _CRT_SECURE_NO_WARNINGS #include"contact.h" enum Option { EXIT, ADD, DEL, SEARCH, MODIFY, SHOW, SORT }; void menu()

  • C语言实现通讯录的方法(包括静态版本和动态版本)

    目录 1.静态通讯录的实现 实现的方法: 2.动态通讯录的实现 实现的方法: 3.总结 1.静态通讯录的实现 实现的方法: 我们采用的方法就是工程形势,实现将功能和定义以及测试分成三个文件,其中定义放在.h文件,实现和测试放在.c文件当中. (1)contact.h文件的基本实现: #pragma once//防止头文件重复定义 #define NAME_MAX 20 #define SEX_MAX 5 #define TELE_MAX 12 #define ADDR_MAX 30 #defin

  • C语言实现静态版通讯录的示例代码

    目录 前言 通讯录需求分析 功能介绍 实现思路 代码实现 test.c contact.c contact.h 效果图 前言 大家好~今天要实现一个非常有意思的东西–通讯录. 通讯录需求分析 为了实现通讯录管理系统,为此,要保证实现以下的功能: 能够存放1000个联系人的信息.每个人的信息包含:名字.年龄.性别.电话.地址.除此之外,还是实现:增加人的信息.删除人的信息.修改指定人的信息.查找指定人的信息.清空联系人的信息.显示联系人的信息.排序通讯录的信息. 功能介绍 1.增加联系人信息 2.

  • C语言实现动态版通讯录的示例代码

    目录 前言 contact.c contact.h test.c 前言 大家好~今天是通讯录的动态版本实现,希望对大家对知识的掌握有所提升! contact.c #include"contact.h" //初始化通讯录 void InitContact(Contact* pc) { assert(pc); pc->sz = 0; pc->data = (PeoInfo*)calloc(DEFAULT_SZ, sizeof(PeoInfo)); if (NULL == pc-

  • C语言实现静态版通讯录的代码分享

    目录 前言 通讯录设计的关键思想点分析 通讯录界面(meun)设计 增加信息功能实现代码 删除信息功能实现代码 查询信息功能实现代码 修改信息功能实现代码 按年龄升序排序信息功能实现代码 显示信息功能实现代码 通讯录完整代码 测试过程展示 前言 哈喽各位友友们,我今天又学到了很多有趣的知识,现在迫不及待的想和大家分享一下!我仅已此文,手把手带领大家在学习C语言知识的同时,并实现一个静态版的通讯录!主要运用了结构体,一维数组,函数,分支与循环语句等等知识,以及分文件书写项目思想.都是精华内容,可不

  • C语言实现可排序通讯录的示例代码

    目录 1.目的 2.分部流程 1.初始化通讯录 2.添加联系人 3.判断联系人是否存在 4.判断通讯录是否已满 5.判断通讯录是否为空 6.通讯录扩容 7.核心函数 8.查找联系人 9.修改联系人 10.清空通讯录 11.删除联系人 12.显示通讯录 13.比较联系人 14.通讯录排序 3.总代码展示 1.目的 写一个实用型通讯录,它有如下功能: 显示目录 void ShowMenu() { printf("#######################\n"); printf(&qu

  • C语言静态版通讯录的设计与实现

    目录 1. 配置运行环境 2. 通讯录的实现 2.1 通讯录的功能目录 2.2 增加信息功能代码的实现 2.3 显示信息功能代码的实现 2.4 删除信息功能代码的实现 2.5 查询信息功能代码的实现 2.6 修改信息功能代码的实现 2.7 按名字排序信息功能代码的实现 3. 完整静态版本通讯录的全部源码 3.1 contact.c 3.2 contact.h 3.3 test.c 4. 静态版本通讯录的缺点 1. 配置运行环境 本通讯录运用到了三个文件 test.c //测试通讯录的相关功能 c

  • C语言实现可保存的动态通讯录的示例代码

    目录 一.Contact.h 二.Contact.c 1.判断是否增容 2.初始化通讯录 3.打印 4.增加联系人信息 5.通过名字查找 6.删除联系人信息 7.查找信息 8.修改信息 9.排序 10.清空通讯录 11.保存通讯录为文件 三.text.c 四.错误写法分享 五.动图展示 一.Contact.h #pragma once #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <assert.h> #

  • C语言实现通讯录的示例代码

    目录 一.Contact.h文件 二.Contact.c文件 三.test.c文件 一.Contact.h文件 包含函数的声明 #pragma once #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <assert.h> #define MAX 100 #define MAX_NAME 20 #defi

  • Java实现泡泡堂对战版游戏的示例代码

    目录 前言 主要设计 功能截图 代码实现 游戏启动类 核心监听类 核心线程类 总结 前言 <泡泡堂II>是一个基于java的自制游戏,使用了MVC模式,分离了模型.视图和控制器,使得项目结构清晰易于扩展,使用配置文件来设置游戏基本配置,扩展地图人物道具等.同时,该程序编写期间用了单例模式.工厂模式.模板模式等设计模式.为了游戏的可玩性,特意设计了平滑碰撞以及机器人. 主要设计 设计游戏界面,用swing实现 绘制游戏启动界面.结束界面.地图.主角.道具 实现泡泡爆炸 为了尽量复原泡泡堂游戏,初

  • C语言实现链表与文件存取的示例代码

    目录 此处为main函数的内容 一.输入数据到链表中 二.把链表数据存入文件 三.输出文件 完整代码 本程序主要功能是建立链表,然后把链表数据存储到文件中,然后把文件数据存储到数组中并输出. 不多说了,放代码. 此处为main函数的内容 int main(void) { char filename[50]; printf("How many ?: "); scanf("%d", &n); /*输入学生数*/ printf("please input

随机推荐