参考资料:
- 《C++ Primer》第5版
- 《C++ Primer 习题集》第5版
3.1 命名空间的using声明(P74)
作用域操作符 :: 表示从左侧名字所示的作用域中寻找右侧名字,因此 std::cin 的意思就是使用命名空间 std 中的 cin 。
为了方便并安全地使用命名空间中的成员,可以使用 using 声明。
每个名字都需要独立的using声明
using std::cin;
using std::cout;
用到的每个名字必须有自己的声明语句,每条声明语句必须以分号结束。
头文件不应包含using声明
由于头文件中的内容可能会拷贝到其他文件中,很可能导致名字冲突。
3.2 标准库类型string(P75)
string 可表示变长的字符序列,定义在命名空间 std 中:
#include<string>
using std::string;
3.2.1 定义和初始化string对象(P76)
一个类可以定义多种初始化方式,这些方式要么初始值类型不同,要么初始值数量不同。string 类最常见的初始化方式有:

直接初始化和拷贝初始化
使用 = 初始化对象实际上执行的是拷贝初始化,反之则执行的是直接初始化。当初始值只有一个时,两种方法都可以;当初始值有多个时,拷贝初始化必须显式创建一个临时对象用于拷贝:
string s7(10, 'c');
string s8 = string(10, 'c');
3.2.2 string对象上的操作(P77)

读写string对象
string s;
cin >> s; // 假设输入“ hello ”
cout >> s; // 输出“hello”
使用 >> 将内容读取到 s 中时,string 对象会自动忽略开头的空白(空格符、换行符、制表符等)并从第一个真正的字符开始读起,直到遇到下一处空白为止。
读取未知数量的string对象
while(cin>>s){
/* ... */
}
使用getline读取一整行
如果希望保留输入中的空白符,可以使用 getline 函数。getline 函数的参数是一个输入流和一个 string 对象,函数从输入流中读取内容,直到遇到换行符位置(换行符也被读进来了),然后把读到的内容存入 string 对象中(不存换行符)。getline 的返回值它的流参数,同样可用于条件判断:
while(getline(cin, s)){
/* ... */
}
string的empty和size操作
string::size_type 类型
size 函数的返回类型为 string::size_type 。大多数标准库类都定义了几种配套类型,体现了标准库类型与机器无关的特性。
string::size_type 是一个无符号的值,并且足够存下任何 string 对象的大小;任何用于存放 string 类 size 函数返回值的变量都应是 string::size_type 类型:
auto len = s.size();
当表达式中有
size()时,不要再使用int
比较string对象
字典序。
为string对象赋值
string s1, s2("hello");
s1 = s2;
两个string对象相加
运算结果为两个运算对象的串接。
字面值和string对象相加
标准库允许把字符字面值和字符串字面值转换成 string 对象。当把 string 对象和字面值混用在一条加法时,必须保证每个 + 两侧至少有一个对象为 string :
string s("hello");
s = s + "," + "world"; // 正确,第一个加号运算后得到string对象
s = "world" + "," + s; // 错误
为了和 C 语言兼容,C++ 中的字符串字面值不是
string对象。例如,"hello"的类型为const char[7]
3.2.3 处理string对象中的字符(P81)

C++ 兼容了 C 语言的标准库,例如,C 语言存在头文件 name.h ,则 C++ 中对应的头文件为 cname 。需要说明的是,cname 中的名字定义在 std 中,而 name.h 则不然,所以 C++ 程序应该使用 cname 头文件。
处理每个字符?使用基于范围的for语句
如果想对字符串中的每个字符进行操作,最好的方法是使用范围 for 语句:
for(declaration : expression)
statement
expression 为一个序列对象,declaration 部分负责定义一个变量,用于访问序列中的基础元素。每次迭代,declaration 部分的变量会被初始化为下一个元素值。
每次迭代都对变量进行初始化,应该是为了保证范围
for语句能使用引用变量。
string s("hello");
for(auto c : s){
cout << c << ' ';
}
这里 auto 推断出的类型为 char 。
使用范围for语句改变字符串中的字符
想要改变 string 对象的值,必须把范围 for 循环中的变量定义成引用类型:
string s("hello");
for(auto &c : s){
c = toupper(c);
}
只处理一部分字符?
想要访问 string 对象中的单个字符有两种方式:使用下标、使用迭代器。
下标运算符 [] 接受的输入参数为 string::size_type 类型,返回值为该位置上字符的引用。string 类型的下标必须大于等于 0 且小于其 size 。
使用下标执行迭代
string s("hello");
// 依次处理s中的字符,知道遇到空格或结尾。
for(decltype(s.size()) index=0;index!=s.size()&&!isspace(s[index]);s++){
s[index] = toupper(s[index]);
}
上面的代码中,&& 运算符只有当左侧为真时才会检查右侧,所以必须先判断 index 的合法性,再对对应的字符进行判断。
使用下标执行随机访问
练习

s[index] = toupper(s[index]);
}
上面的代码中,`&&` 运算符只有当左侧为真时才会检查右侧,所以必须先判断 `index` 的**合法性**,再对对应的字符进行判断。
### 使用下标执行随机访问
### 练习
[外链图片转存中...(img-lnn8ZDjY-1694521712024)]
> 合法,c 为**字符常量的引用**



















