C语言 与 C++ 通讯录对比实现(附源码)

news2024/11/27 22:36:48

目录

1.通讯录的基本框架

C语言版

C++版

2.增加联系人

C语言版

C++版

3.删除联系人

C语言版

C++版

4.查找与打印联系人

C语言版

C++版

5.修改联系人

C语言版

C++版

6.排序联系人

C语言版

C++版

7.其他

8.总结



本文章将对C语言、C++版本的通讯录进行对比实现。其中C++版本引入大量C语言没有的特性。旨在使广大朋友能快速适应,了解,学习C++基础语法。

下面我将把通讯录的增删查改等功能分模块进行对比。(本人为C++初学者,如果大家对文章有任何问题或意见欢迎指出)


1.通讯录的基本框架

C语言版

这里我们无非是打印菜单功能,创建联系人结构体,还有通讯录结构体。我这里就只展示结构体的实现了。这里实现的动态增容版的通讯录所以联系人结构体里放了 sz 表示人数,capacity表示容量。

typedef struct PeoInfo
{
	char name[MAX_NAME];
	char sex[MAX_SEX];
	int age;
	char tele[MAX_TELE];
	char addr[MAX_ADDR];
}PeoInfo;

typedef struct Contact
{
	PeoInfo *date;
	int sz;
	int capacity;
}Contact;

C++版

在C++版里我选择用类来代替结构体因为这里我想牵强的使用一下C++中的继承语法。相比较与C语言的手动开辟内存,这里我选择用vector来存放通讯录类类型。

class Peo
{
public:
	Peo(string n, string a, string s, string t, int age) :name(n), addr(a),
		sex(s), tele(t), age(age) {}//构造函数
	string name;
	string addr;	
	string sex;
	string tele;
	int age;
};
class Contact:public Peo
{
public:
	Contact(string n, string a, string s, string t, int age) :Peo(n,a,s,t,age){}
	//具体没想好父类还可以加些啥成员变量或函数。
};

下面是创建通讯录时代码的区别:

	//(C语言版)创建通讯录 
	Contact con;
	InitContact(&con);//初始化 
    //C++版
    vector<Contact>con;

2.增加联系人

C语言版

这里添加联系人需要判断容量是否足够,如果不够需要增容。

void AddContact(Contact* pc)
{
	if(pc->sz == pc->capacity)
	{
		PeoInfo* prev = (PeoInfo*)realloc(pc->date,sizeof(PeoInfo)*(pc->capacity)*2);
		if(prev!=NULL)
		{
			pc->date = prev;
			printf("增容成功\n");
		}
		pc->capacity = pc->capacity*2;
	}
	//增加一个人信息
	printf("请输入名字:>");
	scanf("%s",pc->date[pc->sz].name);
	printf("请输入年龄:>");
	scanf("%d",&(pc->date[pc->sz].age));
	printf("请输入性别:>");
	scanf("%s",pc->date[pc->sz].sex);
	printf("请输入电话:>");
	scanf("%s",pc->date[pc->sz].tele);
	printf("请输入地址:>");
	scanf("%s",pc->date[pc->sz].addr);	
	
	pc->sz++;
	printf("增加成功\n"); 
} 

C++版

因为C++有了 vector 所以我们就省去了手动判断容量,增容的问题了。

void AddContact(vector<Contact>&con)
{
	string name;
	string addr;
	string sex;
	string tele;
	int age;
	cout << "请输入联系人的姓名:>" ;
	cin >> name;
	cout << "请输入联系人的住址:>" ;
	cin >> addr;
	cout << "请输入联系人的性别:>" ;
	cin >> sex;
	cout << "请输入联系人的电话:>" ;
	cin >> tele;
	cout << "请输入联系人的年龄:>" ;
	cin >> age;
	Contact c(name, addr, sex, tele, age);//创建一个Contact类插入容器中
	con.push_back(c);
	cout << "添加成功" << endl;
	shownumContact(con);//显示联系人数量
	return;
}

3.删除联系人

C语言版

这里注意删除成功时需要手动把联系人 sz-- 。单独封装了一个FindByName函数

void DelContact(Contact* pc)
{
	char name[MAX_NAME] = {0}; 
	if(pc->sz==0)
	{
		printf("通讯录为空,无需删除\n");
		return;
	}
	printf("请输入要删除人的名字:>");
	scanf("%s",name);
	//查找要删除的人
	int pos = FindByName(pc,name);
	if(pos == -1)
	{
		printf("要删除的不存在\n");
	 } 
	 //删除
	 int i = 0;
	 for(i = pos; i < pc->sz-1; i++)
	 {
	 	pc->date[i] = pc->date[i + 1];
	  } 
	  pc->sz--;
	  printf("删除成功\n");
}

 FindByName函数的实现:

int FindByName(Contact* pc,char name[])
{
	int i = 0;
	for(i = 0;i < pc->sz;i++)
	{
		if(strcmp(pc->date[i].name,name) == 0)
		{
			return i;
		}
	}
	return -1;//找不到 
}

C++版

这里直接用自带的erase()来删除联系人,同样的需要封装一个搜索联系人函数。

//删除联系人
void dleContact(vector<Contact>& con)
{
	auto prev = Search(con);
	if (prev == con.end())
	{
		cout << "查无此人删除失败" << endl;
		return;
	}
	con.erase(prev);
	cout << "删除成功" << endl;
	shownumContact(con);//显示联系人数
	return;
}

搜索联系人用到了迭代器等概念:

vector<Contact>::iterator Search(vector<Contact>& con)//返回一个迭代器类型
{
	string delname;
	cout << "请输入联系人的姓名";
	cin >> delname;
	for (auto iter = con.begin(); iter != con.end(); iter++)
	{
		if (iter->name == delname)
		{
			return iter;
		}
	}
	return con.end();//返回尾后表示迭代器表示没找到
}

4.查找与打印联系人

这里查找我就不单独拿出来讲了。

C语言版

打印联系人这里循环整个数组就好了:

void PrintContact(const Contact* pc)
{
 	int i = 0;
 	//打印标题
	 printf("%-20s\t %-5s\t %-5s\t %-12s\t %-20s\n","名字","年龄","性别","电话","地址"); 
	 for(i = 0;i < pc->sz; i++)
	 {
		printf("%-20s\t%-5d\t%-5s\t%-12s\t%-20s\n",pc->date[i].name,
													   pc->date[i].age,
													   pc->date[i].sex,
													   pc->date[i].tele,
													   pc->date[i].addr); 	
	 } 	
}

C++版

这里我又引入了两个新的概念范围for循环和运算符重载,这里因为我们没法用一个左移运算符去打印整个类的成员变量所以我们可以重载左移运算符。

void PrintContact(vector<Contact>& con)
{
	shownumContact(con);//打印联系人数量
	for (auto C : con)
	{
		cout << C << endl;
	}
	return;
}
ostream& operator <<(ostream& cout, Contact c){
	cout << "姓名:" << c.name << "\t" << "住址:" << c.addr << "\t"
		<< "性别:" << c.sex << "\t" << "电话:" << c.tele << "\t"
		<< "年龄:" << c.age;
	return cout;
}

5.修改联系人

C语言版

这里我们用之前封装的函数找到要修改的联系人,修改信息即可。因为与C++版差别较小就不展示代码了。

C++版

void modifyContact(vector<Contact>& con)
{
	auto prev = Search(con);
	if (prev == con.end())
	{
		cout << "要修改的联系人不存在" << endl;
		return;
	}
	cout << "请输入修改后联系人的姓名:>";
	cin >> prev->name;
	cout << "请输入修改后联系人的住址:>";
	cin >> prev->addr;
	cout << "请输入修改后联系人的性别:>";
	cin >> prev->sex;
	cout << "请输入修改后联系人的电话:>";
	cin >> prev->tele;
	cout << "请输入修改后联系人的年龄:>";
	cin >> prev->age;
}

6.排序联系人

C语言版

这里我们按照联系人姓名进行排序,我用的是一个冒泡排序。

void sort(Contact* pc)
{
	for(int i = 0;i < pc->sz-1;i++)
	{
		for(int j = 0;j < pc->sz-1-j;j++)
		{
			if((strcmp(pc->date[j].name,pc->date[j+1].name))>0)
			{
				PeoInfo tmp = pc->date[j];
				pc->date[j] = pc->date[j+1];
				pc->date[j+1] = tmp;
			}
		}
	}
}

C++版

这里我用的是C++里的sort()来进行排序,注意C++的string类型可以直接比较大小

bool cmp(const Contact&a, const Contact&b)
{
	return (a.name < b.name);
}
void sortContact(vector<Contact>& con)
{
	sort(con.begin(), con.end(), cmp);
	cout << "排序成功" << endl;
}

7.其他

在C语言的最后我们需要手动销毁开辟出来的内存。

在C++中我封装了一个打印当前联系人个数的内联函数:

inline void shownumContact(vector<Contact>& con)
{
	cout << "当前联系人数为:" << con.size() << endl;
}

8.总结

在C++版里我们总共用的新的概念有:类,vector,运算符重载,范围for循环,迭代器,内联函数等等。

C++源码:

test.cpp

#include "contact.h"
// 菜单
void menu()
{
	cout << "*****************************" << endl;
	cout << "*****0.Exit    1.add*********" << endl;
	cout << "*****2.del     3.search******" << endl;
	cout << "*****4.modify  5.sort********" << endl;
	cout << "*****6.Print   **************" << endl;
	cout << "*****************************" << endl;
}
//枚举选项
enum option
{
	Exit,
	add,
	del,
	Search,
	modify,
	Sort,
	Print
};
int main()
{
	vector<Contact>con;
	int input;
	do {
		menu();
		cout << "请选择:>";
		cin >> input;
		switch (input)
		{
		case add:
			AddContact(con);
			break;
		case del:
			dleContact(con);
			break;
		case Search:
			searchContact(con);
			break;
		case modify:
			modifyContact(con);
			break;
		case Sort:
			sortContact(con);
			break;
		case Print:
			PrintContact(con);
			break;
		case Exit:
			break;
		default:
			cout << "输入错误" << endl;
			break;
		}
	} while (input);
	return 0;
}

contect.cpp

#include "contact.h"
//添加联系人
void AddContact(vector<Contact>&con)
{
	string name;
	string addr;
	string sex;
	string tele;
	int age;
	cout << "请输入联系人的姓名:>" ;
	cin >> name;
	cout << "请输入联系人的住址:>" ;
	cin >> addr;
	cout << "请输入联系人的性别:>" ;
	cin >> sex;
	cout << "请输入联系人的电话:>" ;
	cin >> tele;
	cout << "请输入联系人的年龄:>" ;
	cin >> age;
	Contact c(name, addr, sex, tele, age);//创建一个Contact类插入容器中
	con.push_back(c);
	cout << "添加成功" << endl;
	shownumContact(con);//显示联系人数量
	return;
}
//重载运算符
ostream& operator <<(ostream& cout, Contact c){
	cout << "姓名:" << c.name << "\t" << "住址:" << c.addr << "\t"
		<< "性别:" << c.sex << "\t" << "电话:" << c.tele << "\t"
		<< "年龄:" << c.age;
	return cout;
}
//单独封装一个搜索
vector<Contact>::iterator Search(vector<Contact>& con)//返回一个迭代器类型
{
	string delname;
	cout << "请输入联系人的姓名";
	cin >> delname;
	for (auto iter = con.begin(); iter != con.end(); iter++)
	{
		if (iter->name == delname)
		{
			return iter;
		}
	}
	return con.end();//返回尾后表示迭代器表示没找到
}
//打印联系人
void PrintContact(vector<Contact>& con)
{
	shownumContact(con);//打印联系人数量
	for (auto C : con)
	{
		cout << C << endl;
	}
	return;
}
//删除联系人
void dleContact(vector<Contact>& con)
{
	auto prev = Search(con);
	if (prev == con.end())
	{
		cout << "查无此人删除失败" << endl;
		return;
	}
	con.erase(prev);
	cout << "删除成功" << endl;
	shownumContact(con);//显示联系人数
	return;
}
void searchContact(vector<Contact>& con)
{
	auto prev = Search(con);
	if (prev == con.end())
	{
		cout << "查无此人" << endl;
		return;
	}
	cout << *prev;
	return;
}
void modifyContact(vector<Contact>& con)
{
	auto prev = Search(con);
	if (prev == con.end())
	{
		cout << "要修改的联系人不存在" << endl;
		return;
	}
	cout << "请输入修改后联系人的姓名:>";
	cin >> prev->name;
	cout << "请输入修改后联系人的住址:>";
	cin >> prev->addr;
	cout << "请输入修改后联系人的性别:>";
	cin >> prev->sex;
	cout << "请输入修改后联系人的电话:>";
	cin >> prev->tele;
	cout << "请输入修改后联系人的年龄:>";
	cin >> prev->age;
}
bool cmp(const Contact&a, const Contact&b)
{
	return (a.name < b.name);
}
void sortContact(vector<Contact>& con)
{
	sort(con.begin(), con.end(), cmp);
	cout << "排序成功" << endl;
}

contect.h

#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Peo
{
public:
	Peo(string n, string a, string s, string t, int age) :name(n), addr(a),
		sex(s), tele(t), age(age) {}
	string name;
	string addr;	
	string sex;
	string tele;
	int age;
};
class Contact:public Peo
{
public:
	Contact(string n, string a, string s, string t, int age) :Peo(n,a,s,t,age){}
	//具体没想好父类还可以加些啥成员变量或函数。
};
//左移运算符重载
ostream& operator <<(ostream& cout, Contact c);
//添加联系人
void AddContact(vector<Contact>&con);
//打印联系人
void PrintContact(vector<Contact>& con);
//删除联系人
void dleContact(vector<Contact>& con);
//查找联系人
void searchContact(vector<Contact>& con);
//修改联系人信息
void modifyContact(vector<Contact>& con);
//按联系人名字排序
void sortContact(vector<Contact>& con);
//显示当前联系人数量(内联函数提高效率)
inline void shownumContact(vector<Contact>& con)
{
	cout << "当前联系人数为:" << con.size() << endl;
}

看到这里就点个关注吧~

216a9460a4cb47f2be428110faea8728.jpeg

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/777974.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

macOS 源码编译 Percona XtraBackup

percona-xtrabackup-2.4.28.tar.gz安装依赖 ╰─➤ brew install cmake ╰─➤ cmake --version cmake version 3.27.0brew 安装 ╰─➤ brew update╰─➤ brew search xtrabackup > Formulae percona-xtrabackup╰─➤ brew install percona-xtrabackup╰─➤ xtr…

提升 API 可靠性的五种方法

API 在我们的数字世界中发挥着关键的作用&#xff0c;使各种不同的应用能够相互通信。然而&#xff0c;这些 API 的可靠性是保证依赖它们的应用程序功能正常、性能稳定的关键因素。本文&#xff0c;我们将探讨提高 API 可靠性的五种主要策略。 1.全面测试 要确保 API 的可靠性…

Kubernetes 入门

Kubernetes 入门 文章目录 Kubernetes 入门一、Kubernetes 环境部署1. 环境准备2. 测试部署 Nginx3. 在任意节点使用 kubectl 二、深入 pod1. 使用配置文件部署引用2. 探针 三、资源调度1.标签与选择器2.Deployment3.StatefulSet4.DaemonSet5.HPA6. Service7. Ingress8. 配置管…

【Unity】为角色添加动画

如何添加动画 在Animations的AnimationClips文件夹下自己为角色创建一个文件夹 为角色添加Animator 然后选中上面创建的文件夹&#xff0c;拖动到上图中的Controller中 点击最上方任务栏的Window>Animation>Animation&#xff0c;这会弹出一个Animation窗口 该窗口存在时…

算法leetcode|63. 不同路径 II(rust重拳出击)

文章目录 63. 不同路径 II&#xff1a;样例 1&#xff1a;样例 2&#xff1a;提示&#xff1a; 分析&#xff1a;题解&#xff1a;rust&#xff1a;go&#xff1a;c&#xff1a;python&#xff1a;java&#xff1a; 63. 不同路径 II&#xff1a; 一个机器人位于一个 m x n 网格…

SQL_SQL_常见面试问题

问题类型 &#xff1a;SQL优化 问题描述 &#xff1a;用户浏览日志&#xff08;date, user_id, video_id&#xff09;, 统计 2020.03.29 观看不同视频个数的前5名 user_id。 思路 &#xff1a;主要注意预计算&#xff0c;避免直接去重 解决方案 &#xff1a; Hive_HQL_Hive…

【VB6|第20期】遍历Excel单元格的四种方法

日期&#xff1a;2023年7月19日 作者&#xff1a;Commas 签名&#xff1a;(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释&#xff1a;如果您觉得有所帮助&#xff0c;帮忙点个赞&#xff0c;也可以关注我&#xff0c;我们一起成长&#xff1b;如果有不对的地方&#xf…

架构实战微服务架构拆解

作业内容 拆分电商系统为微服务。 背景&#xff1a;假设你现在是一个创业公司的 CTO&#xff0c;开发团队大约 30 人左右&#xff0c;包括 5 个前端和 25 个后端&#xff0c;后端开发人员 全部都是 Java&#xff0c;现在你们准备从 0 开始做一个小程序电商业务&#xff0c;请你…

2023牛客暑期多校训练营1--K Subdivision(最短路树)

题目描述 You are given a graph with n vertices and m undirected edges of length 1. You can do the following operation on the graph for arbitrary times: Choose an edge (u,v) and replace it by two edges, (u,w) and (w,v), where w is a newly inserted vertex.…

【毕业季】九年程序猿有话说

活动地址&#xff1a;毕业季进击的技术er 九年程序猿有话说 勇敢前行&#xff0c;绽放青春&#xff0c;不负韶华&#xff01;选择IT的原因职场新人如何选择工作工作中&#xff0c;如何快速成长工作中用技术做过的最有成就感的事&#xff1f;程序员三十五岁瓶颈你怎么看&#xf…

445. 两数相加 II

445. 两数相加 II 给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。 你可以假设除了数字 0 之外&#xff0c;这两个数字都不会以零开头。 示例1&#xff1a; 输入&#xff1a;l1 [7,2,4,…

RocketMQ教程-(4)-主题(Topic)

本文介绍 Apache RocketMQ 中主题&#xff08;Topic&#xff09;的定义、模型关系、内部属性、行为约束、版本兼容性及使用建议。 定义​ 主题是 Apache RocketMQ 中消息传输和存储的顶层容器&#xff0c;用于标识同一类业务逻辑的消息。 主题的作用主要如下&#xff1a; 定义…

断路器分、合闸线圈直流电阻试验和绝缘电阻试验

断路器分、合闸线圈直流电阻试验 试验目的 对于断路器来说, 分、 合闸线圈是用于控制断路器分合闸状态的重要控制元件。 断路器停电检修时, 可以通过测试分、 合闸线圈的直流电阻来判断其是否正常。 试验设备 万用表 厂家&#xff1a; 湖北众拓高试代销 试验接线 分、 合闸线圈…

Linux系统进程概念详解

这里写目录标题 冯诺依曼体系结构操作系统(Operator System)1.概念2.目的3.管理4.系统调用和库函数概念 进程1.概念2.描述进程-PCB3.查看进程4.通过系统调用获取进程标示符5.通过系统调用创建进程-fork 进程状态1.Linux内核源代码2.进程状态查看 进程优先级1.基本概念2.查看系统…

dxf怎么转换成PDF格式?转换方法其实很简单

PDF文件是一种可靠的文件格式&#xff0c;可以在各种操作系统和软件上打开和查看。而dxf是CAD文件的一种格式&#xff0c;打开它一般都是需要相关的操作软件才能打开&#xff0c;不是特别方便&#xff0c;将dxf文件转换成PDF格式就可以很好的解决这一问题&#xff0c;下面教大家…

python:基于反卷积算法的 GEDI 波形树高特征提取

作者:CSDN @ _养乐多_ 本文将介绍如何对 GEDI(Global Ecosystem Dynamics Investigation)激光雷达数据中所标识激光测高数据点的波形数据使用反卷积算法提取树高特征。 文章目录 一、波形数据提取二、代码详细解释三、完整代码一、波形数据提取 波形数据提取参考博客:《p…

Nodejs+vue+elementui手机电脑产品维修售后服务管理系统

需求分析&#xff0c;也称为软件需求分析、系统需求分析或需求分析工程&#xff0c;是指开发人员经过充分的研究和分析&#xff0c;准确地理解用户和项目在功能、性能、可靠性等方面的具体需求&#xff0c;并将用户的非正式需求表述转化为确定系统必须执行的需求的完整定义的过…

pytorch实现图像remap

def gpu_remap(numpy_img,map_tensor):# 准备图像数据img_tensor torch.from_numpy(numpy_img).contiguous().cuda(non_blockingTrue)img_tensor img_tensor.permute(2,0,1).unsqueeze(0).float()res torch.nn.functional.grid_sample(img_tensor,map_tensor,modebilinear,p…

c语言练手项目【编写天天酷跑游戏2.0】EASYX图形库的运用。代码开源,素材已打包

天天酷跑项目的开发 项目前言 项目是基于Windows&#xff0c;easyX图形库进行开发的&#xff0c; 开发环境&#xff1a;Visual Studio 2022 项目技术最低要求&#xff1a; 常量&#xff0c;变量&#xff0c;数组&#xff0c;循环&#xff0c;函数。 文章目录 天天酷跑项目的…

单体架构与微服务架构

什么是单体架构 单体架构&#xff08;Monolithic Architecture&#xff09;是一种传统的软件架构模式&#xff0c;它将整个应用程序作为一个单一、自治的单元构建和部署。在这种架构中&#xff0c;应用程序的所有功能和组件都被集成到一个统一的代码库中。 在单体架构中&…