C++ 学习之六、复合类型之数组
C++ 复合类型之数组笔记。
数组简介
数组(array)是一种数据格式,能够存储多个同类型的值。
数组的声明
声明数组的通用格式如下:
typeName arrayName[arraySize]
Tips: arraySize
指定元素数目,它必须是整型常数(如 10 )或 const
值,也可以是常量表达式(如 8*sizeof( int )
),即其中所有的值在编译时都是已知的。具体地说,arraySize
不能是变量。后面将介绍使用 new
运算符来避开这种限制。
数组与类型是强关联的,如 float f[20]
,f
的类型不是“数组”,而是“float 数组”。
数组的初始化
函数中未初始化的数组的元素值是不确定的,这意味着元素的值为以前驻留在该内存单元中的值。只有在定义数组时才能初始化,此后就不能重新初始化了,不能将一个数组赋给另一个数组
1 | int cards[4] = {3, 6, 8, 10}; // 数组列表初始化 |
几种初始化方式:
1 | float n_float[3] = {0.1, 0.555, 6.8}; // 列表初始化,可列出所有元素 |
Tips: 上述所有列表初始化同其它列表初始化一样,禁止缩窄操作。
特殊的数组 —— 字符串
C 风格字符串
char
数组中存储多个 char
类型的值,其中有一种特殊情况,如果 char
数组最后一个元素为 \0
,即以空字符结尾,这时这个数组就是一个字符串,可以看出,字符串是一种特殊的 char
数组。
1 | char c_array[5] = {'z', 'h', 'o', 'u', 'x'}; // char 数组 |
空字符 '\0'
对 C 风格字符串有着至关重要的意义。如 cout
打印字符串时,它将逐个打印字符直到遇到空字符才停止。
C 风格字符串特点 —— 拼接字面值
有时候字符串很长,无法放到一行中。C++ 允许拼接字符串字面值,即将两个用引号括起的字符串合并为一个。任何两个由空白(空格、制表符和换行符)分隔的字符串常量将自动拼接成一个,如以下两句意义相同。
1 | cout << "This is a" " string"; // 将自动拼接为 "This is a string" |
Tips: 拼接时,前一个字符串末尾的 '\0'
将被后一个字符串中的第一个字符代替,两者之间不会自动加上空白。
数组中使用字符串
在数组中使用字符串,最常用的有两种方法——将数组初始化为字符串、将键盘或文件输入读入到数组中。
数组初始化为字符串前面已详细介绍。
而字符串输入,有以下几种方式:
cin>>
输入方式。cin>>
使用空白(空格、制表符和换行符)来确定字符串的结束位置,cin>>
从缓冲区中读取数据,若缓冲区中第一个字符是空白,cin>>
会将其忽略并清除继续读取下一个字符,若缓冲区为空,则继续等待。cin>>
获取字符数组输入时只读取一个单词,读取该单词后,cin>>
将该字符放到数组中,并自动在结尾添加空字符。cin>>
会将结尾的空白保留在输入序列中。cin cin.getline(char *, int)
。读取一行输入,直到到达换行符,丢弃换行符。它将使用空字符来替换换行符。cin cin.get(char *, int)
。读取一行输入,直到到达换行符,将换行符保留在输入序列中。
Tips: strlen()
用于计算可见的字符数量。
1 | // CinInputArray.cpp 通过控制台输入姓名,年龄,身高,体重,判断是否肥胖 |
读取空行和其他问题
当
getline(char *, int)
或get(char*, int)
读取空行时,将发生什么情况?当前的做法是,当get(char*, int)
(不是getline(char*, int)
)读取空行后将设置失效位(failbit)。接下来的输入将被阻断,但可以用下面的命令来恢复输入:
cin.clear();
另一个问题是,输入字符串可能比分配的空间长。如果输入行包含的字符数比指定的多,则
void getline(char*, int)
和void get(char*, int)
将把余下的字符留在输入队列中,而void getline(char*, int)
还会设置失效位,并关闭后面的输入。将在后面章节讨论。
C++ string 类
ISO/ANSI C++98 标准通过添加 string 类扩展了 C++ 库,只需要包含头文件 string。string 类位于名称空间 std 中,因此需要提供一条 using 编译指令。
string 字符串初始化
1 | string str1 = "This is a string!"; // C-风格字符串初始化方式 |
string 特性
不同于 C-风格字符串只能使用
strcpy()
函数将一个字符串复制给另一个,string 直接可将一个 string 赋给另一个。1
2
3string str1 = "This"; // string 对象将根据字符串的长度自动调整自己的大小
string str2; // 未初始化的 string 对象长度为0
str2 = str1; // 语法正确string 类简化了字符串合并操作。
传统 C-风格字符串使用
strcat()
函数拼接字符串,string 字符串,可以使用运算符+
将两个 string 对象合并起来,还可以使用+=
将字符串附加到 string 对象的末尾。1
2
3string str3;
str3 = str1 + str2; // str3 为 str1 和 str2 的拼接
str1 += str2; // 将 str2 附加到 str1 末尾string 类 I/O
从输入读取字符串到 string 对象时,每次读取一行,而且是使用以下代码方式:
1 | cin.getline(charr, charrSize); // C-风格字符串读取输入 |
字符串字面值
普通类型
1
char array[] = "This is array!";
wchar_t 类型字符串
1
wchar_t array[] = L"This is array!";
char16_t 和 char32_t 类型字符串
1
2char16_t array[] = u"char16_t style array!";
char32_t array[] = U"char32_t style array!";C++11 新增一种类型是原始(raw)字符串
输入原始字符串时,所有的字符以原样显示,特殊字符也不会被转义,按回车键不仅会移动到下一行,还将在原始字符串中添加回车符。
1
2char array[] = R"(This is ray array, \" will not be translate to ".)"; // 以 R"( 开头,以 )" 结束。
char array[] = R"+-(This is ray array, \" will not be translate to ".)+-"; // 允许在开头 "( 之间添加除空格、左括号、右括号、斜杠和控制字符(如制表符和换行符)以外的任意数量的基本字符,然后以相同的格式结尾。Tips: 可将前缀 R 与其他字符串前缀结合,以标识
wchar_t
等类型的原始字符串。可将 R 放在前面,也可将其放在后面,如 Ru、UR 等。
二维数组
每个数组都可以看作是一行数据,二维数组更像是一个表格——既有数据行又有数据列。
C++ 没有提供二维数组的类型,但用户可以创建每个元素本身都是数组的数组。
可以这样声明一个二维数组:
int maxtemps[4][5];
// maxtemps 是一个包含 4 个元素的数组,其中每个元素都是一个由 5 个整数组成的数组。
初始化二维数组
可以像类似一维数组一样初始化
1 | int btus[5] = {23, 26, 24, 3, 5}; |