前言
我感觉我自己也难以忍受自己写的 C with STL 了,于是决定看看 CPPPP(雾)并记下一些之前不会的东西。
然而,所谓阅读,或许只是一次 skimming 吧?或许会烂尾吧?下次一定仔细看.jpg
本篇内容包括:
- 数组初始化
- 字符串
- 结构
- 枚举
第1章 预备知识
None
第2章 开始学习 C++
None
第3章 处理数据
None
第4章 复合类型
4.1 数组
4.1.3 C++11 数组初始化方法
初始化数组时,可省略等号
1
double earnings[]{1.2e4, 1.6e4, 1.1e4, 1.7e4};
列表初始化禁止缩窄转换
1
2
3long plifs[] = {25, 92, 3.0}; // invalid
char slifs[] = {'h', 'i', 1122011, 0}; // invalid
char tlifs[] = {'h', 'i', 112, 0}; // valid
4.2 字符串
4.2.4 每次读取一行字符串输入
-
std::basic_istream<CharT,Traits>::getline
basic_istream& getline( char_type* s, std::streamsize count );
(1)basic_istream& getline( char_type* s, std::streamsize count, char_type delim );
(2)
Extracts characters from stream until end of line or the specified delimiter delim.e.g.
1
2
3const int str_len = 100;
char str[str_len];
std::cin.getline(str, str_len); -
建议使用
get()
而不是getline()
。变体:
工作方式与
getline()
类似,它们接受的参数相同,解释参数的方式也相同,并且都读取到行尾。但get()
并不再读取并丢弃换行符,而是将其留在输入队列中。只读取一个字符,类似
getchar()
使用不带任何参数的
cin.get()
调用可读取下一个字符(即使是换行符)。将两个类成员函数拼接起来(合并)
1
std::cin.get(str, str_len).get();
之所以可以这样做,是由于
cin.get()
返回一个cin
对象,该对象随后将被用来调用get()
函数。getline()
也同理。
错误处理
当
get()
(不是getline()
)读取空行后将设置失效位(failbit
)。这意味着接下来的输入将被阻断,但可以用下面的代码来恢复输入:1
cin.clear();
如果输入行包含的字符数比指定的多,则
getline()
和get()
将把余下的字符留在输入队列中,而getline()
还会设置失效位,并关闭后面的输入。
混合输入字符串和数字
注意到数字后的回车之类的字符会导致字符串读取失败,可使用下列代码解决:
1
2(std::cin >> number).get();
std::cin.get(str, str_len);
4.3 string
类介绍
4.3.3 string
类的其他操作
1 | std::string str{"Hello World!"}; |
4.3.5 其他形式的字符串字面值
除
char
类型外,C++ 还有类型wchar_t
;而 C++11 新增了类型char16_t
和char32_t
。可创建些类型的数组和这些类型的字符串字面值。对于这些类型的字符串字面值,C++ 分别使用前缀L
、u
和U
表示。C++11 还支持
Unicode
字符编码方案UTF-8
。在这种方案中,根据编码的数字值,字符可能存储为1~4个八位组。C++ 使用前缀u8
来表示这种类型的字符串字面值。C++11 新增的另一种类型是原始(raw)字符串。在原始字符串中,字符表示的就是自己。原始字符串将
"(
和)"
用作定界符,并使用前缀R来标识原始字符串:1
std::cout << R"(I've said "Hello World!")" << std::endl;
原始字符串语法允许在表示字符串开头的
"
和(
之间添加其他字符,这意味着表示字符串结尾的"
和)
之间也必须包含这些字符,如:1
std::cout << R"233("(Who wouldn't?)", she whispered.)233" << std::endl;
4.4 结构简介
4.4.6 结构中的位字段
与 C 语言一样,C++ 也允许指定占用特定位数的结构成员,这使得创建与某个硬件设备上寄存器对应的数据结构非常方便。字段的类型应为整型或枚举(稍后将介绍),接下来是冒号,冒号后面是一个数字,它指定了使用的位数。可以使用没有名称的字段来提供间距。每个成员都被称为位字段(bit field)。下面是一个例子:
1 |
|
上述代码输出为4
。这个结构体对齐的理论我以后还要再研究研究。(Flag)
4.6 枚举
4.6.2 枚举的取值范围
先看下面的代码
1 |
|
它的输出是 6
,但注意到 6 并不是枚举值。
合法的原因是 6 在枚举定义的取值范围内。取值范围的定义如下。
$$ UpperBound = 2^{\lceil \log_2(\max \limits_{0 \le i<n} \lbrace x_i \rbrace) \rceil} $$
$$ LowerBound=\begin{cases} 0 & \min \limits_{0 \le i<n} \lbrace x_i \rbrace >= 0 \\ -2^{\lceil \log_2(-\min \limits_{0 \le i<n} \lbrace x_i \rbrace) \rceil} & \min \limits_{0 \le i<n} \lbrace x_i \rbrace < 0 \end {cases} $$
4.7 指针和自由储存空间
4.7.6 使用 new
来创建动态数组
1 | int* psome = new int[10]; |
4.10 数组的替代品
4.10.2 模板类 array
(C++11)
1 |
|
注意:数组长度必须是常量表达式
4.10.3 比较数组、vector
对象和 array
对象
array
的 at()
成员函数可以检查越界访问,但显然用 at()
而不是 []
时速度会减慢。