数组
声明数组的通用格式如下
- 存储在每个元素中的值的类型
- 数组名
- 数组中的元素数
1 | typeName arrayName[arraySize]; |
包含了每个元素的值类型、数组名、数组中的元素个数,arraySize
必须是整形常量(如10)或 const
值,也可以是常量表达式(如 8 * sizeof(int)
),即其中所有的值在编译时都是已知的
数组的初始化有以下几种
1 | int cards[4] = {1, 2, 3, 4}; |
另外还有特殊的初始化
1 | float hotelTips[5] = {5.0, 2.5}; //只初始化hotelTips的前两个元素 |
如果只对数组的一部分进行初始化,则编译器将把其他元素设置为 0
如果不指定数组的元素个数,编译器将计算元素个数
1 | short things[] = {1, 5, 3, 8}; //编译器将使things数组包含4个元素 |
C++11
将使用大括号的初始化(列表初始化)作为一 种通用初始化方式,可用于所有类型,C++11 中的列表初始化新增了一些功能
- 初始化数组时,可省略等号
=
- 可不在大括号内包含任何东西,这将把所有元素都设置为
- 列表初始化禁止缩窄转换
1 | double earnings[4] {1.2e4, 1.6e4, 1.1e4, 1.7e4}; |
C++标准模板库STL
提供了一种数组替代品—模板类vector
,而 C++11
新增了模板类array
字符数组
字符串是存储在内存的连续字节中的一系列字符,意味着可以将字符串存储在char数组中,其中每个字符都位于自己的数组元素中,但注意以 以空字符(null character)结尾!!!!
1 | char dog[10] = {'h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd'}; //not a string |
所以字符常量 'S'
与字符串常量 "S"
是不等价的,"S"
表示的是两个字符(字符S和\0)组成的字 符串。更糟糕的是,"S"
实际上表示的是字符串所在的内存地址,以下是非法的
1 | char shirt_size = "S"; //illegal type mismatch |
另外,跟数组的初始化类似,字符数组也会为没有初始化的自动设置值

为了在数组中使用字符串,可以有两种办法
- 将数组初始化为字符串常量
char cat[10] = "hellobaby";
- 将键盘或文件输入读入到数组中,如下
1 | const int Size = 15; |
输出结果
1 | nihao |
可以看到 strlen
返回的是字符串的长度,但是 sizeof
返回的数组的长度。另外 strlen
只计算可见的字符,而不把空字符计算在内。
如果输入长度超过字符数组长度怎么办?
1 | const int Size = 5; |
运行结果
1 | ni hello world #输入 |
这里有两个注意的地方
name1
是ni
而不是ni he
,这是因为cin
使用空白(空格、制表符和换行符)来确定字符串的结束位置- 没有执行(用户输入)
cin >> name2;
,cin
把hello
放入name1
中并添加空字符。然后输出队列中剩余的world
直接输入到name2
中,所以感觉不到输入第二次
要是就是想将 ni hello world
保存到一个字符串中怎么办?
-
getline()
函数读取整行,通过换行符来确定输入结尾1
2
3
4
5
6
7const int Size = 5;
char name1[Size];
char name2[Size];
cin.getline(name1, Size);
cin.getline(name2, Size);
cout << name1 << " " << strlen(name1) << endl;
cout << name2 << " " << strlen(name2) << endl;输出结果
1
2
3ni hello world #输入
ni h 4
0这里不一样的是
- 输入超过字符数组长度的会被自动截断
- 如果输入超过长度,那么后面的会等于直接输入
'\0'
-
get()
与 getline() 不同的是,get()
并不再读取并丢弃换行符,而是将其留在输入队列中1
2
3
4
5
6
7const int Size = 5;
char name1[Size];
char name2[Size];
cin.get(name1, Size);
cin.get(name2, Size);
cout << name1 << " " << strlen(name1) << endl;
cout << name2 << " " << strlen(name2) << endl;输出结果
1
2
3ni hello world #输入
ni h 4
ello 4 -
可以将上述逻辑合并到一起
1
2
3
4
5
6const int Size = 20;
char name1[Size];
char name2[Size];
cin.getline(name1, Size).getline(name2, Size);
cout << name1 << " " << strlen(name1) << endl;
cout << name2 << " " << strlen(name2) << endl;运行结果
1
2
3
4hello world #输入
hello #输入
hello world 11
hello 5 -
当读取空行后将设置失效位 (
failbit
)。这意味着接下来的输入将被阻断,但可以用下面的命令来cin.clear()
恢复输入,从上次结尾的地方继续读取1
2
3
4
5
6
7
8const int Size = 5;
char name1[Size];
char name2[Size];
cin.getline(name1, Size);
cin.clear();
cin.getline(name2, Size);
cout << name1 << " " << strlen(name1) << endl;
cout << name2 << " " << strlen(name2) << endl;运行结果
1
2
3ni hello world #输入
ni h 4
ello 4
如果手动设置字符数组指定位置为空字符,那么将导致字符串被截断
1 | const int Size = 15; |
输出结果
1 | Hello World! 12 |
最后一种输入的异常是混合输入
1 | cout << "Waht year was your house built?\n"; |
运行结果是
1 | Waht year was your house built? |
用户根本没有输入地址的机会。问题在于,当cin
读取年份,将回车键生成的换行符留在了输入队列中。后面的cin.getline( )
看到换行符后,将认为是一个空行,并将一个空字符串赋给address
数组。
解决办法是,在读取地址之前先读取并丢弃换行符。可以通过 空参数的cin.get()
或者 cin.clear() 解决
数组的替代
1 | vector<typeName> vt(n_elem); |
参考链接
- 《C++ Primer Plus》