文章目录
- 前言:
- 1 数组
- 1.1数组的初始化规则
- 1.2 C++11的数组初始化方法
- 2 字符串
- 2.1 拼接字符串常量
- 2.2在数组中使用字符串
- 2.3 字符串输入
- 2.4 每次读取一行字符串输入
- 2.5 混合输入字符串和数字
- 3 string类简介
- 3.1 C++11字符串初始化
- 3.2 赋值、拼接、附加
- 3.3 string类的其他操作
- 3.4 string类I/O
- 4 结构简介
- 4.1 在程序中使用结构
- 4.2 C++11结构初始化
- 4.3 结构可以将string类的关系
- 4.4 其他结构属性
- 4.5 结构数组
- 4.6结构中的位字段
- 5 共用体
- 6 枚举
- 6.1 设置枚举值的值
- 6.2 枚举的取值范围
- 7指针和自由存储空间
- 7.1声明和初始化指针
- 7.2指针的危险
- 7.3指针和数字
- 7.4使用new来分配内存
- 7.5使用delete释放内存
- 7.6使用new来创建动态数组
- 8指针、数组和指针算数
- 8.1程序说明
- 8.2指针小结
- 8.3指针和字符串
- 8.4使用new创建动态结构
- 8.5自动存储、静态存储和动态存储
- 9 类型组合
- 10 数组的替代品
- 10.1模板类vector
- 10.2模板类array(C++11)
- 10.3 比较数组,vector对象,array对象
- 11 总结
- 12 参考
前言:
第三章介绍了基本的数据类型:整型与浮点型,相对来说比较基础,但是不足以应付实际的复杂情况,为了更加灵活地使用数据,语言开发者推出了复合类型。
1 数组
当你要记录班级中同学的身高时,之前的方法,班级有多少人,你就要创建多少个int类型的变量,然后一个一个地记录下来。这很繁琐,效率也很低;生活中类似的场景很多,这时候需要一个结构来存储同种类型的变量,应这种实际开发需求,诞生了数组这种变量类型。
数组是一种数据格式,能够存储多个同类型的数值。要创建数组需要使用声明语句。需要声明三点:
- 1)存储在每个元素中的类型;
- 2)数组名称;
- 3)数组中的元素个数;
例子:
short Months[12]
数组的名称为Months,数组一共有12个元素,每个元素存储的类型是short类型。
注意:在编写程序的过程中,不会检查数组的下标是否有效,编译时不会出错但在实际运行过程中可能会引发问题。
1.1数组的初始化规则
- 1)只有在定义数组时才能进行初始化,不能先声明然后整体再进行初始化;
- 2)如果只对一部分元素进行初始化,剩余的元素都被设置为0;
- 3)初始化数组不声明元素个数,C++编译器将计算元素个数;
1.2 C++11的数组初始化方法
- 1)初始化数组时可以省略“等号”运算符;
- 2)可以不在大括号内包含任意东西,默认所有元素都是0;
- 3)列表初始化禁止缩窄“转换”。
2 字符串
代码是为了处理现实世界中的工作,不可能只有数字而没有字符,还是举之前的例子,在对班级同学的成绩做记录时,只记录成绩毫无意义,要把这个成绩背后的名字也记录下来,这样之前的数字才有意义,所以字符串是非常重要的数据类型,它可以帮助我们处理和操作各种文本数据,并且可以通过标准库中提供的函数轻松地完成各种文本操作。
字符串是存储在内存的连续字节的一系列字符。即字符串是存储在char数组中的,空字符被写作“\0”,同时字符串也是以\0进行结尾的。
2.1 拼接字符串常量
有时候,单个字符串过于冗长,C++允许拼接字符串的字面值,即将两个用引号括起来的字符串合并为一个。
2.2在数组中使用字符串
要将字符串存储到数组中,常用的有两种方法:
1)将数组初始化为字符串常量;
2)将键盘或文件输入读入到数组中;
书中给出了示例程序,用了“sizeof”与”strlen”,区别是:”sizeof”计算整个数组的长度,而“strlen”只是计算可见的字符,并不把空字符算在内。
2.3 字符串输入
在示例的程序中,输入了两个单词,后续便直接将这两个单词赋值给两个变量,然后立马显示最后一行。通过cin完成字符的输入,cin使用空白(空格,制表符,换行符)来确定字符串的结束位置,这意味着cin在获取字符串数组输入时只读取一个单词。读取该单词后,cin将该字符串放到数组中,并自动在结尾添加空字符。
2.4 每次读取一行字符串输入
有时候不一定按单词个数进行读取,也可以按行进行读取。istream中的类提供了一些面向行的类成员函数:getline()和get()。
-
1)面向行的输入:getline()
getline()读取整行,它使用通过回车键输入的换行符来确定输入结尾。
cin.getline()有2个参数,第一个参数用来存储输入行的数组的名称,第二个参数是要读取的字符数。getline()函数每次读取一行,他通过换行符来确定行尾,但不保存换行符,在存储字符串时,他将空字符来代替换行符。
-
2)面向行的输入:get()
连续调用2次cin.get()示例:
cin.get(name,ArSize)
cin.get(dessert,ArSize)
由于第一次调用,换行符留在输入队列中,因此第二次调用时看到的第一个字符便是换行符。cin.get()会认为已经到达行尾,而没有发现任何可读取的内容。
解决办法是:用cin.get()来处理换行符。
3)空行和其他问题
当使用getline()或者get()读取空行时,下一条输入语句将在前一句getline()或者get()结束读取的位置开始读取。但这意味着接下来的输入将被阻断,可以用cin.clear()进行恢复。
2.5 混合输入字符串和数字
书中给出了示例代码,在混合输入的情况下,有些输入无法实现。在第一次读取过程中,按回车键生成的换行符留在了输入队列中,后面的cin.getline()看到换行符之后以为是一个空行,所以后续的输入便无法实现。解决方法是:在读取地址之前先读取并舍弃换行符,这样便能解决这个问题。
3 string类简介
通过添加string类扩展了C++库,以后便可以使用string类的对象来存储字符串。书中给出了示例来介绍string类的用法。从中我们可以得知:
1)可以使用C风格初始化string对象;
2)可以使用cin将键盘输入存储到string对象中;
3)可以使用cout来显示string对象;
4)可以使用数组表示法来访问存储在string对象中的字符。
3.1 C++11字符串初始化
可以用字符数组,string类方法进行初始化2种方法:
char a[] = {“aaaaa”};
string b = {“bbbbbb”};
3.2 赋值、拼接、附加
赋值:可以将一个string对象赋值给另一个string对象;
拼接:直接用+运算符,将两个字符串相加。
3.3 string类的其他操作
C语言风格字符串对字符串进行操作的时候,提供了一些函数,strcpy用于函数的复制,strcat用于函数的拼接;strlen()函数用于获得字符串的长度。
3.4 string类I/O
当输入为一个简单的单词的时候,是用简单的cin,cout运算符,当要读取一行输入内容而不是一个单词的时候,可以用getline()来获取。
4 结构简介
结构是一种比数组更灵活的数据格式,因为同一个结构可以存储多种类型的数据,从而将数据的表示合并到一起。结构是用户定义的类型,而结构声明定义了这种类型的数据属性。定义了类型后,便可以创建这种类型的变量。所以创建结构包括两步:
(1)定义结构描述,描述并标记了能够存储在结构中的各种数据类型;
(2)按描述创建结构变量。
结构描述的组成部分
4.1 在程序中使用结构
书中给出了示例代码,声明了一个结构体,并调用了结构体对象。C++中建议将结构体声明在外部,这样各个函数都能使用。
4.2 C++11结构初始化
C++11支持结构体进行列表初始化;如果大括号里不包含任何东西,各个成员都被设置为0.
4.3 结构可以将string类的关系
可以,将之前的char数组转化为string,更加好用。
4.4 其他结构属性
可以使用赋值运算符,将结构赋值给另一个同类型的结构体,这种赋值称为成员赋值。介绍了一些初始化的特殊方法,不建议使用,结构体的声明,初始化,使用按部就班的来。
4.5 结构数组
顾名思义就是元素全都是结构体的数组,方法和创建基本类型的数组完全一致;书中给出了代码示例。
4.6结构中的位字段
允许指定占用特定位数的结构成员,使得结构体与硬件上的寄存器相对应。
5 共用体
共用体是一种数据格式,它能存储不同的数据类型,但只能同时存储其中的一种类型。使用共同体,当数据项使用两种或者更多格式的时候,可以节省空间。
6 枚举
enum工具提供了一种创建符号常量的方式,允许定义新类型,但必须按照严格的限制进行。
6.1 设置枚举值的值
可以使用赋值运算符来显示地设置枚举量的数值。指定的数值必须是整数,也可以只显示地定义其中一些枚举量的数值。
补充:可以创建多个数值相同的枚举量。
6.2 枚举的取值范围
C++11扩展了枚举,增加了作用域内枚举;C++的枚举范围更加灵活,下限一般情况是0,上限由最大的枚举数值决定,由大于这个数值的,最小2次幂确定。例如枚举中一个数值为108,大于108的最小2次幂是128,此时最大枚举数值便是127,枚举范围为[0,127]。
7指针和自由存储空间
计算机存储数据需要明确的3种基本属性:
(1)信息存储在何处
(2)存储的值为多少
(3)存储的信息是什么类型
指针是C++语言的精髓,只有灵活地使用指针,才能真正掌握C++语言。
7.1声明和初始化指针
书中给出了示例程序,声明和初始化了指针。
7.2指针的危险
在C++中创建指针时,计算机将分配用来存储地址的内存,但不会分配存储指针所指向数据的内存。
7.3指针和数字
指针的表示形式是数字,表示的意义是位置。
7.4使用new来分配内存
为一个数据对象获得并指定分配内存的通用格式:
typename * pointer_name = new typeName
7.5使用delete释放内存
一定要配对地使用new和delete,否则会发生内存泄漏。
7.6使用new来创建动态数组
- 1、使用new来创建动态数组
- 2、使用动态数组
8指针、数组和指针算数
指针和数组基本等价的原因在于指针算术和C++内部处理数组的方式。书中给出了示例程序验证了这一点。
8.1程序说明
C++将数组名解释为第一个元素的地址。
8.2指针小结
1、声明指针
2、给指针赋值
3、对指针解除引用
4、区分指针和指针所指向的数值
5、数组名
6、指针算术
7、数组的动态联编和静态联编
8、数组表示法和指针表示法
8.3指针和字符串
主要介绍了strcpy函数,strcpy函数暗暗包含了new的操作,虽然是复制,内容会进行复制,但是变量地址的值是全新的。
8.4使用new创建动态结构
书中给出了示例程序。
8.5自动存储、静态存储和动态存储
分别对应自动变量,静态变量;new和delete运算符,共同管理一个内存池,使得数据的生命周期不完全受程序或函数的生存时间控制。
9 类型组合
第四章介绍了数组,结构以及指针,书中给了一个示例,来对他们进行访问。来看其中四个cout。
1、trio->year
trio是结构体数组的首地址,打印出来的是trio[0].year;
2、arp[1]->year
打印的是s02.year
3、(*ppa)->year
声明的ppa是一个指向指针地址的指针,打印的是s01.year;
4、(*(ppb+1))->year
打印的是s02.year.
10 数组的替代品
模板类vector与array是数组的替代品。
10.1模板类vector
在C++中,vector是一个标准库容器,用于存储和管理动态大小的元素序列。它提供了许多内置的函数和操作符,使得元素的插入、删除和访问变得非常方便。
vector的主要作用包括:
- 动态大小:vector可以根据需要动态调整大小,可以在任意位置插入或删除元素,而不需要手动管理内存。这使得它比数组更具灵活性。
- 高效的随机访问:vector中的元素在内存中是连续存储的,因此可以通过索引快速访问任何元素。这使得vector非常适合需要频繁随机访问的场景。
- 尾部插入和删除:vector提供了push_back()和pop_back()等函数,可以高效地在尾部插入和删除元素。这对于实现栈(stack)和队列(queue)等数据结构很有用。
- 可以使用迭代器遍历:vector支持使用迭代器进行元素的遍历。迭代器提供了一种统一的方式来访问和处理容器中的元素。
- 自动内存管理:vector负责管理内部存储空间的分配和释放,使得开发者无需手动处理内存分配和释放的细节。
总之,vector是一个强大而灵活的容器,适用于各种情况下需要动态管理元素序列的场景。无论是存储对象、构建数据结构还是进行算法实现,vector都是C++中常用的工具之一。
模板类vector类似于string类,是一种动态数组,
(1)使用前提:包含vector头文件,使用using编译指令;
(2)如何使用:
创建一个名为vt的vector对象,可以存储n_elem个类型为typeName的元素;
vector<typeName> vt(n_elem);
其中n_elem可以是整型常量,也可以是整型变量。
10.2模板类array(C++11)
在C++中,array是一个用于存储固定大小的相同类型元素序列的容器类模板。它起到以下作用:
- 存储数据:array可以存储一组具有相同数据类型的元素。它提供了连续的内存空间来存储这些元素。
- 快速访问:由于array中的元素是连续存储的,可以通过索引快速访问特定位置的元素。数组的索引从0开始,因此可以使用索引来直接访问数组中的元素。
- 高效的元素访问和修改:与其他容器(如vector或list)相比,array提供了更高效的元素访问和修改。由于元素是连续存储的,可以利用指针算术来进行高效的访问和修改操作。
- 固定大小:array在创建时需要指定固定的大小,并且无法动态调整。这意味着一旦创建了一个array,它的大小就不能改变。这种固定大小的特性可确保在编译时就分配了足够的内存空间。
- 与原生数组的兼容性:array提供了与原生数组相似的语义和行为。它可以被传递给期望原生数组参数的函数,并且可以与使用原生数组的代码进行交互。
总而言之,array在C++中提供了一种方便的方式来存储和访问固定大小的连续元素序列,并且具有高效的性能。
array对象的长度是固定的,使用栈(静态内存分配),其效率与数组相同,但更方便,安全。在声明中创建一个名为arr的array对象,它包含n_elem个类型为typeName的元素:
array<typeName,n_elem> arr;
10.3 比较数组,vector对象,array对象
书中给出了示例,对数组,array,vector三者的对象输出他们的数值以及地址,但是对数组下标使用了-2这个索引,编译不会警告,数组名称本质上是一个地址,-2的索引,表示输出这个指针之前指向的数据。但是在执行过程中叫做“越界”,就会出现问题。
为了在vector与array中避免这种情况发生,使用at(),在函数运行期间捕获非法索引,若是下标不符合规范,程序运行过程中默认会中断。
11 总结
很多类型在学习C语言的时候都或多或少接触过,数组,字符串,指针的使用频率很高,多看几遍也无妨。数组的替代品,array以及vector比较重要,这都是C++新增的,需要重点关注一下。
12 参考
12.1 《C++ Primer Plus》