2020 我的C++的学习之路

以C++ Primer Plus为参考书籍,自身归纳知识点,加深记忆。

第四章 复合类型

4.1 数组

数组(array)是一种数据格式,存储多个同类型的值。声明数组应指出数组中元素的类型,元素数量以及数组名称。
声明格式:TypeName ArrayName[ArraySize] ,其中ArraySize必须为整型常量或者const值或常量表达式,即所有的值在编译时已知,不能为变量。

数组的初始化规则:① 只有定义数组才能使用初始化,不能将一个数组赋给另一个数组,但可以用数组下标分别赋值;
② 初始化数组时可以进行部分初始化,其余部分编译器默认为0;
③ C++11 新方法:初始化数组,可以省略 = 号;int ary[3] {1,2,3};
④ C++11 新方法:大括号内可为空,则所有元素均为0;int ary[4] {};//ary数组中元素初始化为0.
⑤ C++11 新方法:列表初始化禁止缩窄转换。long ary[3] {25,30,32.5};//ary[2]为float类型,浮点数转为整型是缩窄操作,小数部分的精度会丧失。

4.2 字符串

字符串是存储在内存中连续字节中的一系列字符。传统C语言中字符串末尾以空字符 ‘\0’ 结尾,但有一种更好的初始化字符串的方法,那就是直接用引号括起来字符串,这种字符串成为字符串常量(string constant)。char food[10] = "bread";引号括起的字符串隐式包括结尾的 ‘\0’ ,因此不显式包括。

字符串的输入
iostream中的cin会将键盘输入中的空格,制表符,换行符以分界线结束位置,因此在输入名字时会导致“Smith Young”只录入“Smith”一个单词。在istream中提供了面向行的类成员函数。

4.2.1 getline()
getline()读取整行,通过回车键入的换行符确定输入结尾,调用方式为 cin.geiline(arrayname,size) ,getline读取的字符数为 size-1,剩下的空间存储一个 ‘\0’。

#include<iostream>
int main()
{
	using namespace std;
	const int size = 20;
	char name[size];

	cout >> "输入英文名字: ";
	cin.getline(name,size);
	cout << "你的英文名字是: " << name << endl;

	return 0;
}

4.2.2 get()
get()接受的参数与getline()相同,同样读取到结尾,但是get()不丢弃换行符,而是将其保留在输入队列中。因此在使用get()时应考虑在键入回车时残留下的换行符,通常的解决方式为

//接上部分代码
	cout >> "输入英文名字: ";
	cin.get(name,size);
	cin.get();//读取键入后的换行符以方便下次的键入读取

另外一种方式是将两个类成员函数拼接起来,效果一样:

	cin.get(name,size).get();//cin.get()返回一个cin对象,该对象又被用来调用get(),故可以这样拼接。
	//cin.getline(name1,size).getline(name2,size)  则是读取两行分别读入到name1和name2数组中,其效果与调用两次getline()相当。

4.3 string类

要使用string类,必须包含头文件string,string类位于名称空间std中,因此需要一条using编译指令,或者std::string引用。
声明: string ArrayName,string对象和字符数组的区别就是可以将string对象声明为简单变量,而不是数组,并且类设计让程序自动处理string的大小,自动调整string的长度。string str = "amazing" ;//或采取C++11 string str = {"amazing"};“=”可以省略。

4.3.1 赋值、拼接与附加

① string对象可以赋给另一个string对象

	char food1[10];
	char food2[10] = "bread";
	food1 = food2; //编译不可通过,字符串间不能直接赋值
	string drink1 = "milk";
	string drink2;
	drink2 = drink1; //string对象的特殊性

② string简化了字符串合并,可以直接用 + 将两个string对象合并,还可以用 += 附加到对象末尾

	string str1 = "talking";
	string str2 = " to the moon";
	string str3;
	str3 = str1 + str2; //str3 = "talking to the moon"
	str1 += str2; //str1 = "talking to the moon"

4.3.2 string的其他事项

在C++新增string之前,使用头文件cstring来完成拼接等操作。
使用函数strcpy()实现字符串的复制,使用函数strcat()实现字符串附加在末尾:
strcpy(str1,str2) //将str2复制到str1中
strcat(str1,str2) //将str2接到str1的末尾
但strcat,strcpy存在安全隐患,由于str1,str2的字符数组大小已定,因此在拼接,复制过程中容易出现str1的大小过小,导致无法完整存储信息的危险,因此提供了strncpy()与strncat()函数,它们接受第三个参数为目标数组最大允许长度,但还是不如string类自动调整大小的功能。

4.3.3 string类的I/O

#include<iostream>
#include<string>
int main ()
{
	using namespace std;
	char food[20];
	string drink;
	
	cout << "Please input food name:";
	cin.getline(food,20);
	cout << "Please input drink name:";
	getline(cin,drink);
	
	return 0;
}

在引入string之前,C++就有istream类,因此没有考虑到string类型,所以没有处理string对象的方法,因此字符串常量采取cin.getline(),而string对象采取getline()。

4.3.4 其他形式的字符串字面值

① 类型wchar_t,C++11还新增了char16_t 和 char32_t,分别用前缀L、u和U表示
wchar_t food[] = L"Sssnjk JHbuihbi";
char16_t food2[] = u"Sssnjk JHbuihbi";
char32_t food3[] = U"ssnjk JHbui";
② C++11 还新增原始(raw)字符串,在原始字符串中,字符表示的就是自己,比如转义序列 \n不再是换行符而是独立的 \ 和 n。原始字面符将 "( 和 )"用作界定符,并在前标R标识。

4.4 结构简介

结构是一种比数组更灵活的数据格式,同一个结构可以存储多种类型的数据。
定义结构:

	//定义结构
	struct fish
	{
		char name[20];
		int num;
		float weight;
	}; //结尾的分号不能忘
	
	//创建结构变量
	fish Fish; //C++ 允许声明结构变量省略关键词struct,

结构的初始化

	fish Fish =
	{
		"carp"34.2
	}//使用逗号分隔,并用花括号括起,C++11中(=)可选并且不允许缩窄转换,而且花括号可以为空。

结构内可以使用string对象,但是必须让结构访问名称空间std,可以将using放在结构声明之前或者采取 std::string name。

4.4.1 结构数组

fish Fishs[20]; 此时Fishs是一个fish数组,其中的每个元素都是fish的对象,Fishs本身是个数组,而不是结构

结构数组的初始化:

	fish Fishs[2] = 
	{
		{"carp",2,1.9},
		{"salmon"46.7}
	}

4.5 共用体(联合)

共用体(union)是一种数据形式,能够存储不同的数据类型,但只能同时存储一种类型,语法与结构类似。

	union world
	{
		int cnt;
		double money;
		long maximum;
	};//共用体的长度为最大成员的长度

4.6 枚举

	enum color {red, orange, yellow, green, blue, violet, indigo};

red、orange、yellow等作为符号常量,对应整数值0~6,常量叫枚举量,枚举量为整型,可被提升为int型。

4.7 指针与自由存储空间

指针是一个变量,其存储的是值的地址,而不是值本身。 *运算符成为解引用运算符,应用于指针。

	int cnt = 8;
	int *pcnt;
	pcnt = &cnt;//对变量cnt取址,并赋予pcnt
	int *ptr = &cnt/*还有简洁写法*/

❗ 指针的声明需要与*联合使用,不能省略

	int *ptr,str;//此时声明了一个str变量与一个指向int型的指针ptr

4.7.1 分配内存

C语言中分配内存采用malloc()函数,C++也可以采用这个,同时还有更好的办法 — new运算符。

TypeName *pointer_name = new typename

#include<iostream>
int main()
{
	using namespace std;
	int cnt = 200;
	int *ptr = new int;
	*ptr = 200;
	
	cout << "cnt = " << cnt <<" location cnt = " << &cnt << endl; //cnt = 200 location cnt = 0x7ffe1ed8b8c4
	cout << "*ptr = " << *ptr << " location ptr = " << ptr <<endl;//*ptr = 200 location ptr = 0x108d010
	cout << "sizeof cnt = " << sizeof(cnt) << endl;//sizeof cnt = 4
	cout << "sizeof *ptr = " << sizeof(*ptr) << endl;//sizeof *ptr = 4
	cout << "sizeof ptr = " << sizeof(ptr) <<endl;//sizeof ptr = 8 ,64位机器的编译器指针大小为8byte,32位则为4byte

	return 0;
}

4.7.2 释放内存

C语言中与malloc()对应的释放内存函数为free(),C++中则用delete()。

	int *ptr = new int;
	delete ptr;

注意:delete必须指向new的指针对应的内存,只会释放ptr指向的内存但不会把指针ptr本身删除,delete与new配对使用,否则会导致内存泄漏,被分配的内存再也无法使用,如果内存泄露严重,程序将由于不断寻找更多内存而终止。delete不能用于释放声明变量所获的内存。

4.7.3 new 与 动态数组

数组分配内存的格式:
typename *pointername = new typenamep[num];
数组释放内存格式:
delete [] ponitername;

	int *ptr = new int[4];
	ptr[3] = 6; 
	ptr[2] = 9;
	ptr[1] = 12;
	ptr[0] = 40;

	cout << "ptr[2]= " << ptr[3] <<endl;//ptr[2] = 9
	cout << "ptr[2]= " << *(ptr+2) << endl;//ptr[2] = 9
	delete []ptr;
	return 0;

上述代码中,可以用数组表示法表示数组中元素的值 cout << "ptr[2]= " << ptr[3] <<endl;,也可以用指针表示法表示cout << "ptr[2]= " << *(ptr+2) << endl;

4.7.4 new 与 结构

new用于结构首先需要创建一个结构,然后访问其成员

	#include<iostream>
	struct fish
	{
		char name[20];
		int num;
	}int main()
	{
		using namespace std;
		fish *ptr = new fish;//new创建内存
		cout<<"Enter name of fish: ";
		cin.getline(ptr->name,20);//指针表示法表示结构
		cout<<"Enter num of fish: ";
		cin>>(*ptr).num;//常规结构表示法,*ptr是fish结构本身

		cout<<"NAME: "<<(*ptr).name<<endl;
		cout<<"NUM:  "<<ptr->num<<endl;

		delete ptr;//释放结构内存
		return 0;
	}
	

4.7.4.1 new与结构数组

structname *pointname = new structname[num]

	struct fish
	{
		char name[20];
		int num;
	}

	fish *pfish = new fish[2];//new结构数组

4.8 数组的替代品

4.8.1 模板类vector

模板类vector类似于string类,自动完成new与delete的内存管理,是new创建动态数组的替代品。要使用vector对象,头文件包含vector并且存在于名称空间std中,因此使用using编译或者using声明或者std::vector。
声明格式:
vector name(num); num可以是整型常量或者整型变量。

4.8.2 模板类array(C++11)

创建array对象需要array头文件,以及名称空间std,与数组一样,array对象长度固定,使用栈(静态内存分配),效率与数组相同,但array可以对数组进行直接赋值,arr1=arr2;
声明格式:
array<typename,num>name;,num只能为整型常量。

#include<iostream>
#include<vector>
#include<array>
int main()
{
	using namespace std;
	double cary[4] = {2.3,6.5,7.2,1.6};//传统C语言的数组的初始化
	vector<double>vary[4];
	vary[0] ={6.1};//vector对象的初始化
	vary[1] ={5.9};
	vary[2] ={7.4};
	vary[3] ={8.3};
	array<double,4>aary = {1.4,5.8,4.9,6.3};
	array<double,4>bary;
	bary = aary;//array允许数组的复制

	cout<<"aary[1~4]: "<< aary[0] <<"  "<<aary[1] <<"  "<<aary[2]<<"  "<<aary[3]<<endl;
	cout<<"bary[1~4]: "<< bary[0] <<"  "<<bary[1] <<"  "<<bary[2]<<"  "<<bary[3]<<endl;
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值