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

news2025/3/10 10:02:06

目录

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

看到这里就点个关注吧~

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

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

相关文章

第 5 章 Spark Shuffle 解析

第 5 章 Spark Shuffle 解析 5.1 Shuffle 的核心要点1. 数据分区&#xff1a;2.数据传输&#xff1a;3. 数据排序&#xff1a;4.数据聚合&#xff1a;5. 数据重分发&#xff1a;6.数据持久化&#xff1a;5.1.1 ShuffleMapStage 与 ResultStage 5.2 HashShuffle 解析5.2.1 未优化…

KUKA机器人_外部安全条件不满足时,如何操作机器人的方法

KUKA机器人_外部安全条件不满足时&#xff0c;如何操作机器人的方法 如果大家在做项目时&#xff0c;控制系统尚未完成&#xff0c;外部紧急停止等安全条件尚未满足时&#xff0c;但是此时想操作或移动机器人&#xff0c;有办法吗&#xff1f; 答案是有。 具体的方法可参考以…

驾驶证——科目一笔记(二)

知识点1&#xff1a;通行规定 有加速&#xff08;x&#xff09; 各种礼让&#xff08;√&#xff09; 减速慢行、减速靠右、减速或停车、停车避让&#xff08;√&#xff09; 不用减速慢行、无需减速、不必减速&#xff08;x&#xff09; 不得&#xff08;√&#xff09; …

【文档模板】产品故障分析报告

今天和大家分享产品故障分析报告的文档模板。产品故障分析报告是一份文件&#xff0c;通常由技术团队、工程师或相关专业人员编写&#xff0c;用于详细描述和分析出现在系统、设备、产品或服务中的故障原因和根本原因。这些报告旨在对故障进行系统性的研究&#xff0c;以便团队…

Windows沙盒的安装与配置

沙盒安装 1、打开控制面板 2、选择程序与功能 3、勾选Windows 沙盒&#xff0c;然后点击确定&#xff0c;等待安装完成即可。 沙盒配置 Windows 沙盒支持简单的配置文件&#xff0c;这些文件为沙盒提供最少的自定义参数集。 此功能可与 Windows 10 内部版本 18342 或 Windows…

数据库管理-第九十二期 一周故障汇总(20230717)

第九十二期 一周故障汇总&#xff08;20230717&#xff09; 距离上一篇已经过了整整一周了&#xff0c;平时我虽然不是生产队的驴&#xff0c;但是一周一篇以上的数量还是维持了一段时间了。为啥上周只写了一篇&#xff0c;因为各种故障、各种保障、各种割接忙了整整一周&…

数据分析师:解读数据背后的故事

数据在当今信息时代中扮演着至关重要的角色&#xff0c;而数据分析师则是解读和发掘数据中隐藏信息的关键人物。作为数据分析师&#xff0c;他们运用统计学、机器学习和数据可视化等技术手段&#xff0c;从海量的数据中提取出有价值的信息和洞察&#xff0c;并将其转化为可供决…

大数据学习02-Hadoop分布式集群部署

操作系统&#xff1a;centos7 软件环境&#xff1a;jdk8、hadoop-2.8.5 一、创建虚拟机 1.下载VMware,建议支持正版 2.安装到Widows目录下任意位置即可&#xff0c;安装目录自定义。打开VMware&#xff0c;界面如下&#xff1a; 3.创建虚拟机 创建虚拟机—>选择自定义 …

kafka消息队列最常用的两种模式,以及应用场景

目录 一、发布-订阅模式 二、点对点模式 三、应用场景 一、发布-订阅模式 发布-订阅模式是最常见的消息传递模式&#xff0c;其中消息发布者将消息发送到一个或多个主题&#xff08;Topic&#xff09;&#xff0c;而订阅者可以选择订阅一个或多个主题来接收消息。每个订阅者…

在嵌入式系统开发培训中常用的数据库有哪些种?

数据库是一种储存和管理、组织数据的仓库&#xff0c;在嵌入式开发当中起到至关重要的作用。一个在嵌入式培训中&#xff0c;我们可学习使用的数据库有多种&#xff0c;每种数据库都会呈现出不同的一面&#xff0c;那么我们在嵌入式系统开发培训中可用到的数据库都有哪几种&…

JQuery(二):DOM操作、动画、遍历、事件绑定

1.DOM操作 1.1内容操作 html(): 获取/设置元素的标签体内容 <a><font>内容</font></a> --> <font>内容</font>text(): 获取/设置元素的标签体纯文本内容 <a><font>内容</font></a> --> 内容val()&am…

RK3588+FPGA视频实时处理与双屏显示、存储解决方案

主板平台的主要功能电路示意图 在ARM端: 脚踏开关是电平输入10 口&#xff0c;双路。 触摸面板与主板的连接方式为 UART 外加12V 电源。 键盘为自开发产品&#xff0c;通过USB透传 UART&#xff0c;并传递12V电源USB、千兆网络为主板上的接口&#xff0c;USB 为3.0版本host 接口…

Hadoop 之 单机部署和测试(一)

Hadoop单机部署和测试 一.单机部署1.安装 JDK&#xff08;JDK11&#xff09;2.安装 HADOOP3.测试 一.单机部署 系统版本&#xff1a;cat /etc/anolis-release1.安装 JDK&#xff08;JDK11&#xff09; #!/bin/bashTOP_PATH$(pwd) JAVA_PATH/usr/local/java FILEls $TOP_PATH/…

【Linux | Shell】结构化命令2 - test命令、方括号测试条件、case命令

目录 一、概述二、test 命令2.1 test 命令2.2 方括号测试条件2.3 test 命令和测试条件可以判断的 3 类条件2.3.1 数值比较2.3.2 字符串比较 三、复合条件测试四、if-then 的高级特性五、case 命令 一、概述 上篇文章介绍了 if 语句相关知识。但 if 语句只能执行命令&#xff0c…

兴达易控modbus转profinet网关与三菱变频器通讯

本案例分享兴达易控modbus转profinet网关&#xff08;MDPN100&#xff09;连接西门子1200plc&#xff0c;实现三菱变频器485通讯兼容转modbusTCP通信&#xff0c;在博图中配置。 拓展图 打开博图&#xff0c;并添加PLC 加载由兴达易控免费提供的modbus转profinet GSD文件 安装网…

基于MSP432P401R送药小车【2021年电赛F题】

文章目录 一、任务清单1. 硬件部分2. 软件部分 二、神经网络训练1. 创建数据集2. 数据采集3. 数字训练 三、OpenMV数字及其坐标识别四、巡线1. 直行2. 转向3. 停止 五、路口判断与原路径返回六、技术交流 由于前边已经用MSP430做过一遍该赛题了&#xff0c;这里就不再重复叙述赛…

Java培训:什么是Busy spin?为什么要使用Busy spin?

Busy spin(繁忙自旋)是一种线程等待的技术&#xff0c;它通过循环检查条件来等待某个事件或条件的发生&#xff0c;而不进行阻塞或休眠。 通常情况下&#xff0c;线程等待事件发生的方式是使用阻塞或休眠操作&#xff0c;这样线程会释放CPU资源&#xff0c;其他线程可以继续执行…

Qt6 Qt Quick UI原型学习QML第二篇

Qt6 Qt Quick UI原型学习QML第二篇 界面效果QML语法语法讲解核心要素项目元素矩形元素文本元素图像元素MouseArea元素 界面效果 QML语法 import QtQuick 2.12 import QtQuick.Window 2.12Window {id: rootvisible: truewidth: 640height: 480title: qsTr("QML学习第二篇&…

【题解】 模拟赛2 题解

T1 假设商品价格为x 618:int(x*0.66) 211:x-(x/100)*35 两者比较一下大小即可 #include<bits/stdc.h> using namespace std;int x,x1,x2;int main(){scanf("%d",&x);x1 x*0.66;x2 x-(x/100)*35;if (x1 x2) printf("both\n%d",x1);if (x1 &g…

浏览器打开PDF标题乱码

问题 使用 itext5 用pdf模板生成预览pdf乱码问题 解决办法 使用pdf编辑器打开之后&#xff0c;选择 文件>> 属性&#xff0c; 修改乱码的标题。