C++ string类基本操作
为什么我们需要string
1.尽管在C中我们可以使用char*类型的指针来指向一个字符串数组,但是在字符串的长度、字符串的空间等等我们都需要考虑,这就给我们设计的时候带来了极大的困扰
2.对于char*类型的数据,我们进行赋值、比较等操作的时候都需要逐一进行,这就给复用带来了问题。
3.同基本数据类型一样,string是C++封装好的一个类,可以将它作为基本数据类型来使用,就解决了很多原来char*类型数据的复杂的问题
基本操作
引入
string类在头文件iostream中,直接引入即可使用(引入string也可以)
#include<iostream>
构造函数与析构函数
1) string s; //生成一个空字符串s
string a;
2) string s(string str) //拷贝构造函数 生成str的复制品
string s = "123456";
string a(s);//123456
3) string s(string str,int stridx) //将字符串str内从stridx开始的部分当作字符串的初值
string s = "123456";
string a(s,2);//3456
4) string s(string str,int stridx,int strlen) //将字符串str内始于stridx且长度顶多strlen的部分作为字符串的初值
string s = "123456";
string a(s, 2, 4);//3456
5) string s(const char* cstr) //将C字符串作为s的初值
string a("123456");//123456
6) string s(const char* cstr,int chars_len) //将C字符串前chars_len个字符作为字符串s的初值。
string a("123456",5);//12345
7) string s(int num,char c) //生成一个字符串,包含num个c字符
string a(3,'1');//111
8) s.~string() //销毁所有字符,释放内存
string a;
a.~string();
当然还可以以对象的形式创建
1) string* s = new string;
string* s = new string("hello");
2) delete s;
类变量
//string::npos是一个string类的类变量,即定义为
static const string::npos;
//这是一个无符号数,但有时该值是-1,但是他并不表示位置
//通常,这个类变量会在调用find()方法查找失败时作为返回值出现
//或作为一个字符串的长度参数表示到字符串的结尾
迭代器
string虽然不是标准的STL容器,但是string也可以像STL容器一样使用迭代器来完成一些工作
迭代器可以简单理解为指针,实际上迭代器的底层就是用指针实现的
迭代器总共有四种:
- 正向迭代器(iterator)
- 反向迭代器(reverse_iterator)
- 只读迭代器(const_iterator)
- 只读反向迭代器(const_reverse_iterator)
当我们有针对const修饰的对象时,则必须使用只读迭代器const_iterator
API
string提供了8种API接口,每两种接口分别对应一种迭代器
begin类接口
begin():指向容器第一个元素的位置(可读可写),对应iterator
rbegin():指向容器最后一个元素的位置(可读可写),对应reverse_iterator
cbegin():指向容器第一个元素的位置(只读),对应const_iterator
crbegin():指向容器最后一个元素的位置(只读),对应const_reverse_iterator
end类接口
end():指向容器最后一个元素的下一个位置(可读可写),对应iterator
rend():指向容器第一个元素的前一个位置(可读可写),对应reverse_iterator
cend():指向容器最后一个元素的下一个位置(只读),对应const_iterator
crend():指向容器第一个元素的前一个位置(只读),对应const_reverse_iterator
迭代器可以用于遍历string,详情戳迭代器遍历
迭代器失效
迭代器失效指的是,迭代其所指向的对象不再是我们所期望的指向的对象。
什么意思?先看代码:
string s = "abcdef";
string::iterator iter = s.begin();
s.insert(0, "0");
cout << *iter;//0
这里我们的迭代器iter指向了字符a,但是我们调用了insert插入了字符0,现在字符s是0abcdef了,这时候调用迭代器输出结果为0,这表明迭代器也跟着插入更新了指向,这就是迭代器实效的一个范例,他不在指向原来的对象了。
除了插入,迭代器失效还可能发生在其他地方,比如我们使用了迭代器,却又对对象内容进行修改与扩容或删除(比如for循环中扩容、删除)
总之,当我们使用迭代器,同时又要对对象内容或者容量进行修改时,再修改结束后一定要更新迭代器以确保迭代器不会失效。
类方法
注:这里许多函数原型并非标准的函数原型,只是为了方便理解(比如size_t标注为int表示我们一般调方法的时候输入为int)
=与assign(赋值)
1.=与asign()
string s = "123456";//123456
//或使用assign方法(多个重载)
s.assign(string str); //赋值str给s
string a = "123";
string s;
s.assign(a);//123
s.assign(string str,int beg,int end);//将str从索引为beg到end(包括)end赋值给s
string a = "123";
string s;
s.assign(a,1,2);//23
s.assign(string str,int beg,const string::npos);//把字符串str从索引值beg开始到结尾赋给s
string a = "123";
string s;
s.assign(a,2,string::npos);//3
s.assign(cstr); //赋值c字符串给s
string s;
s.assign("123");
s.assign(const char* cstr,int strlen);//把c字符串长度为strlen的字符赋给字符串s
string s;
s.assign("123456",2);//12
s.assign(int num,char c);//把num个c赋值给s
string s;
s.assign(3,'1'); //111
+=、append()、push_back()(添加字符)
以上方法都是在结尾处增加字符
2.+=、append()、push_back()
s += mystr;
string s = "123";
string a = "456";
s += a;//123456,同理这里可以加string对象或者单个字符
s.append();
//该方法同样有多个重载,参数类型与assign一致,这里不再演示
s.push_back(char c);
//该方法只接受一个字符
string s = "123";
s.push_back('a');//123a
插入、删除与替换
3.insert()
s.insert();
//三个重载,分别用于接收string对象和string常量和迭代器
s.insert(int stridx,string str);
string s = "13";
string a = "2";
s.insert(1, a);//123,接受对象
s.insert(int stridx,const char* cstr);
string s = "13";
s.insert(1,"2");//123,接受常量
s.insert(iterator iter,int num,char c);
//其中num表示插入的个数,可以不写
string s = "23";
s.insert(s.begin(),'1');//123,迭代器
4.erase()/clear()
s.erase();
s.erase(iterator iter);
//删除迭代器指向的字符
string s = "123456";
s.erase(s.begin());//23456
s.erase(iterator beg,iterator end);
//删除从beg开始到end结尾(包括)的字符
string s = "123456";
s.erase(s.begin(),s.end() - 1);//6
s.erase(int beg,int end);
//删除从索引为beg开始到end的字符
string s = "123456";
s.erase(1,4);//16
s.clear();
//清空整个字符串
string s = "1234";
s.clear();//""
5.replace()
s.replace();
s.replace(int stridx,int len,const char* cstr);
//将从stridx索引开始长度为len的字符串转变为c字符串str
string s = "boys and world";
s.replace(9, 5, "girl");//boys and girl
s.replace(int stridx,int len,int num,char c);
//将从stridx索引开始长度为len的字符串转变为num个字符c
string s = "boys and world";
s.replace(9, 5, 6, '.');//boys and ......
s.replace(iterator iter1, iterator iter2, const char* s);
//将iter1(包括)到iter2(不包括)的字符串改为s
string s = "world and girl";
s.replace(s.begin(),s.begin()+5,"boys");//boys and gril
长度与判空
6.size()/length()
s.size();
string s = " ";
cout << s.size();//3
s.length();
string s = " 1";
cout << s.length();//4
7.empty()
s.empty();
//返回值为1或0
string s = " ";
s.empty();//返回值为0
遍历
8.auto/iterator/reverse_iterator/[]
auto方法
string s = "boys and girl";
for (auto c : s) {
cout << c;
}//boys and girl
iterator正向迭代器
string s = "boys and girl";
for (string::iterator iter = s.begin(); iter != s.end();iter++) {
cout << *iter;
}//boys and girl
reverse_iterator逆向迭代器
string s = "boys and girl";
for (string::reverse_iterator iter = s.rbegin(); iter != s.rend();iter++) {
cout << *iter;
}//lrig dna syob
[]下标表示法
string s = "boys and girl";
for (int i = 0; i < s.size();i++) {
cout << s[i];
}//boys and girl
string与C字符串转换
9.c_str()
c_str();
//这是为了与C语言兼容所创造的函数,用于将string转为C字符串,该方法会在末尾加上'\0'
//返回值为C字符串首字符的地址
string s = "boys and girl";
const char* cstr = s.c_str();
//cstr指向了字符数组boys and girl
比较函数
10.compare/</>/==/<=/>=/!=
//比较遵从字典顺序,如果当前字符小,则返回小于0大则返回大于0,所有都相等就返回0
//存在多个重载,如下
s.compare(string str);
s.compare(const char* cstr);//c字符串
s.compare(int stridx1,int stridy1,int stridx2,int stridy2);
//从索引为stridx1(包括)到stridy2(不包括)与从stridx2(包括)到stridy2(不包括)比较
s.compare(int stridx,int stridy,string str,int len);
//从索引为stridx(包括)到stridy(不包括)与str被截取长度为len的字符串比较
获取子串与拼接
11.substr/+
s.substr();
//多个重载,直接调用就返回整个字符串
s.substr(int stridx);
string s = "boys and girl";
string a = s.substr(5);//and girl
s.substr(int stridx,int len);
//从stridx(包括)开始长度为len的字符串
string s = "boys and girl";
string a = s.substr(5,3);//and
输入输出
12.cin/cout
//没啥好说的
string a;
cin >> a;
cout << a;
大小写
13.tolower/toupper
//借用C的函数
string s = "ABCDEFG";
for( int i = 0; i < s.size(); i++ )
{
s[i] = tolower(s[i]);
}//abcdefg
14.借用transform配合实现(需要引入头文件algorithm)
//小写
string s = "ABCDEFG";
transform(s.begin(), s.end(), s.begin(), ::tolower);//abcdefg
//大写
string s = "abcdefg";
transform(s.begin(), s.end(), s.begin(), ::toupper);//ABCDEFG
查找
15.find/rfind/find_first_of/find_first_not_of/find_last_of/find_last_not_of
s.find (const char* cstr);
//在s中寻找字符串cstr,找到则返回索引,否则返回string::npos
string s = "abcdefg";
s.find("cde");//2
s.find (const char* cstr, int stridx);
//从索引为stridx开始查找cstr,找到则返回索引,否则返回string::npos
string s = "abcdefgcde";
s.find("cde",3);//7
s.rfind (const char* cstr);
//从后往前查找字符串cstr,找到则返回索引,否则返回string::npos
string s = "abcdefgcde";
s.rfind("cde");//7
s.rfind (const char* cstr, int stridx);
//从索引为stridx开始从后往前查找cstr,找到则返回索引,否则返回string::npos
string s = "abcdefgcde";
s.rfind("cde",6);//2
s.find_first_of(const char* cstr);
//将字符串s的字符与cstr逐个匹配,返回找到第一个存在于cstr字符串的字符在s中的索引,否则返回string::npos
string s = "abcdefgcdef";
s.find_first_of("1234567f");//s中第一个存在于cstr的字符为f,index为5
s.find_first_of(const char* cstr,int stridx);
//从索引为stridx开始将字符串s的字符与cstr逐个匹配,返回找到第一个存在于cstr字符串的字符在s中的索引,找到则返回索引,否则返回string::npos
string s = "abcdefgcdef";
s.find_first_of("1234567f",6);//10
s.find_first_not_of(const char* cstr);
//将字符串s的字符与cstr逐个匹配,返回找到第一个不存在于cstr字符串的字符在s中的索引,否则返回string::npos
string s = "abbbcdeffff";
s.find_first_not_of("ab1");//c不在ab1中,返回4
s.find_first_not_of(const char* cstr,int stridx);
//从索引为stridx开始将字符串s的字符与cstr逐个匹配,返回找到第一个不存在于cstr字符串的字符在s中的索引,否则返回string::npos
string s = "abbbcdeffff";
s.find_first_not_of("ab1",6);//f不在ab1中,返回6
s.find_last_of(const char* cstr);
//将字符串s的字符与cstr逐个匹配,返回找到最后一个存在于cstr字符串的字符在s中的索引,否则返回string::npos
string s = "accbccb";
s.find_last_of("ab1");//6
s.find_last_not_of(const char* cstr);
//将字符串s的字符与cstr逐个匹配,返回找到最后一个不存在于cstr字符串的字符在s中的索引,否则返回string::npos
string s = "accbccbcccc";
s.find_last_not_of("ab1");//10
排序
16.sort
//结合algorithm库的sort函数(可加cmp)
string s = "cdefba";
sort(s.begin(),s.end());//abcdef