题外话: 在我眼里,我实习的第一家公司教会了我两件事,一是让自己忙起来,二是代码规范整洁。有时候有所悟会很晚,但终究不迟。
序: C++提供了基于整型和浮点类型创建的复合类型。影响最深远的复合类型是类
。然而,C++还支持几种普通的复合类型。
例如,数组 可以存储多个同类型的值。
结构 可以存储多个不同类型的值。
指针 则是一种将数据所处位置告诉计算机的类型。
数组array
数组声明应指出以下三点:
- 存储每个元素中的值的类型
- 数组名
- 数组的元素数量
格式:
short months[12];
typename arrayname[size];
size 必须是整型常数或const值,也可以是常量表达式。他不能是变量。
C++11新增初始化的功能
初始化数组可以省略
等于号=
,例如double ear {1.2e2, 1.6e3, 2.3e4,3.5e10};
可以不在大括号内包含任何东西,意味着所有元素是
0
列表初始化禁止缩窄转换
1
2
3long plifs[] = {23,12,3.0}; //浮点数转换成长整型是缩窄操作,不能编译通过
char slifs[] = {'g',1123456,'\o'}; //1123456超过char变量的取值范围,不能编译通过
char tlifs[] = {'h',112,'o'}; //OK
数组的替代品 – 模板类vector
在C++标准模板库STL提供了vector,以及C++11增加了模板类array
。
字符串
C++处理字符串的方式有两种,一种来自C语言,常称为
C-风格字符串
,另一种基于string
类库的方法。
C-风格字符串(字符数组)
C-风格字符串以
空字符 \0
结尾,其ASCII码是0
。char dog[3] = {'d','o','g'}; //not a string
char dog[3] = {'d','o','g', '\0'}; //is a string
字符串常量或者称字符串字面值
使用双引号表示字符串常量,而字符是单引号
char bird[11] = "Mr. cheeps"; //the \0 is hideen,隐式包含结尾的空字符
char fish[] = "buddles"; //left the complier count
sizeof()
指出整个数组长度,而strlen
返回的是存储在数组中字符串的长度,而不是数组本省的长度。strlen()
只计算可见的字符,不计算空字符\0
在内。(只针对char数组
,并且需要加入头文件#include<cstring>
)读取一行字符串输入
istream中的类(例如
cin
)提供了一些面向行的成员函数:getline()和get()
这两个函数都读取一行输入,直到到达换行符
随后,getline
将丢弃换行符,get()
将换行符保留在输入序列。(1)
cin.getline(name,20);
将一行数据读入到一个包含20个元素的name数组。如果这行包含的字符不超过19个(\0
)instr2.cpp 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main() {
using namespace std;
const int size = 20;
char name[size];
char group[size];
cout << "Enter your name : \n";
cin.getline(name, size); //read info inline
cout << "Enter group: \n";
cin.getline(group, size);
cout << "name is "<< name <<endl;
cout << "groupf is " << group <<endl;
return 0;
}结果:
1
2
3
4
5
6Enter your name :
abc
Enter group:
def
name is abc
groupf is def(2)
cin.get(name,size)
不会换行,而是将换行符读入到下一行开始。可以通过以下两种方式换行:1
2
3
4
5
6//first
cin.get(name,size);
cin.get();
cin.get(group,size);
//second
cin.get(name.size).get();(3) 读取空行
当get()或者getline()读取空行后将设置
失效位 failbit
。这意味接下来的输入将被阻断。
恢复输入方法:cin.clear();
(4) 输入字符串比分配的空间(数组size)长,则getline()和get()将把余下的字符留在输入队列中,
getline()
还会设置失效位
,并关闭后续的输入。
string
类
string类需要头文件
string
。并且string位于命名空间std
中。
代码示例:
1 |
|
结果:
1 | Enter string data: |
Note:
类设计让程序能够自动处理string
的大小。例如str1声明的时候长度为0,读取到输入后长度是3。
- C++11新增的字符串初始化:
1 | char char1[] = {"hello boy"}; |
- 字符串拼接合并
1 | string str3; |
cstring头文件
的字符数组char[]
复制和附加操作
1 | strcpy(char1, char2); //将char2数组赋值到char1 |
对比来说,字符串string的拼接和附加操作更加简单。
两种字符串书写方式的I/O
和字符串长度
代码:
1 |
|
结果:
1 | length of ch[10] = 0 |
wchar_t, char16_t, char32_t
的初始化
1 | wchar_t title[] = L"Paper"; //L |
C++11新增的原始字符串raw
,以R
为前缀
cout << R"("king" \n and queue)"
结果:
"king" \n and queue
原始字符串使用
"(
和)"
作为限定符,换行符\n
也只打印两个单独的符号。
或者使用"+*(
和)*+"
作为限定符
结构
结构可以存储多种类型的数据。
结构是用户定义的类型
而结构声明定义了这种类型的数据属性
定义了类型之后,便可以创建这种类型的变量创建结构包含两步:
- 定义结构描述(它描述并且标记能够存储在结构中的各种数据的类型)
- 按照描述创建变量(结构数据变量)
- 例如以下结构描述
1 | struct inflatable //结构的关键字`struct`,标识符`inflatable`是这种数据格式的名称 |
- 创建这种类型的变量:
1 | inflatable hat; //允许省略关键字`struct`,因为结构声明定义了一种新的数据格式 |
因为hat
是数据结构类型,所以允许使用hat.name
来访问成员。
- 示例代码:
1 |
|
执行结果:
1 | List name : pen ,and pencil |
结构声明的位置
结构声明的位置很重要,可以将声明放在main函数中,紧跟在开始括号的后面
也可以选择将声明放在main函数前面位于函数外面的声明被成为
外部声明
,如果类包含两个或更多的函数,外部声明可以被后面的函数使用
而内部声明只能当前函数使用
C++11的初始化
同字符串和数组,结构也支持
列表初始化
,即在初始化的时候=等于号
是可选的。
`inflatable duck {"Dada", 0.12, 9.98};`
同时定义结构和和创建变量
1 | struct perks { |
结构数组
可以创建结构数组,例如
inflatable gifts[100];
,此时访问成员元素使用gifts[0].name
此时的gifts
不是结构,而是数组
‘gifts[0]’是结构
结构中的位字段
C++允许指定占用特定位数的结构成员。这使得创建与某个硬件的寄存器对应的数据结构非常方便。
字段的类型应为整型或者枚举,接下来是冒号,冒号后面是数字,它指定了使用的位数
每个成员都被称为位字段
位字段常用于低级编程中
1 | struct torgle { |
共用体union
union能够存储不同类型的数据,但是只能同时存储其中的一种类型。
例如:
1 | union one4all { |
可以使用one4all
存储不同的类型,存储int,long,或者double
1 | one4all pail; |
因此,pail有时候是int类型,有时候也可以使long,double
成员名称标识了变量的容量
共同体每次只能存储一个值,因此必须有足够的空间来存储里面最大的成员,所以共同体的长度为其最大成员变量的长度
共同体的用途之一是:当数据项使用两种或者更多的格式,但是不会同时使用时,可以节省时间。
例如一些商品的ID是整数,而另一些的ID是字符,则可以定义:
1 | struce thing { |
匿名共用体
匿名共用体没有名称,其成员将成为位于相同地址的变量。
每次只有一个成员是当前的成员。
1 | struce thing { |
因为是匿名共用体,所以id_num
和id_char
被视为结构体thing
的成员,他们的地址相同(相对于结构体来理解),因而不需要中间标识符id_val
(即共用体的变量声明)。
共用体常用于节省内存(例如操作系统数据结构或硬件数据结构)