-
第4章 复合类型
4.1数组(array)
- 数组:能存储多个同类型的值;
- 数组声明:
- 存储在每个元素中的值的类型;
- 数组名;
- 数组中的元素数
short months[12]
- 数组:可以单独访问数组元素。方法是使用下标或索引来对元素进行编号。C++数组从0开始编号。
4.2 字符串
- 字符串:以空字符结尾,空字符被写作\0,其ACCII码为0,用来标记字符串的结尾。
char dog[8] = {'b', 'e','a','u','x',' ','i','i'};//not a string
char cat[8] = {'f','a','t','e','s','s','a','\0'};//a string
- 字符串常量或字符串字面值
char bird[11] = "Mr. cheeps";
char fish[] = "bubbles";
在确定存储字符串所需的最短数组时,别忘了将结尾的空字符计算在内。
字符串常量(使用双引号)不能与字符常量(使用单引号)互换。
char shirt_size = 'S';
/*字符常量'S'是字符串编码的简写表示。
在ASCII上,'S'是83的另一种写法。该语句将83赋值给shirt_size;*/
char shirt_size = "S";
/*表示的是两个字符(字符S和\0)组成的字符串。
"S"实际上表示的是字符串所在的内存地址。该语句将一个内存地址赋给shirt_size*/
4.2.1拼接字符串常量
任何两个由空白(空格、制表符和换行符)分隔的字符串常量都将自动拼接成一个。
cout << "I'd give my right arm to be" " a great violinist.\n";
cout << "I'd give my right arm to be a great violinist.\n";
cout << "I'd give my right ar"
"m to be a great violinist.\n";
4.2.2在数组中使用字符串
将字符串存储到数组中:将数组初始化为字符串常量、将键盘或文件输入读入到数组中。
4.2.3字符串输入
cin 使用空白(空格、制表符和换行符)来确定字符串的结束位置,这意味着cin在获取字符数组输入时只读取一个单词。读取该单词后,cin将该字符串放到数组中,并自动在结尾添加空字符。
4.2.4每次读取一行字符串输入
- 面向行的输入:getline()
使用通过回车键输入的换行符来确定输入结尾;但不保存换行符。在存储字符串时,使用空字符来替换换行符;
cin.getline(name,20);//将姓名读入到一个包含20个元素的name数组中。
- 面向行的输入:get()
将换行符保留在输入队列中。因此采用在两句之间添加cin.get()来处理换行符;
cin.get(name,20);//读取第一行
cin.get();//换行
cin.get(dessert,20);//读取第二行
//或另一种形式:将两个类成员函数拼接起来
cin.get(name,20).get();
4.3string类简介
- 使用string类,必须包含头文件string。
函数strcpy()将字符串复制到字符数组中,使用函数strcat()将字符串附加到字符数组末尾;
运算符 + :将两个string对象合并起来,
运算符+=:将字符串附加到string对象的末尾;
4.4 结构简介
同一个结构可以存储多种类型的数据。
4.5共用体(union)
共用体(union):能够存储不同的数据类型,但只能同时存储其中一种类型。
共用体的长度为其最大成员的长度。
4.6枚举(enum)
枚举(enum):创建一种符号常量,可以代替const。
enum spectrum {red,orange,yellow,green,blue,violet,indigo,ultraviolet};
默认情况下,将整数值赋给枚举量,第一个枚举量的值为0,第二个枚举量的值为1,依次类推。
- 设置枚举量的值
enum bits {one -1, two =2, four = 4, eight = 8};
enum bigstep{first, second = 100, third};//third = 101
4.7指针和自由存储空间
- 指针:存储的是地址;
- 常规变量的地址:对变量应用地址运算符(&)
- 取值运算符:(*);
假设manly是一个指针,则manly表示的是一个地址,而*manly表示存储在该地址处的值。
假如home是一个变量,则&home是地址。
4.71 声明和初始化指针
int * p_updates;
*p_updates的类型为int,由于*运算符作用于指针,因此p_updates变量本身为指针。
double *tax_ptr;
char *str;
虽然tax_ptr和str指向两种长度不同的数据类型,但这两个变量本身的长度是相同的。char的地址和double的地址的长度是相同的。地址的长度或值既不能指示关于变量的长度或类型的任何信息,也不能指示该地址有什么。地址需要2个还是4个字节,取决于计算机系统。
int higgens = 5;
int * pt = &higgens;
该语句将pt(而不是*pt)的值设置为&higgens。
4.7.2使用new来分配内存
// typename * pointer_name = new typename;
int *pn = new int;
new从被称为堆或自由存储区
4.7.3使用delete释放内存
int *ps = new int;
delete ps;
配对使用new 和delete,否则会发生内存泄漏。
4.7.4使用new 创建动态数组
int *psome = new int[10];//创建一个包含10个int元素的数组
//指针psome指向包含10个int值的内存块中的第1个元素。
delete [] psome;//释放数组
new运算符返回第一个元素的地址,该地址被赋给指针psome。
- 使用new和delete时,应遵守的规则:
- 不要使用delete来释放不是new分配的内存;
- 不要使用delete释放同一个内存块两次;
- 若使用new[ ]为数组分配内存,则应使用delete[ ]来释放;
- 若使用new为一个实体分配内存,则应使用delete来释放;
- 对空指针应用delete是安全的。
4.8指针、数组和指针算术
C++将数组名解释为其第一个元素的地址。对数组名应用地址运算符时,得到的是整个数组的地址。
char animal[20] = "bear";
const char *bird = "wren";
char *ps;
ps = animal;
cout << animal << " at " << (int *) animal << endl;
cout << ps << " at " << (int *) ps << endl;
如果给cout提供一个地址,将打印地址。但如果指针的类型为char*,则cout将显示指向的字符串。如果要显示字符串的地址,则要将该指针强制转换为另有一种指针类型,如( int *) animal;
4.8.4使用new创建动态结构
将new用于结构由两步组成:创建结构和访问其成员。
用于指向结构的指针:运算符(->);
或者:ps是指向结构的指针,*ps就是被指向的值--结构本身。由于*ps是一个结构,因此(*ps).price是该结构的price成员。
4.8.5自动存储、静态存储和动态存储
1.自动存储:
在函数内部空间定义的常规变量使用自动存储空间,被称为自动变量。在所属函数被调用时自动产生,在该函数结束时消亡。
自动变量是一个局部变量,作用域为包含它的代码块。
自动变量存储在栈中。后进先出。
2.静态存储
静态存储:是整个程序执行期间都存在的存储方式。
使变量成为静态的方式:(1)在函数外面定义;(2)在声明变量时使用关键字static。
3.动态存储
new和delete运算符:管理一个内存池。
4.10数组的替代品
1.模板类vector
使用vector对象,必须包含头文件vector。
#include <vector>
//vector<typename> vt(n_elem);
//其中n_elem可以是整型常量,也可以是整型变量
vector <int> vt(20);//vt为vector对象,可存储20个类型为int的元素;
2.模板类array
array对象的长度是固定的,也使用栈(静态内存分配);
要创建array对象,要包含头文件array。
#include <array>
//array<typename, n_elem> arr;
//其中n_elem不能是变量
array<double, 4> ad = {1.2, 2.1, 4.3, 3.43};
array<int, 5> ai;