【C++ Primer】第 3 章 字符串、向量和数组

Spring-_-Bear 的 CSDN 博客导航

三、字符串、向量和数组

3.1 命名空间的 using 声明

  1. 作用域操作符::: 的含义是编译器应从操作符左侧名字所示的作用域中寻找右侧那个名字

  2. using 声明:有了 using 声明就无须专门的前缀也能使用所需的名字了

    #include <iostream>
    
    using std::cout;
    
    int main() {
         
        cout << "Hello World";
        return 0;
    }
    
  3. 每个名字都需要独立的 using 声明:

    #include <iostream>
    
    using std::cin;
    using std::cout;
    using std::endl;
    
    int main() {
         
        cout << "Enter two numbers:" << endl;
        int v1, v2;
        cin >> v1 >> v2;
        cout << "The sum of " << v1 << " and " << v2 << " is " << v1 + v2 << endl;
        return 0;
    }
    
  4. 头文件不应包含 using 声明:头文件的内容会拷贝到所有引用它的文件中去,对于某些程序来说,由于不经意间包含了一些名字,反而可能产生始料未及的名字冲突

3.2 标准库类型 string

标准库类型 string 表示可变长的字符序列,使用 string 类型必须首先包含 string 头文件。作为标准库的一部分,string 定义在命名空间 std 中。

3.2.1 定义和初始化 string 对象

  1. 常用的初始化 string 对象的方式:

    #include <string>
    
    using std::string;
    
    int main() {
         
        string s1;              // ""
        string s2 = s1;         // s2 是 s1 的副本
        string s3 = "hello";    // s3 是该字符串字面值的副本
        string s4(10, 'c');     // cccccccccc
    }
    
    表达式 说明
    string s1; 默认初始化,s1 是一个空串
    string s2(s1); s2s1 的副本
    string s2 = s1; 等价于 s2(s1)
    string s3("value"); s3 是字面值 "value" 的副本,除了最后的空字符 '\0'
    string s3 = "value"; 等价于 s3("value")
    string s4(n, 'c'); s4 初始化为由连续 n 个字符 c 组成的串
  2. 直接初始化和拷贝初始化:如果使用等号初始化一个变量,实际上执行的是拷贝初始化,编译器把等号右侧的初始值拷贝到新创建的对象中去。与之相反,不使用等号时执行的是直接初始化

3.2.2 string 对象上的操作

操作 含义
os << s s 写到输出流 os 当中,返回 os
is >> s is 中读取字符串赋给 s,字符串以空白分隔,返回 is
getline(is, s) is 中读取一行赋给 s,返回 is
s.empty() s 为空串返回 true,否则返回 false
s.size() 返回 s 中字符的个数
s[n] 返回 s 中第 n 个字符的引用,位置 n0 开始计数
s1 + s2 返回 s1s2 连接后的结果
s1 = s2 s2 的副本代替 s1 中原来的字符
s1 == s2 判断 s1s2 中所含的字符是否完全一样
s1 != s2 判断 s1s2 中所含的字符不完全一样
<<=>>= 利用字符在字典中的顺序进行比较,且大小写敏感
  1. 读写 string 对象:

    #include <iostream>
    #include <string>
    
    int main() {
         
        std::string s;
        // 将标准输入的内容读取到 s 中,
        // string 对象会自动忽略开头的空白,一直读取直到遇到下一处空白停止
        std::cin >> s;
        std::cout << s << std::endl;
        return 0;
    }
    
  2. 读取未知数量的 string 对象:

    #include <iostream>
    #include <string>
    
    int main() {
         
        std::string word;
        while (std::cin >> word) {
         
            std::cout << word << std::endl;
        }
        return 0;
    }
    
  3. 使用 getline 读取一整行:

    #include <iostream>
    #include <string>
    
    int main() {
         
        std::string line;
        /*
         * getline 函数从给定的输入流中读入内容,直到遇到换行符为止(注意换行符也被读进来了),
         * 然后把所读的内容存入到那个 string 对象中去(注意不存换行符)
         */
        while (getline(std::cin, line)) {
         
            std::cout << line << std::endl;
        }
        return 0;
    }
    
  4. stringemptysize 操作:

    #include <iostream>
    #include <string>
    
    int main() {
         
        std::string line;
        while (getline(std::cin, line)) {
         
            if (!line.empty() && line.size() > 10) {
         
                std::cout << line << std::endl;
            }
        }
        return 0;
    }
    
  5. string::size_type 类型:size() 函数的返回值是 string::size_type 类型。string 类及其他大多数标准库类型都定义了几种配套的类型,这些配套类型体现了标准库类型与机器无关的特性,类型 size_type 即是其中的一种。

  6. 比较 string 对象:

    • 如果两个 string 对象的长度不同,而且较短 string 对象的每个字符都与较长 string 对象对应位置上的字符相同,就说较短 string 对象小于较长 string 对象
    • 如果两个 string 对象在某些对应的位置上不一致,则 string 对象比较的结果其实是 string 对象中第一对相异字符比较的结果
    #include <iostream>
    #include <string>
    
    int main() {
         
        std::string str = "Hello";
        std::string phase = "Hello World";
        std::string slang = "Hiya";
        // slang > phase > str
        std::cout << (str > phase) << std::endl;        // 0
        std::cout << (str > slang) << std::endl;        // 0
        std::cout << (phase > slang) << std::endl;      // 0
        return 0;
    }
    
  7. string 对象赋值:一般来说,在设计标准库类型时都力求在易用性上向内置类型看齐

    std::string str1(10, 'c'), str2;
    str1 = str2;    // 赋值,用 str2 的副本替换 str1 的内容,此时二者均为空串
    
  8. 两个 string 对象相加:

    std::string s1 = "hello, ", s2 = "world\n";
    std::string s3 = s1 + s2;   // s3 = "hello, world\n"
    s1 += s2;                   // s1 = s1 + s2
    
  9. 字面值和 string 对象相加:即使一种类型并非所需,我们也可以使用它,不过前提是该种类型可以自动转换成所需的类型。因为标准库允许把字符字面值和字符串字面值转换成 string 对象,所以在需要 string 的地方就可以使用这两种字面值来替代

    std::string s1 = "hello", s2 = "world";
    // string 与字符或字符串字面值混加时,需保证加号一侧是 string 对象
    std::string s3 = s1 + ", " + s2 + '\n';
    std::string s4 = s1 + ", ";             // 正确
    std::string s5 = "hello" + ", ";        // 编译错误
    std::string s6 = s1 + ", " + "world";   // 正确: (s1 + ", ") 返回 string 对象
    std::string s7 = "hello" + ", " + s2;   // 编译错误
    

    因为某些历史原因,也为了与 C 兼容,所以 C++ 语言中的字符串字面值并不是标准库类型 string 的对象。切记,字符串字面值与 string 是不同的类型。

3.2.3 处理 string 对象中的字符

cctype 头文件中定义了一组标准库函数用于处理 string 对象中的字符:

函数名 功能
isalnum(c) c 是字母或数字时为真
isalpha(c) c 是字母时为真
iscntrl(c) c 是控制字符时为真
isdigit(c) c 是数字时为真
isgraph(c) c 不是空格但可打印时为真
islower(c) c 是小写字母时为真
isprint(c) c 是可打印字符时为真(即 c 是空格或 c 具有可视形式)
ispunct(c) c 是标点符号时为真(即 c 不是控制字符、数字、字母、可打印空白中的一种)
isspace(c) c 是空白时为真(即 c 是空格、横向制表符、纵向制表符、回车符、换行符、进纸符中的一种)
isupper(c) c 是大写字母时为真
isxdigit(c) c 是十六进制数字时为真
tolower(c) c 转换为小写字母
toupper(c) c 转换为大写字母
  1. 使用 C++ 版本的 C 标准库头文件:C 语言的头文件形如 name.hC++ 将这些文件命名为 cname。也就是去掉了 .h 后缀,而在文件名 name 之前添加了字母 c,表示这是一个属于 C 语言的标准库头文件。cname 头文件中定义的名字从属于命名空间 std,而定义在 .h 中的头文件则不然。

  2. 使用基于范围的 for 语句:C++11 新标准提供的范围 for 语句非常适用于处理 string 对象中的每个字符

    #include <iostream>
    #include <string>
    #include <cctype>
    
    int main() {
         
        std::string s("Hello World!!!");
        // punct_cnt 的类型与 s.size 的返回类型一样
        decltype(s.size()) punct_cnt = 0;
        for (auto c: s) {
         
            if (ispunct(c)) {
         
                ++punct_cnt;
            }
        }
        std::cout << punct_cnt << " punctuation characters in " << s << std::endl;
        return 0;
    }
    
  3. 使用范围 for 语句改变字符串中的字符:

    #include <iostream>
    #include <string>
    #include <cctype>
    
    int main() {
         
        std::string str("hello world!!!");
        for (auto &c: str) {
         
            c = toupper(c);     // c 是一个引用,因此赋值语句将改变 s 中字符的值
        }
        std::cout << str << std::endl;
        return 0;
    }
    
  4. 使用下标运算符实现只处理一部分字符:下标运算符 [] 接收的输入参数是 string::size_type 类型的值,这个参数表示要访问的字符的位置,返回值是该位置上的字符的引用

    #include <iostream>
    #include <string>
    #include <cctype>
    
    int main() {
         
        std::string str
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

春天熊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值