《C++ Primer》第3章 字符串、向量和数组(一)

参考资料:

  • 《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 类最常见的初始化方式有:

image-20230912184917241

直接初始化和拷贝初始化

使用 = 初始化对象实际上执行的是拷贝初始化,反之则执行的是直接初始化。当初始值只有一个时,两种方法都可以;当初始值有多个时,拷贝初始化必须显式创建一个临时对象用于拷贝:

string s7(10, 'c');
string s8 = string(10, 'c');

3.2.2 string对象上的操作(P77)

微信图片_20230912190215

读写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)){
    /* ... */
}

stringemptysize操作

string::size_type 类型

size 函数的返回类型为 string::size_type 。大多数标准库类都定义了几种配套类型,体现了标准库类型与机器无关的特性。

string::size_type 是一个无符号的值,并且足够存下任何 string 对象的大小;任何用于存放 stringsize 函数返回值的变量都应是 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)

image-20230912193638884

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合法性,再对对应的字符进行判断。

使用下标执行随机访问

练习

image-20230912201428570

s[index] = toupper(s[index]);
}


上面的代码中,`&&` 运算符只有当左侧为真时才会检查右侧,所以必须先判断 `index` 的**合法性**,再对对应的字符进行判断。

### 使用下标执行随机访问

### 练习

[外链图片转存中...(img-lnn8ZDjY-1694521712024)]

> 合法,c 为**字符常量的引用**
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值