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

第3章 字符串、向量和数组

第2章介绍的内置类型是由C++语言直接定义的,这些类型,如数字和字符,体现了大多数计算机硬件本身具备的能力。标准库定义了另一组具有更高级性质的类型,它们尚未直接实现到计算机硬件中。本章介绍两种最重要的标准库类型:string和vector。string表示可变长的字符序列,vector存放的是某种给定类型对象的可变长序列。还将介绍内置数组类型。

3.1 命名空间的using声明

使用作用域操作符(::)的含义是:编译器应从操作符左侧名字所示的作用域中寻找右侧的那个名字。std::cin的意思就是要使用命名空间std中的名字cin。该方法比较烦琐。
使用using声明,就无须专门的前缀(形如命名空间::)也能使用所需的名字了。using声明形式为: using namespace::name; 一旦声明了上述语句,就可以直接访问命名空间中的名字。
每个名字都需要独立的using声明,用到的每个名字都必须有自己的声明语句,而且每句话都得以分号结束。位于头文件中的代码一般来说不应该使用using声明。

3.2 标准库类型string

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

3.2.1 定义和初始化string对象

C++ Primer 第3章 字符串、向量和数组_第1张图片
直接初始化和拷贝初始化
如果使用等号(=)初始化一个变量,实际上执行的是拷贝初始化,编译器把等号右侧的初始值拷贝到新建的对象中去。如果不使用等号,则执行的是直接初始化。

对于用多个值进行初始化的情况,一般来说使用直接初始化的方式,如s7.

3.2.2 string对象上的操作

一个类除了要规定初始化其对象的方式外,还要定义对象上所能执行的操作。
C++ Primer 第3章 字符串、向量和数组_第2张图片
读写string对象
使用IO操作符读写string对象。
C++ Primer 第3章 字符串、向量和数组_第3张图片
首先定义了一个名为s的空string,然后将标准输入的内容读取到s中。在执行读取操作时,string对象会自动忽略开头的空白(即空格符、换行符、制表符等)并从第一个真正的字符开始读起,直至遇到下一处空白为止。
读取未知数量的string对象
C++ Primer 第3章 字符串、向量和数组_第4张图片
循环条件负责在读取时检测流的情况,如果流有效,也就是说没有遇到文件结束标记或非法输入,那么执行while语句内部的操作。
使用getline读取一整行
有时我们希望能在最终的字符串中保留输入时的字符串,这是应该用getline函数代替原来的>>运算符。getline函数的参数是一个输入流和一个string对象,函数从给定的输入流中读取内容,直至遇到换行符为止(注意换行符也被读进来了),然后把读入的内容存入string对象中(注意不存在换行符)。getline只要一遇到换行符就结束读取操作并返回结果,触发getline函数返回的那个换行符实际上被丢弃掉了,得到的string对象中并不包含该换行符。
string的empty和size操作
empty函数根据string对象是否为空返回一个对应的布尔值。empty是string的一个成员函数,只要使用点操作符指明是哪个对象执行了empty函数就可以了,例如:line.empty()
size函数返回string对象的长度,即string对象中字符的个数,使用方法为:line.size()。size函数返回的是一个string::size_type类型的值,它是一个无符号类型的值,而且能足够存放下任何string对象的大小。如果一条表达式中已经有了size()函数就不要再用int了,这样可以避免混用int和unsigned可能带来的问题。
比较string对象
比较运算符逐一比较string对象中的字符,并且对大小写敏感。有相等性运算符(==和!=)和关系运算符(<、<=、>、>=),如果对应位置上的字符相同,较短的小于较长的;如果在某些对应的位置上不一致,比较第一对相异字符比较的结果。
为string对象赋值
对于string类而言,允许把一个对象的值赋给另外一个对象。
两个string对象相加
把左侧的运算对象与右侧的运算对象串接而成,使用加法运算符(+)。
字面值和string对象相加
标准库允许把字符字面值和字符串字面值转化为string对象。 C++中的字符串字面值并不是标准库类型string的对象。当把string对象和字符字面值及字符串字面值混在一条语句中使用时,必须确保每个加号运算符的两侧的运算对象至少有一个是string:
C++ Primer 第3章 字符串、向量和数组_第5张图片
s1 + ","的结果是一个string对象,它同时作为第二个加法运算符的左侧运算对象。

3.2.3 处理string对象中的字符

我们经常需要单独处理string对象中的字符,这类处理的一个关键问题是如何获得字符本身,另一个关键问题是要知道能改变某个字符的特性。
C++ Primer 第3章 字符串、向量和数组_第6张图片(注:C++兼容了C语言的标准库,C语言的头文件形如name.h,C++则将这些文件名命名为cname,在cname头文件中定义的名字从属于命名空间std)
使用基于范围的for语句处理每个字符
范围for(range for)语句,遍历给定序列中的每个元素并对序列中的每个值执行某种操作,其语法形式为:

其中,expression部分是用于表示一个序列的对象,declaration负责定义一个变量,该变量用于访问序列中的基础元素。每次迭代,declaration部分的变量会被初始化为expression部分的下一个元素值。

使用范围for语句改变字符串中的字符
如果想要改变string对象中字符串的值,必须把循环变量定义成引用类型。
C++ Primer 第3章 字符串、向量和数组_第7张图片
如果不用引用类型,则每次循环中,c会被初始化为s中的元素值,对c操作并不会改变s相应的元素值。
只处理一部分字符
要想访问string对象中的单个字符有两种方式:一种是使用下标,另外一种是使用迭代器。
下标运算符([ ])接收的输入参数是string::size_type类型的值,这个参数表示要访问的字符的位置,返回值是该位置上字符的引用。string对象的下标从0记起,必须大于等于0而小于s.size()。
下标的值称为“下标”或者“索引”,任何表达式只要它的值是一个整型值就能作为索引。如果某个索引是带符号类型的值将自动转换成由string::size_type表达的无符号类型。
使用下标执行迭代
C++ Primer 第3章 字符串、向量和数组_第8张图片
使用下标执行随机访问 通过计算得到某个下标值,然后直接获取相应位置的字符。

3.2.4 string上的常用操作

插入
(1)使用push_back尾插一个字符
string s1; s1.push_back(‘a’);

(2)使用insert(pos,char)在指定位置pos前插入字符char
s1.insert(s1.begin(),‘a’);
拼接
(1) 使用append()
string s1(“abc”); s1.append(“def”);

(2) 使用‘+’操作符
string s1(“abc”); s1+=“def”;
遍历
(1)下标法 for(int i = 0; i < s.size(); i++){ }

(2)正向迭代器 for(iter=s.begin();iter!=s.end();iter++){ }

(3)反向迭代器 for(riter=s.rbegin();riter!=s.rend();riter++){ }
删除erase()
iterator erase(iterator p);//删除字符串中p所指的字符

iterator erase(iterator first, iterator last);//删除字符串中迭代器区间[first,last)上所有字符

string& erase(size_t pos = 0, size_t len = npos);//删除字符串中从索引位置pos开始的len个字符

void clear();//删除字符串中所有字符
字符替换replace()
string& replace(size_t pos, size_t n, const char *s);//将当前字符串从pos索引开始的n个字符,替换成字符串s

string& replace(size_t pos, size_t n, size_t n1, char c); //将当前字符串从pos索引开始的n个字符,替换成n1个字符c

string& replace(iterator i1, iterator i2, const char* s);//将当前字符串[i1,i2)区间中的字符串替换为字符串s
查找find()

string s("dog bird chicken bird cat");

//字符串查找-----找到后返回首字母在字符串中的下标

s.find("chicken") // 1. 查找一个字符串,结果是:9

s.find('i',6)  // 2. 从下标为6开始找字符'i',返回找到的第一个i的下标, 结果是:11

s.rfind("chicken")  // 3. 从字符串的末尾开始查找字符串,返回的还是首字母在字符串中的下标,结果是:9

s.rfind('i') // 4. 从字符串的末尾开始查找字符,结果是:18-------因为是从末尾开始查找,所以返回第一次找到的字符

s.find_first_of("13br98")  // 5. 在该字符串中查找第一个属于字符串s的字符,结果是:4---b

 s.find_first_not_of("hello dog 2006")  // 6. 在该字符串中查找第一个不属于字符串s的字符------先匹配dog,然后bird匹配不到,所以打印4

s.find_last_of("13r98")  // 7. 在该字符串最后中查找第一个属于字符串s的字符,结果是:19

s.find_last_not_of("teac")   // 8. 在该字符串最后中查找第一个不属于字符串s的字符------先匹配t--a---c,然后空格匹配不到,所以打印21

排序sort()
sort(s.begin(),s.end())
截取substr()
string s2 = s1.substr(3,6)//从下标3开始,截取长度为6
按某个字符分割字符串

vector<string> splitString(const string &str, const string &pattern){
    vector<string> resVec;
    if (str.size() == 0)
        return resVec;

    string strs = str + pattern;
    size_t pos = strs.find(pattern);
    size_t size = strs.size();
    
    while (pos != string::npos){//string:npos是个特殊值,说明查找没有匹配
        string x = strs.substr(0,pos);
        resVec.push_back(x);
        strs = strs.substr(pos+1,size);
        pos = strs.find(pattern);
    }
    return resVec;
}


int main(){

    string str = "12.34.567.89.";
    string pattern = ".";
    vector<string> result = splitString(str,pattern);
    for (auto s : result)
        cout << s << endl;

    return 0;
}

你可能感兴趣的:(C++)