当前位置: 首页 > news >正文

C++ 对象的基础(结构及结构指针)

结构:

结构(Structure)是一种由程序员定义的,由其他变量类型组合而成的数据类型
定义一个结构的基本语法是:

struct name
{
    type varName1;
    type varName2;
};

注意后面还有一个分号


当需要处理一些具有多种属性的数据时,结构往往是很好的选择
例如编写一个个人信息管理程序时,涉及到的基本特征有:名称、账号、性别等

struct IDmation
{
	//声明三个成员变量 
	string name;
	string ID;
	char sexual;
};

C++对于一个结构所能包含的变量的个数是没有限制的,那些变量通常我们称为该结构的成员,他们可以是任意一种合法的数据类型


结构的用法 先定义结构 之后用 "."点符号或 "->"指向符 对结构成员进行赋值

IDmation IDdata;//定义一个IDmation类 名为IDdata的IDmation类结构变量(相当于让IDdata有了IDmation所定义的数据结构)
IDdata.name="TaylorDurden";
IDdata.ID="FightClub";
IDdata.sexual='M';

如果我们在创建一个结构类型变量的时候就已经知道它的各个成员相关的值,我们可以在声明新变量的同时进行结构体初始化例如:

IDmation IDinit = {"TylerDurden","DoNotTalkAbout",'M'};

结构与指针

创建一个指向该结构的指针:
C和C++中指针无所不能 既可以指向结构 就像指向其他任何变量

IDmation IDdata;//建立一个名为IDdata的结构体变量名
IDmation *Pmation=&IDdata;//建立一个结构体变量名为Pmation的结构体指针 指向结构体实例变量IDdata

因为指针的类型必须与指向的地址的变量的类型一致 所以Pmation指针的类型也是IDmation


有两种方法来访问结构指针里面的变量值

第一种:可以通过指针进行解引用来访问相应的变量值(相当于直接用结构体变量名进行访问)

(*Pmation).name="TylerDurden";

第二种: 通过 -> 指向符进行访问

Pmation->name="TylerDurden";

什么时候用“.”,什么时候用“->”呢,就是说前面如果是指针解引用或结构体变量名的话就是用“.”,前面如果是指针的话就用“->”


C++结构体详解https://blog.csdn.net/Chroniccandy/article/details/108071395

案例
定义一个结构体
1.要求存储 姓名 账号 性别等信息
2.实现用户数据文件的读取存储
3.将用户数据和功能界面打印到屏幕

1.首先进行用户数据的初始化

INITmation();//进行 用户数据的初始化

在这里插入图片描述
结构体数据(或文件)写入函数INITmation()
在这里插入图片描述
在这里插入图片描述
至此 结构体已经并初始化完毕 并将结构体内的参数 按照结构体的格式 输出到了用户文件中 等待用户读取


2.用户数据的初始化完毕后 进入系统界面 等待用户选择功能
在这里插入图片描述
用户界面
在这里插入图片描述


3.用户选择选项1 进行用户文件数据的打印
在这里插入图片描述
case 1 (选项1) 中调用 ReadMation()函数进行用户数据文件的读取

结果

在这里插入图片描述


3.用户选择选项2 进行用户数据的录入 以及 用户数据的保存在这里插入图片描述
case 2 (选项2) 中调用 RecordMation()函数WriteMation函数 进行用户数据的录入和保存

结果
在这里插入图片描述


完整代码

#include <iostream>
#include <fstream>
#include <string>
#include <windows.h>//为了使用sleep()函数

using namespace std;

//定义结构体
//创建结构包括两步 1..定义结构描述——它描述并标记了能够存储在结构中的各种数据类型 2.按描述创建结构变量(结构数据对象)



//todo建立名为IDmation的结构体 (结构体只会声明成员变量)
struct IDmation
{
	//声明三个成员变量 
	string name;
	string ID;
	char sexual;
}wangmazi;//todoC++ 结构变量 声明可以在定义结构后面声明

//它的本质是创建了一个名为IDmation的新的数据类型
//结构体成员默认为 public 所以它们可以被直接访问,并且可以像常规变量一样使用


//todoC++结构变量声明
struct IDmation lisi;

//todoC++允许在声明结构变量时省略关键字 例如   (lisi zhangsan wangmazi均为做演示用没有实际意义)
IDmation zhangsan;


bool INITmation();//数据初始化
bool ReadMation();
void RecordMation();
bool WriteMation(IDmation* Pmation);

//todo案例 定义一个结构 至少存储 : 姓名 身份证 性别  并实现文件数据的存储 并打印数据到屏幕
int main()
{

	INITmation();//进行 用户数据的初始化

	int i;
	while (1)
	{
			
				cout << "欢迎使用ID注入查询系统" << endl;
				cout << "1.打印数据到屏幕" << endl;
				cout << "2.录入数据到TXT文件中" << endl;
				cout << "3.退出程序" << endl;
				
				cin >> i;//todo i 准备接收 相应的值 此值作为选择功能的区分依据

				switch (i)//等待用户键入i的值 以i的值为选择根据
				{
				case 1://功能一 读取用户信息并显示
					if (ReadMation())//todo使用带有bool类型返回值的读取文件子函数 读取存储用户信息的txt文件中的用户数据 并显示到屏幕上 (返回值为真 成功读取 返回值为假 读取失败)
					{
						cout << "成功读取文件" << endl;
					}
					else
					{
						cout << "读取文件失败" << endl;
					}
					break;
				case 2://功能二 录入用户信息 到 用户信息文件中
					RecordMation();
					break;
				case 3:
					return 0;
				}
	}
}

bool INITmation()//数据初始化
{
	IDmation IDinit = {"TylerDurden","DoNotTalkAbout",'M'};
	//todo使用初始化列表 初始结构体变量 (初始结构体变量的另一种方法为构造函数初始化结构体)
	//初始化结构体变量成员的最简单的方法是使用初始化列表。初始化列表是用于初始化一组内存位置的值列表。列表中的项目用逗号分隔并用大括号括起来
	//注 : 也可以仅初始化结构体变量的部分成员 
	//注:如果某个结构成员未被初始化,则所有跟在它后面的成员都需要保留为未初始化。使用初始化列表时,C++不提供跳过成员的方法
	//注:不能在结构体声明中初始化结构体成员,因为结构体声明只是创建一个新的数据类型,还不存在这种类型的变量

	if (WriteMation(&IDinit) == false)//调用录入用户数据函数WriteMation 并将结构体变量 IDinit作为形参传递初始化的结构信息到WriteMation函数中 
	//如果WriteMation函数返回false(即未能成功打开用户数据文件) 则初始化用户数据失败
	{
		cout << "初始化失败" << endl;
		return true;
	}
	else
	{
		return false;
	}
}


bool ReadMation()//建立读取用户数据的子函数 此函数为带有bool类型返回值的函数
{	
	string temp;//建立字符串对象 等待存储打开的文件流的整行数据
	ifstream fileInput("mation.txt");//用文件流类的构造函数来打开文件

	if (fileInput.is_open())
	{
		cout << "\n正在输入记录数据...";
		for (int i = 0; i <= 100; i++)
		{
			cout.width(3);//防止进度条数组 在显示的过程中不断向左靠齐刷新 (因为cout.width的默认对齐方式为右对齐)
			cout << i << "%";//width只影响他设置后的下一个输出,再下一个字段输出后,后继的字段被恢复为默认值  
			
			//cout <<"正在输入记录数据... "<<i<< "% "<<"\r";//简易的方法实现数组刷新
		
			Sleep(10);
			cout << "\b\b\b\b";
			// '\b'为C++ 中的的转义字符 进行输出后的退格操作 在使用\b进行退格的操作的时候 实际上每次使用’'\b' 之后 就相当于按下了退格键
			//想要删除几个字符就要使用至少几个'\b'  这里的\b\b\b\b起到了把之前的数据清除 达到进度条数据循环显示的效果
		}

		//todo关于 cout.width 控制输出宽度 成员函数 (cout.width的默认对齐方式为右对齐)
		//该函数有两个版本,一个带参数的,一个不带参数的,如下
		//cout.width(整型参数)  函数是设置指定的输出宽度,该宽度值必须是有效的:大于0 且宽度不足时 缺少的字符用空格补足
		//cout.width(无参数)  将显示当前的字段宽度(显示宽度的前提是设置好了输出宽度  是显示设置的输出宽度 不是输出流字符中的宽度)

		//例如 cout.width(n); 意为输出n-1个字符 字符自动右对齐 左边用空格补上缺少的字符  视字符中的空格为读取断开
		//即遇到空格时认为读取完一块 再读取下一块  热如果字符串长度大于n 则全部读取到下一个空格读完一块

		cout << endl;

		cout << "姓名   " << "  身份证   " << "性别   " << endl;

		while (getline(fileInput, temp))//使用getline函数读取整行 包括前导和嵌入的空格 并将其存储在字符串对象(temp)中
		{
			cout << temp;
			cout << endl;
			//todo文档读取完毕将自动跳出循环 (因为文档尾部有EOF文档结束标志位 当此标志位被读取 getline函数返回值为false 即跳出循环 表示读取完毕)
		}
		//todo关于getline函数 getline(cin, inputLine);
		//getline函数一共两个参数 其中cin是正在读取的输入流 而inputLine是接收输入的字符串string变量 的名称 

		cout << endl;

		return true;//当程序运行至此 则说明输入选项1后 文件读取显示的工作已经成功完成 则可以返回一个true 表示成功
	}
	else
	{
		return false;//如果文件不存在或者未能成功打开 返回一个false标志位 表示此项工作失败
	}
}


void RecordMation()//建立录入用户数据的子函数 此函数为带有bool类型返回值的函数
{
	char goon, save;//建立两个字符型变量  
	IDmation IDdata;//建立一个IDmation类 名为IDdata的IDmation类结构变量(相当于让IDdata有了IDmation所定义的数据结构) 
	IDmation *Pmation;//建立一个IDmation类 名为Pmation的IDmation类 指针结构变量 

	goon = 'Y';//初始化goon值为Y 
	while ('Y' == goon)//进入录入用户信息的循环 直到goon的值不为Y 
	{
		//todo访问结构体成员
		cout << "请输入姓名"<<"    ";
		cin >> IDdata.name;//首先写入 IDdata结构变量中的.name成员 (name为string类型的字符串)
		cout << "请输入ID账号" << "    ";
		cin >> IDdata.ID;//(name为string类型的字符串)
		cout << "请输入性别" << "    ";
		cin >> IDdata.sexual;//(sexual为char类型的字符)

		//结构体成员的访问方式与类的公共成员一样,都是使用点运算符 
		//注:类的数据成员通常是私有的,必须通过函数访问 因为结构数据成员是公共的,所以它们可以被直接访问,并且可以像常规变量一样使用
		//todo什么时候用“.”,什么时候用“->”呢,就是说前面如果是指针解引用的话就是用“.”,前面如果是指针的话就用“->”

		cout << "录入成功 请问是否保存(Y/N)";
		
		cin >> save;//save字符型变量接收键盘的值

		if('Y'==save)//如果键盘输入Y字符 则进行输入数据的保存
		{
			Pmation = &IDdata;//此时将建立的指针类型Pmation指向之前输入的包含了name ID sexual三个结构体成员的 结构变量IDdata 
			if (WriteMation(Pmation))//以指向包含用户数据的结构变量IDdata的指针Pmation为形参 传输输入的数据 到 写入数据 子函数WriteMation中 (此函数为带有bool类型返回值的函数)
			{
				cout << "成功写入文件" << endl;
			}
			else
			{
				cout << "写入文件失败" << endl;
			}
		}
		else
		{
			return;
		}
		cout << "\n请问需要再次输入吗?(Y/N)";
		cin >> goon;//再次给goon赋值 以进行循环 
	}
}

bool WriteMation(IDmation* Pmation)//建立录入用户数据的子函数 下  进行录入工作的子函数 此函数为带有bool类型返回值的函数
// (此函数的实参为之前录入用户数据函数中定义的IDmation结构体的IDdata结构变量的数据 将结构体变量以指针的方式进行 值传递)
{
	ofstream fileOutput("mation.txt", ios::app);//todo打开存放用户数据的文件夹 并 将使用方法设为ios::app (即在老数据尾部追加新数据)

	if (fileOutput.is_open())//如果打开文件夹成功 
	{
		fileOutput << Pmation->name << "  ";//将之前输入的结构体变量的数据前方加上空格(起到间隔作用)后 流向 打开的文件流对象fileOutput中
		fileOutput << Pmation->ID << "  ";
		fileOutput << Pmation->sexual << endl;//结束后记得使用换行符 方便下一个数据的输入
		//访问结构体变量(结构体变量为指针形式时 访问符用“->”)

		return true;//返回一个为真的bool值 向case2中程序说明 用户数据录入的工作已经完成
	}
	else//如果文件未能打开 返回录入失败的信息
	{
		cout << "数据保存失败" << endl;
		return false;
	}

}

关于char和string的区别
1.char是字符类型, String是字符串类
2.String字符串是用来包含串的, char是用来包含单字符的

C++结构体基础知识
https://www.cnblogs.com/jiyi-conding/p/11342144.html
关于C++中转义字符 ‘\b’ 退格字符的使用方法及其原理
https://www.cnblogs.com/cppskill/p/12756107.html

相关文章:

  • 《Linux内核设计与实现》读书笔记(三)- Linux的进程
  • C++联合枚举和类型别名
  • while循环与中断语句break、continue、return以及goto的使用
  • CentOS使用Screen管理会话选项
  • 循环程序跳出(_kbhit()、getch() 、getchar())
  • C++ 类与对象
  • (转) Android中ViewStub组件使用
  • C++ 构造函数与析构函数
  • MFC应用程序中处理消息的顺序,创建窗口的过程关闭窗口的顺序(非模态窗口),打开模式对话框的函数调用顺序...
  • C++ this指针 与 类的继承
  • OpenGL_Qt学习笔记之_07(闪烁的星星)
  • C++ 继承机制中的构造器与析构器
  • C#数组
  • C++ 访问控制
  • ASA842配置内网DNS欺骗测试
  • [LeetCode] Wiggle Sort
  • Go 语言编译器的 //go: 详解
  • Java Agent 学习笔记
  • laravel5.5 视图共享数据
  • Spark VS Hadoop:两大大数据分析系统深度解读
  • vue和cordova项目整合打包,并实现vue调用android的相机的demo
  • vue学习系列(二)vue-cli
  • 创建一种深思熟虑的文化
  • 构建二叉树进行数值数组的去重及优化
  • 基于Dubbo+ZooKeeper的分布式服务的实现
  • ​iOS实时查看App运行日志
  • (1)(1.8) MSP(MultiWii 串行协议)(4.1 版)
  • (17)Hive ——MR任务的map与reduce个数由什么决定?
  • (8)STL算法之替换
  • (C语言)逆序输出字符串
  • (附源码)ssm户外用品商城 毕业设计 112346
  • (接口封装)
  • (一) storm的集群安装与配置
  • (原创)攻击方式学习之(4) - 拒绝服务(DOS/DDOS/DRDOS)
  • ./和../以及/和~之间的区别
  • .NET Core Web APi类库如何内嵌运行?
  • .NET Framework Client Profile - a Subset of the .NET Framework Redistribution
  • .NET/C# 判断某个类是否是泛型类型或泛型接口的子类型
  • .net实现头像缩放截取功能 -----转载自accp教程网
  • .vue文件怎么使用_我在项目中是这样配置Vue的
  • /var/lib/dpkg/lock 锁定问题
  • ?.的用法
  • @angular/cli项目构建--http(2)
  • @FeignClient注解,fallback和fallbackFactory
  • @JSONField或@JsonProperty注解使用
  • [<死锁专题>]
  • [3D基础]理解计算机3D图形学中的坐标系变换
  • [C++]priority_queue的介绍及模拟实现
  • [Eclipse] 详细设置护眼背景色和字体颜色并导出
  • [flink总结]什么是flink背压 ,有什么危害? 如何解决flink背压?flink如何保证端到端一致性?
  • [HJ56 完全数计算]
  • [HTML]Web前端开发技术29(HTML5、CSS3、JavaScript )JavaScript基础——喵喵画网页
  • [Java] 什么是IoC?什么是DI?它们的区别是什么?
  • [LeetCode]—Copy List with Random Pointer 深度复制带“任意指针”的链表
  • [leetcode]Flatten Binary Tree to Linked List