更多关于STL的文章:STL专栏
文章目录
为了防止学习的过程中出现学后忘的情况,我将接触到的知识进行整理,作该笔记,由于本人水平有限,如果出现错误,还望赐正。
介绍
STL(Standard Template Library 标准模板库) 中只有一个字符串类,即 basic_string类 。basic_string 实现管理以 \0 结尾的字符数组,字符类型由模板参数决定。通常,basic_string 被处理为不透明的对象,靠获得只读指针来访问缓冲区,写操作是由 basic_string 的成员函数实现的。
用字符数组存放字符串容易发生数组越界的错误,而且往往难以察觉。因此,C++ 标准模板库设计了 string 数据类型,专门用于字符串处理。string 作为类出现,其集成的操作函数足以完成多数情况下的需要。使用时不必担心内存是否充足、字符串长度等问题。
string 类型的变量就是用来存放字符串的,也叫“string对象”。string 并不是 C++ 的基本数据类型,它是 C++ 标准模板库中的一个“类”。
string成员函数
string 类提供的各种操作函数大致分为八类:构造器和析构器、大小和容量、元素存取、字符串比较、字符串修改、字符串接合、I/O 操作以及搜索和查找 。
函数名称 | 功能 |
---|---|
构造函数 | 产生或复制字符串 |
析构函数 | 销毁字符串 |
=,assign() | 赋以新值 |
swap() | 交换两个字符串的内容 |
+=,append(),push_back() | 添加字符 |
insert() | 插入字符 |
back() | 返回字符串最后一个字符的引用 |
front() | 返回字符串第一个字符的引用 |
erase(),pop_back() | 删除字符 |
clear() | 清空字符串 |
resize() | 改变字符串的长度 |
shrink_to_fit() | 请求字符串减小其容量以适合其大小 |
replace() | 替换字符串 |
+ | 拼接字符串 |
==,! =,<,<=,>,>=,compare() | 比较字符串内容 |
size(),length() | 返回字符串长度 |
max_size() | 返回字符的最大可能个数 |
empty() | 判断字符串是否为空 |
capacity() | 返回重新分配之前的字符容量 |
reserve() | 保留内存以存储一定数量的字符 |
[],at() | 存/取单一字符 |
>>,getline() | 从 stream中读取某值 |
<< | 将值写入 stream |
copy() | 将内容复制为一个 C – string |
c_str() | 将内容以 C – string 形式返回 |
data() | 将内容以字符数组形式返回 |
substr() | 返回子字符串 |
find() | 搜寻某子字符串或字符 |
begin( ),end(),cbegin(),cend() | 提供正向迭代器支持 |
rbegin(),rend(),crbegin(),crend() | 提供逆向迭代器支持 |
get_allocator() | 返回配置器 |
成员类型 | 定义 |
---|---|
value_type | char |
size_type | size_t |
iterator | char的随机访问迭代器 |
const_iterator | const char的随机访问迭代器 |
pointer | char* |
const_pointer | const char* |
reference | char& |
const_reference | const char& |
成员函数用法示例
1. 构造
构造函数有四个参数,其中三个具有默认值。要初始化一个 string 类,可以使用 C 风格字符串或 string 类型对象,也可以使用 C 风格字符串的部分或 string 类型对象的部分或序列。
注意,不能使用字符或者整数去初始化字符串。//如string str (‘abc’), string str(123) 都是错误的
常见的 string 类构造函数有以下几种形式:
typedef basic_string string;
string var; //生成空字符串
string var(const basic_string& str); //生成字符串str的复制
string var(const basic_string& str, size_type pos); //将字符串str中始于pos的部分作为构造函数的初始值
string var(const basic_string& str, size_type pos, size_type n);
//将字符串str位于区间[pos,pos+n-1]的子字符串作为var的初始值string var(const char* s); //以C_string类型s作为字符串var的初始值
string var(const char* s, size_type n); //以C_string类型s的前n个字符串作为字符串var的初始值
string var(size_type n, char c);//生成一个字符串,包含n个c字符
string var(InputIterator beg, InputIterator end); //以闭区间[beg, end]内的字符作为字符串var的初始值
析构函数形式如下:
~basic_string() //销毁所有内存,释放内存
【例】
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str ("12345678");
char ch[ ] = "abcdefgh";
string str_1(str); //将str全部复制给str_1
string str_2(str,3);//从字符串str的第3个元素开始,复制后面的所有元素,并赋值给str_2
string str_3(str, 2, 5); //从字符串str的第2个元素开始,复制5个元素,并赋值给str_3
string str_4(ch);//复制C_string类型字符串,并赋值给str_4
string str_5(ch, 5); //将C_string类型字符串ch的前5个元素赋值给str_5
string str_6(5,'X'); //将5个'X'组成的字符串"XXXXX"赋值给str_6
string str_7(str.begin(), str.end()); //复制字符串str的所有元素,并赋值给 str_7
cout << str << endl;
cout << ch << endl;
cout << str_1 << endl;
cout << str_2 << endl;
cout << str_3 << endl;
cout << str_4 << endl;
cout << str_5 << endl;
cout << str_6 << endl;
cout << str_7 << endl;
return 0;
}
以下为程序运行结果:
12345678
abcdefgh12345678
45678
34567
abcdefgh
abcde
XXXXX
12345678
2. 字符串输入输出
“<<” 和 “>>” 提供了 C++ 语言的字符串输入和字符串输出功能。”<<” 可以将字符读入一个流中(例如 ostream);”>>” 可以实现将以空格或回车为 “结束符” 的字符序列读入到对应的字符串中,并且开头和结尾的空白字符不包括进字符串中。
还有一个常用的 getline() 函数,该函数的原型包括两种形式:
template <class CharType, class Traits, class Allocator > basic_istream<CharType, Traits>& getline (basic_istream<CharType, Traits>& _Istr,basic_string <CharType,Traits, Allocator> &_Str);
//上述原型包含 2 个参数:第 1 个参数是输入流;第 2 个参数是保存输入内容的字符串
template <class CharType, class Traits, class Allocator> basic_istream<CharType, Traits>& getline (basic_istream <CharType, Traits>&_ Istr, basic_string <CharType, Traits, Allocator>& _Str,CharType_Delim);
//上述原型包含 3 个参数:第 1 个参数是输入流,第 2 个参数保存输入的字符串,第 3 个参数指定分界符
该函数可将整行的所有字符读到字符串中。在读取字符时,遇到文件结束符、分界符、回车符时,将终止读入操作,且文件结束符、分界符、回车符在字符串中不会保存;当已读入的字符数目超过字符串所能容纳的最大字符数时,将会终止读入操作。
【例】
#include<iostream>
#include<string>
using namespace std;
int main()
{
//三块代码分开执行
string str_1;
cin>>str_1;
cout<<"第一个:"<< str_1<<endl;
/*string str_2; getline(cin,str_2); cout<<"第二个:"<<str_2<<endl;*/
/*string str_3; getline(cin,str_3,'a'); cout<<"第三个:"<<str_3<<endl;*/
return 0;
}
下面为程序运行结果(三种情况均输入:qweasd zxc)
第一个:qweasd //>>遇到空格结束
第二个:qweasd zxc //getline读取字符,直到遇见文件结束符、分界符、回车符停止
第三个:qwe //getline遇到分界符a 读取结束
3.获取字符串的长度
string 类型对象包括三种求解字符串长度的函数:size() 和 length()、 maxsize() 和 capacity():
- size() 和 length():这两个函数会返回 string 类型对象中的字符个数,且它们的执行效果相同。
- max_size():max_size() 函数返回 string 类型对象最多包含的字符数。一旦程序使用长度超过 max_size() 的 string 操作,编译器会拋出 length_error 异常。
- capacity():该函数返回在重新分配内存之前,string 类型对象所能包含的最大字符数。跟size()不同,它返回的是分配的容量的大小,并不是string里面字符串的长度。
【例】
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str("abcdef");
unsigned long size = str.size();
unsigned long length = str.length();
unsigned long max = str.max_size();
unsigned long cap = str.capacity();
cout<<"size:"<<size<<endl;
cout<<"length:"<<length<<endl;
cout<<"max_size:"<<max<<endl;
cout<<"capacity:"<<cap<<endl;
return 0;
}
下面为程序输出结果:
size:6
length:6
max_size:9223372036854775807
capacity:15 //至于这里为什么输出15,还不清楚
string 类型对象包括一个 reserve() 函数。调用该函数可以为 string 类型对象重新分配内存(预分配,此时不能用下标访问新分配的内存)。重新分配的大小由其参数决定。reserve() 的默认参数为 0。
还包含一个 resize() 函数。其功能与 reserve() 相同,但reserve() 只能将内存扩大,而 resize() 可以任意分配内存(直接分配,如果内存变小,则原字符串被截断,如果内存变大,则用’\0’填充,此时可以用下标访问新分配的内存)。
这两个方法分别对应两个属性:capacity() 和 size()
【例】
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str("abcdef");
str.reserve(40);
cout<<"size:"<<str.size()<<endl;
cout<<"capacity:"<<str.capacity()<<endl;
str.resize(60);
//str.shrink_to_fit();
cout<<str<<endl;
cout<<"size:"<<str.size()<<endl;
cout<<"capacity:"<<str.capacity()<<endl;
str.resize(3);//原字符串被截断
cout<<str<<endl;
return 0;
}
下面为程序运行结果:
size:6
capacity:40abcdef
size:60
capacity:80abc
上述程序中str.reserve(40);
如果将n=40改为0~14,capacity仍输出15,而将n改为15~29时,capacity将输出30。只有改为31及以上,才会输出值n。
此外从运行结果可以看到resize之后,capacity也会发生改变,resize之后(扩大内存)理论上capacity的值与size相同,上述程序由于预先调用了reserve,影响了结果。但是若添加str.shrink_to_fit();
,则capacity将会与size相同。
- shrink_to_fit()无返回值,功能如下:
- 请求字符串减小其容量以适合其大小。
- 该请求是非绑定的,并且容器实现可以自由地进行优化,否则将使字符串的容量大于其大小。
- 此函数对字符串长度没有影响,并且不能更改其内容。
4.获取字符串元素
字符串中元素的访问是允许的,一般可使用两种方法访问字符串中的单一字符:下标操作符[] 和 成员函数at()。两者均返回指定的下标位置的字符。第 1 个字符索引(下标)为 0,最后的字符索引为 length()-1。
需要注意的是,这两种访问方法是有区别的:
- 下标操作符 [] 在使用时不检查索引的有效性,如果下标超出字符的长度范围,会示导致未定义行为。对于常量字符串,使用下标操作符时,字符串的最后字符(即 ‘\0’)是有效的。对应 string 类型对象(常量型)最后一个字符的下标是有效的,调用返回字符 ‘\0’。
- 函数 at() 在使用时会检查下标是否有效。如果给定的下标超出字符的长度范围,系统会抛出 out_of_range 异常。
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str("abcdef");
cout<<str[3]<<endl;
cout<<str.at(3)<<endl;
cout<<str[10]<<endl;//越界,返回'\0',但Qt Creator13.01执行时未报错
cout<<str.at(10)<<endl;//异常
return 0;
}
运行结果:
d
dterminate called after throwing an instance of ‘std::out_of_range’
what(): basic_string::at: __n (which is 10) >= this->size() (which is 6)
- front() 和 back()
front() 和 back() 分别返回字符串首、尾字符的引用,无参数。
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str("abcdef");
cout<<str.front()<<endl;
cout<<str.back()<<endl;
str.front() = 'c';
str.back() = 'x';
cout<<str<<endl;
return 0;
}
运行结果为:
a
f
cbcdex
另外,为了防止使用下标时,字符串尚未初始化等情况,使用empty() 和 size() 或 length()可以有效防止出错。
- empty()无参数,功能如下 :
- 判断字符串是否为空,是返回真,否则返回假。
- substr()
返回子字符串
basic_string substr(size_type pos = 0, size_type n = npos) const;
//返回区间[pos,pos+n-1]的子字符串
string str("abcdefg");
cout<<str.substr(2,5)<<endl; //输出cdefg
5.字符串内容的修改
可以通过使用多个函数修改字符串的值。例如 assign(),operator=,erase(),operator+,pop_back(),swap(),insert()等。另外,还可通过 append() ,push_back()函数添加字符,以及clear()清空字符串。
- assign()
使用 assign() 函数可以直接给字符串赋值。该函数既可以将整个字符串赋值给新串,也可以将字符串的子串赋值给新串。其在 basic_string 中的原型为:
basic_string& assign(const char* s); //直接使用C_string字符串赋值
basic_string& assign(const char* s, size_type n);//将C_string字符串s前n个字符赋值给调用串
basic_string& assign (const basic_string& str); //使用string字符串賦值
basic_string& assign(const basic_string& str, size_type pos, size_type n = npos);
//将str的子串赋值给调用串,n表示长度,默认值为-1(直到字符串末尾)basic_string& assign(size_type n, char c); //使用 n个重复字符賦值
basic_string& assign(InputIterator first, InputIterator last); //使用迭代器赋值
【例】
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str1("123456");
char s[6] = "abcde";
string str;
str.assign(s);//用C_string类型字符串赋值
cout<<str<<endl;
str.assign(s,3);//将C_string类型字符串s的前3个字符赋值给str
cout<<str<<endl;
str.assign(str1);//用string类型字符串赋值
cout<<str<<endl;
str.assign(str1,3);//将str1从第3个字符到最后一个字符赋值给str
cout<<str<<endl;
str.assign(str1,2,3);//将str1从第2个字符开始,长度为3的字符串赋值给str
cout<<str<<endl;
str.assign(5,'c');//用5个c字符赋值
cout<<str<<endl;
str.assign(str1.begin()+2,str1.end()-2);//使用迭代器赋值
cout<<str<<endl;
return 0;
}
下面为程序运行结果:
abcde
abc
123456
456
345
ccccc
34
operator=
operator= 的功能就是赋值。operator+
将两个或多个字符串拼接起来
string str1("123456");
string str("789");
str = str1 + str;
cout<<str<<endl;//输出123456789
- push_back()
在字符串末尾追加一个字符,参数为多个字符时,会被截断
void push_back(char c);
string str("abc");
str.push_back('d')
cout<<str<<endl;//输出abcd
- swap()
交换两个字符串的值
void swap (basic_string& str);
string str1("123456");
string str("789");
str.swap(str1);
cout<<str<<endl; //输出123456
cout<<str1<<endl;//输出789
- pop_back()
删除字符串最后一个字符
void pop_back();
- erase()
删除指定子字符串
basic_string& erase(size_type pos = 0, size_type n = npos);
//删除从pos开始,长度为n的子字符串(即区间[pos,pos+n-1]的子字符串)(默认删除全部)iterator erase(const_iterator position);//使用迭代器,删除指定的一个字符
iterator erase(const_iterator first, const_iterator last);//使用迭代器,删除指定区间的子字符串
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str("123456");
str.erase(3);//从第3个开始删除后续所有字符
cout<<str<<endl;
str = "123456";
str.erase(3,2);//从第3个开始删除长度为2的子字符串
cout<<str<<endl;
str = "123456";
str.erase(str.begin()+3);//删除第3个字符
cout<<str<<endl;
str = "123456";
str.erase(str.begin()+2,str.begin()+4);//删除区间[2,4)的子字符串
//str.erase(str.end()-4,str.end()-2); //删除区间{2,4)的子字符串
cout<<str<<endl;
return 0;
}
运行结果:
123
1236
12356
1256
clear()
清空字符串,该函数无参数,无返回值。insert()
向指定位置插入字符串
basic_string& insert(size_type pos, const char* s);//在调用串的第pos个元素前面插入C_string类型字符串
basic_string& insert(size_type pos, size_type n, char c);//在调用串的第pos个元素前面插入n个字符c
iterator insert(const_iterator p, char c);//使用迭代器,在正向迭代器指向的位置p前面插入单个字符c
iterator insert(const_iterator p, size_type n, char c);//在正向迭代器指向的位置p前面插入n个字符c
basic_string& insert(size_type pos, const char* s, size_type n);
//在调用串的第pos个元素前面插入C_string类型字符串s的前n个字符basic_string& insert(size_type pos1, const basic_string& str, size_type pos2, size_type n = npos);
//在调用串的第pos1个元素前插入字符串str位于区间[pos2,pos2+n -1]的子字符串(n默认直到末尾)basic_string& insert(size_type pos1, const basic_string& str);//在调用串的第pos1个元素前插入字符串str
iterator insert(const_iterator p, InputIterator beg, InputIterator end);
【例】
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str("123456");
string ss("vwxyz");
char s[6] = "abcde";
str.insert(2,s);//在str第2个元素前面插入C_string类型字符串s
cout<<str<<endl;
str = "123456";
str.insert(2,3,'a');//在str第2个元素前面插入3个字符a
cout<<str<<endl;
str = "123456";
str.insert(str.begin()+1,'b');//在str第1个元素前面插入字符b
cout<<str<<endl;
str = "123456";
str.insert(str.begin(),3,'c');//在str第0个元素前面插入3个字符c
cout<<str<<endl;
str = "123456";
str.insert(3,s,2);//在str第3个元素前面插入c_string类型字符串s的前2位
cout<<str<<endl;
str = "123456";
str.insert(2,ss,2,2);//在str第2个元素前面插入字符串ss从第2个元素开始长度为2的子字符串
cout<<str<<endl;
str = "123456";
str.insert(2,ss);//在str第2个元素前面插入字符串ss
cout<<str<<endl;
str = "123456";
str.insert(str.begin()+1,ss.begin()+3,ss.end());//在str第1个元素前面插入字符串ss从第3个元素到最后一个元素所构成的子字符串
cout<<str<<endl;
return 0;
}
程序运行结果为:
12abcde3456
12aaa3456
1b23456
ccc123456
123ab456
12xy3456
12vwxyz3456
1yz23456
- append()
追加字符串
basic_string& append(const basic_string& str);//在调用串末尾添加字符串str
basic_string& append(const basic_string& str, size_type pos, size_type n = npos) ;//在调用串末尾添加字符串从第pos个元素开始长度为n的子字符串(即区间[pos,pos+n-1]的子字符串)(n默认直到末尾)
basic_string& append(const char* s, size_type n);//在调用串末尾添加c_string类型字符串s的前n个元素
basic_string& append(const char* s);//在调用串末尾添加c_string类型字符串s
basic_string& append(size_type n, char c);//在调用串末尾添加n个字符c
basic_string& append(InputIterator first, InputIterator last);
【例】
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str("123456");
string ss("vwxyz");
char s[6] = "abcde";
str.append(ss);//在str末尾添加字符串ss
cout<<str<<endl;
str = "123456";
str.append(ss,2,2);//在str末尾添加字符串ss从第2个元素开始长度为2的子字符串
cout<<str<<endl;
str = "123456";
str.append(s,3);//在str末尾添加c_string类型字符串s的前3个字符
cout<<str<<endl;
str = "123456";
str.append(s);//在str末尾添加c_string类型字符串s
cout<<str<<endl;
str = "123456";
str.append(3,'a');//在str末尾添加3个字符a
cout<<str<<endl;
str = "123456";
str.append(ss.begin()+1,ss.end());//在str末尾添加字符串ss在区间[1,4]上的子字符串
cout<<str<<endl;
return 0;
}
程序运行结果为:
123456vwxyz
123456xy
123456abc
123456abcde
123456aaa
123456wxyz
6.字符串内容的替换
如果在一个字符串中标识出具体位置,便可以通过下标操作修改指定位置字符的值,或者替换某个子串。完成此项操作需要使用 string 类的成员函数 replace()。
replace() 函数的原型如下:
basic_string& replace(size_type pos, size_type n, const basic_string& str);
//将调用串从第pos个元素开始长度为n的子字符串(即区间[pos,pos+n-1]的子字符串)替换为字符串strbasic_string& replace(size_type pos1, size_type n1, const basic_string& str,size_type pos2, size_type n2 = npos);//将调用串从第pos1个元素开始长度为n1的子字符串(即区间[pos1,pos1 + n1 -1]的子字符串)替换为字符串str从第pos2个元素开始长度为n2的子字符串(即区间[pos2,pos2 + n2 -1]的子字符串)(n2默认值指向末尾)
basic_string& replace(size_type pos, size_type n1, const char* s,size_type n2);
//将调用串位于区间[pos,pos+n1 – 1]的子字符串替换为c_string类型字符串s的前n2个字符basic_string& replace(size_type pos, size_type n1, const char* s);
//将调用串位于区间[pos,pos + n1 -1]的子字符串替换为c_string类型字符串sbasic_string& replace(size_type pos, size_type n1, size_type n2, char c);
//将调用串位于区间[pos,pos + n1 -1]的子字符串替换为n2个字符cbasic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str);
//将迭代器i1,i2指向的元素之间的字符串(包括i1)替换为字符串strbasic_string& replace(const_iterator i1, const_iterator i2,const char* s, size_type n);
//将迭代器i1,i2指向的元素之间的字符串(包括i1)替换为c_string类型字符串s的前n个字符basic_string& replace(const_iterator i1, const_iterator i2, const char* s);
//将迭代器i1,i2指向的元素之间的字符串(包括i1)替换为c_string类型的字符串sbasic_string& replace(const_iterator i1, const_iterator i2, size_type n, char c);
//将迭代器i1,i2指向的元素之间的字符串(包括i1)替换为n个字符cbasic_string& replace(const_iterator i1, const_iterator i2,InputIterator k1, InputIterator k2);
//将迭代器i1,i2指向的元素之间的字符串(包括i1)替换为迭代器k1,k2指向的元素之间的字符串(包括k1)basic_string& replace(const_iterator i1, const_iterator i2 , char* k1, char* k2);
//在测试的时候直接输入k2没有作用,要输入k2+(一个常数)表示k2的前几位,在下面的例子会有注释介绍basic_string& replace(const_iterator i1, const_iterator i2, iterator k1, iterator k2);//使用迭代器替换
【例】
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str("123456");
string ss("vwxyz");
char s1[6] = "abcde";
char s2[6] = "qwert";
str.replace(2,3,ss);//将str[2,4]的字符串替换为字符串ss
cout<<str<<endl;
str = "123456";
str.replace(2,3,ss,1,3);//将str[2,4]的字符串替换为字符串ss[1,3]
cout<<str<<endl;
str = "123456";
str.replace(1,2,s1,3);//将str[1,2]的字符串替换为c_string类型字符串s1的前3个字符
cout<<str<<endl;
str = "123456";
str.replace(1,2,s1);//将str[1,2]的字符串替换为c_string类型字符串s1
cout<<str<<endl;
str = "123456";
str.replace(3,2,6,'a');//将str[3,4]的字符串替换为6个'a',即aaaaaa
cout<<str<<endl;
str = "123456";
str.replace(str.begin()+1,str.begin()+4,ss);//将str[1,4)的字符串替换为字符串ss
cout<<str<<endl;
str = "123456";
str.replace(str.begin()+1,str.begin()+4,s1,3);//将str[1,4)的字符串替换为c_string类型字符串的前3个字符
cout<<str<<endl;
str = "123456";
str.replace(str.begin()+1,str.begin()+4,s1);//将str[1,4)的字符串替换为c_string类型字符串s1
cout<<str<<endl;
str = "123456";
str.replace(str.begin(),str.begin()+5,6,'c');//将str[0,5)的字符串替换为6个字符c
cout<<str<<endl;
str = "123456";
str.replace(str.begin()+1,str.begin()+3,s1,s2+3);//将str[1,3)的字符串替换为c_string类型字符串s1+s2的前3个字符
//值的注意的是,s2+n保留s2的前n个字符。而s1+n,则保留s1从第n个字符开始直到末尾的字符串
//即str.replace(str.begin()+1,str.begin()+3,s1+2,s2+3);//则输出1cdeqwe456
cout<<str<<endl;
str = "123456";
str.replace(str.begin(),str.end(),ss.begin(),ss.end());//将str替换为ss
cout<<str<<endl;
return 0;
}
以下为程序运行结果:
12vwxyz6
12wxy6
1abc456
1abcde456
123aaaaaa6
1vwxyz56
1abc56
1abcde56
cccccc6
1abcdeqwe456
vwxyz
7.字符串的比较
字符串可以和类型相同的字符串相比较,也可以和具有同样字符类型的数组比较。
basic_string 类模板既提供了 >、<、==、>=、<=、!= 等比较运算符,还提供了 compare() 函数,其中 compare() 函数支持多参数处理,支持用索引值和长度定位子串进行比较。该函数返回一个整数来表示比较结果。如果相比较的两个子串相同,compare() 函数返回 0,大于返回正值,小于返回负值。
- compare()
比较两字符串大小
类 basic_string 的成员函数 compare() 的原型如下:
int compare(const basic_string& str) const;//直接与str比较
int compare(size_type pos, size_type n, const basic_string& str) const;
//调用串在区间[pos,pos+n-1]上的子字符串与字符串str比较int compare(size_type pos1, size_type n1, const basic_string& str,size_type pos2, size_type n2 = npos) const;//调用串在区间[pos1 , pos1 + n1 -1]上的子字符串与字符串str在区间[pos2,pos2+n2 – 1]上的子字符串比较(n2默认指向末尾)
int compare(const char* s) const; //直接与c_string类型的字符串s比较
int compare(size_type pos, size_type n1, const char* s) const;
//调用串在区间[pos,pos+n1 – 1]上的子字符串与c_string类型字符串s比较int compare(size_type pos, size_type n1, const char* s,size_type n2) const;
//调用串在区间[pos,pos+n1 – 1]上的子字符串与c_string类型字符串s的前n2个字符比较
【例】
#include<iostream>
#include<string>
using namespace std;
string comp(int result)
{
if(result==0)
return "=";
else if (result>0)
return ">";
else
return "<";
}
int main()
{
string str("123456");
string ss("1234");
char s[6] = "123ab";
int result;
result = str.compare(ss);//123456与1234比较
cout<<comp(result)<<endl;
result = str.compare(0,5,ss);//12345与1234比较
cout<<comp(result)<<endl;
result = str.compare(0,2,ss,2,2);//12与34比较
cout<<comp(result)<<endl;
result = str.compare(s);//123456与123ab比较
cout<<comp(result)<<endl;
result = str.compare(0,3,s);//123与123ab比较
cout<<comp(result)<<endl;
result = str.compare(0,3,s,3);//123与123比较
cout<<comp(result)<<endl;
return 0;
}
下面为程序运行结果:
>
>
<
<
<
=
- 重载操作符<,>,==,<=,>=,!=
与数字的比较相同,不再赘述
值得一提的是字符串比较规则:
- 字符串比较大小并不是比较二者的长度。
- 字符串比较大小,从左数第一个字符开始进行比较
- 进行比较的是两字符的ASCII码的大小
- 逐一进行比较,如果出现差异直接结束比较,否则继续比较下一个字符,直到某一个字符串结束
8.字符串的查找
在 C 语言和 C++ 语言中,可用于实现字符串查找功能的函数非常多。在 STL 中,字符串的查找功能可以实现多种功能,比如说:
- 搜索单个字符、搜索子串;
- 实现前向搜索、后向搜索;
- 分别实现搜索第一个和最后一个满足条件的字符(或子串);
若查找 find() 函数和其他函数没有搜索到期望的字符(或子串),则返回 npos;若搜索成功,则返回搜索到的第 1 个字符或子串的位置。其中,npos 是一个无符号整数值,初始值为 -1。当搜索失败时, npos 表示“没有找到(not found)”或“所有剩佘字符”。
值得注意的是,所有查找 find() 函数的返回值均是 size_type 类型,即无符号整数类型。该返回值用于表明字符串中元素的个数或者字符在字符串中的位置。
下面分别介绍和字符查找相关的函数。
- find()和rfind()
find() 函数的原型有以下 4 种:
size_type find(const char* s, size_type pos, size_type n) const;
//第1个参数是被搜索的字符串,第2个参数是源串中开始搜索的下标,第3个参数是关于第1个参数的字符个数,可能是 s 的所有字符数,也可能是 s 的子串宇符个数size_type find(const basic_string& str, size_type pos = 0) const;
//find()函数的第1个参数是被搜索的字符串,第2个参数是在源串中开始搜索的下标位置,默认从头开始搜索size_type find(const char* s, size_type pos = 0) const;
//同上,搜索c_string类型字符串size_type find(char c, size_type pos = 0) const;
//第1个参数是被搜索的单个字符,第2参数是在源串中开始搜索的下标位置,默认从头开始搜索
rfind() 函数的原型和find()函数的原型类似,参数情况也类似。只不过 rfind() 函数适用于实现逆向查找。
【例】
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str("Try not to become a man of success "
"but rather try to become a man of value");
string search("but");
string::size_type position1 = str.find("best");
string::size_type position2 = str.find('o');
string::size_type position3 = str.find("todoit",0,2);
cout<<static_cast<int>(position1)<<endl;
cout<<static_cast<int>(position2)<<endl;
cout<<static_cast<int>(position3)<<endl;
string::size_type position4 = str.rfind(search);
string::size_type position5 = str.rfind('o');
string::size_type position6 = str.rfind("todoit",string::npos,2);
cout<<static_cast<int>(position4)<<endl;
cout<<static_cast<int>(position5)<<endl;
cout<<static_cast<int>(position6)<<endl;
return 0;
}
- find_first_of()和 find_last_of()
find_first_of() 函数可实现在源串中搜索某字符串的功能,该函数的返回值是被搜索字符串的某 1 个字符第 1 次出现的下标(位置)。若查找失败,则返回 npos。
size_type find_first_of(const basic_string& str, size_type pos = 0) const;
//搜索str字符串中的字符第一次在调用串中出现的位置,pos为搜索起点,默认从头开始size_type find_first_of(const char* s, size_type pos, size_type n) const;
//搜索c_string类型字符串s的前n个字符第一次在调用串中出现的位置,pos为搜索起点size_type find_first_of(const char* s, size_type pos = 0) const;
//搜索c_string类型字符串s中的字符第一次在调用串中出现的位置,pos为搜索起点,默认从头开始size_type find_first_of(char c, size_type pos = 0) const;
//搜索字符c第一次在调用串中出现的位置,pos为搜索起点,默认从头开始
find_last_of() 函数同样可实现在源串中搜索某字符串的功能。函数的原型和find_first_of()函数的原型类似,参数情况也类似。与 find_first_of() 函数所不同的是,该函数的返回值是被搜索字符串的最后 1 个字符的下标(位置)。若查找失败,则返回 npos。
- find_first_not_of()和 find_last_not_of()
find_first_not_of() 函数可实现在源字符串中搜索与指定字符(串)不相等的第 1 个字符;
find_last_not_of() 函数可实现在源字符串中搜索与指定字符(串)不相等的最后 1 个字符。
这两个函数的参数及意义与find_first_of() 和 find_last_of()相同,不再赘述。
【例】
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str("Try not to become a man of success "
"but rather try to become a man of value");
string search("but");
char sh[5] = "some";
string::size_type position1 = str.find_first_of("best");
string::size_type position2 = str.find_first_of(sh,34,1);//从str[34]开始搜索第一个为s的字符
string::size_type position3 = str.find_first_of(sh,0);
string::size_type position4 = str.find_first_of('v');
cout<<static_cast<int>(position1)<<endl;
cout<<static_cast<int>(position2)<<endl;
cout<<static_cast<int>(position3)<<endl;
cout<<static_cast<int>(position4)<<endl;
string::size_type position5 = str.find_first_not_of(" abcTrynot");
string::size_type position6 = str.find_first_not_of(sh,0,2);//搜索第一个不是s,o,m的字符
string::size_type position7 = str.find_first_not_of(sh,0);//从str的头开始搜索第一个不是s,o,m,e的字符
string::size_type position8 = str.find_first_not_of('e');//搜索第一个不是e的字符
cout<<static_cast<int>(position5)<<endl;
cout<<static_cast<int>(position6)<<endl;
cout<<static_cast<int>(position7)<<endl;
cout<<static_cast<int>(position8)<<endl;
string::size_type position9 = str.find_last_of(" abcTrynot");
string::size_type position10 = str.find_last_of(sh,string::npos,2);
string::size_type position11 = str.find_last_of(sh,string::npos);
string::size_type position12 = str.find_last_of('e');
cout<<static_cast<int>(position9)<<endl;
cout<<static_cast<int>(position10)<<endl;
cout<<static_cast<int>(position11)<<endl;
cout<<static_cast<int>(position12)<<endl;
string::size_type position13 = str.find_last_not_of(" abcTrynot");
string::size_type position14 = str.find_last_not_of(sh,string::npos,3);
string::size_type position15 = str.find_last_not_of(sh,string::npos);
string::size_type position16 = str.find_last_not_of('e');
cout<<static_cast<int>(position13)<<endl;
cout<<static_cast<int>(position14)<<endl;
cout<<static_cast<int>(position15)<<endl;
cout<<static_cast<int>(position16)<<endl;
return 0;
}
程序运行结果为:
6
-1
5
69
12
0
0
0
70
66
73
73
73
73
72
72
9.string支持迭代器
迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址。迭代器修改了常规指针的接口,所谓迭代器是一种概念上的抽象:那些行为上像迭代器的东西都可以叫做迭代器。然而迭代器有很多不同的能力,它可以把抽象容器和通用算法有机的统一起来。
迭代器提供一些基本操作符:*、++、==、!=、=。这些操作和C/C++“操作array元素”时的指针接口一致。不同之处在于,迭代器是个所谓的复杂的指针,具有遍历复杂数据结构的能力。其下层运行机制取决于其所遍历的数据结构。因此,每一种容器型都必须提供自己的迭代器。事实上每一种容器都将其迭代器以嵌套的方式定义于内部。因此各种迭代器的接口相同,型号却不同。这直接导出了泛型程序设计的概念:所有操作行为都使用相同接口,虽然它们的型别不同。
STL 定义了 5 种迭代器,根据所需的迭代器类型对算法进行描述。这 5 种迭代器分别是:输入迭代器 、输出迭代器 、 正向迭代器、 双向迭代器 和 随机访问迭代器。对于这 5 种迭代器不仅可以执行解除引用操作(* 操作符),还可进行比较。这里主要讲述 basic_string(或 string 类)中迭代器的使用。
basic_string 和 string 类均提供了常规的迭代器和反向迭代器。string 是字符的有序群集。
C++ 标准库为 string 提供了相应接口,便于将字符串作为 STL 容器使用。可以使用迭代器遍历 string 内的所有字符;也可以使用其他算法遍历 string 内的所有字符。而且能够访问字符串中的每个字符,并对这些字符进行排序、逆向重排、找出最大值等操作。
string 类的迭代器是随机存取迭代器,即支持随机存取。任何一个 STL 算法都可与其搭配使用。通常 string 的“迭代器型别”由 string 类本身定义,通常可以被简单地定义为一般指针。对迭代器而言,如果发生重新分配,或其所指的值发生某些变化时,迭代器会失效。
string 类中和使用迭代器相关的成员函数是很多的,主要包括 begin()、end()、rbegin ()、rend()、append()、assign()、insert()、erase()、replace() 等。
名称 | 功能 |
---|---|
begin( ) | 返回指向字符串第一个字符的迭代器。 |
end() | 返回指向字符串最后一个字符(’\0’)的迭代器。 |
cbegin() | 返回指向字符串第一个字符的const类型迭代器。 |
cend() | 返回指向字符串最后一个字符(’\0’)的const类型迭代器。 |
rbegin() | 返回一个反向迭代器,该迭代器指向字符串的最后一个字符(即它的反向开始)。 |
rend() | 返回一个反向迭代器,该迭代器指向字符串第一个字符之前的理论元素(该字符被视为反向元素)。 |
crbegin() | 返回一个const类型反向迭代器,该迭代器指向字符串的最后一个字符(即它的反向开始)。 |
crend() | 返回一个const类型反向迭代器,该迭代器指向字符串第一个字符之前的理论元素(该字符被视为反向元素)。 |
begin()与cbegin()的区别是 begin()指向非const的字符串时,可以对其进行修改,而cbegin()只能指向const类型字符串(即开头的c表示const,r表示reverse)。其余同上。
#include<iostream>
#include<string>
#include<algorithm>
#include<iterator>
using namespace std;
int main()
{
string str("Standing up to your own."
"That would take a real hero.");
cout<<str<<endl;
string::iterator it;//使用正向迭代器遍历字符串
for(it = str.begin();it!=str.end();it++)
cout<<*it;
//function();//可以进行其他操作
cout<<endl;
string::reverse_iterator rev_it;//使用反向迭代器倒序输出字符串
for(rev_it = str.rbegin();rev_it!=str.rend();rev_it++)
cout<<*rev_it;
//function();//可以进行其他操作
cout<<endl;
std::ostreambuf_iterator<char> out_it(std::cout);//使用输出流迭代器正序输出字符串
std::copy(str.begin(),str.end(),out_it);
cout<<endl;
std::ostreambuf_iterator<char> rev_out_it(std::cout);//使用输出流迭代器倒序输出字符串
std::copy(str.rbegin(),str.rend(),rev_out_it);
cout<<endl;
//还有各种函数中使用迭代器,在上文已经涉及
return 0;
}
程序运行结果为:
Standing up to your own.That would take a real hero.
Standing up to your own.That would take a real hero.
.oreh laer a ekat dluow tahT.nwo ruoy ot pu gnidnatS
Standing up to your own.That would take a real hero.
.oreh laer a ekat dluow tahT.nwo ruoy ot pu gnidnatS
资料来源
- The C++ Resources Network(http://www.cplusplus.com)
- C语言中文网(http://m.biancheng.net)
- 百度百科 (https://baike.baidu.com/item/capacity/6299959)
- 百度百科 (https://baike.baidu.com/item/%E8%BF%AD%E4%BB%A3%E5%99%A8)