目录
学前必须掌握知识
string字符串是表示字符序列的类,标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作 单字节字符字符串的设计特性。string在底层实际是:basic_string
模板类的别名,typedef basic_string<char, char_traits, allocator> string
;
使用string类,需要引入头文件< string >
学习string接口之前,我们必须知道什么是迭代器
迭代器是一种设计模式,是元素访问的一种设计模式,所有容器都是需要遵循相同的设计规范。例如手机的充电线,我们常用的type-c接口,无论是哪个厂商生产的,你手机只要支持type-c充电线,都可以充电。而迭代器的使用方式都是一样的那如何使用呢?
迭代器的使用方式和指针类似
1、begin迭代器:指向第一个元素的位置
2、end迭代器:指向最后一个元素的下一个位置
3、访问数据方式:*
、->
4、迭代器的移动:++移动到下一个元素的位置;–移动到上一个元素的位置
5、迭代器支持比较:!=
、 ==
特殊的反向迭代器
1、rbegin迭代器:指向最后一个元素的位置
2、rend迭代器:指向第一个元素的前一个位置
string类对象的常见构造
功能:构造一个字符串对象,根据所使用的构造函数版本来初始化其值
string()
创建一个空对象
string (const string& str)
拷贝一个字符串对象
string (const char* s)
给予字符串常量来创建字符串
string (const string& str, size_t pos, size_t len = npos)
截取字符串str,从pos位置开始截取len个
string (const char* s, size_t n)
给予字符串常量并从头开始截取n个字符来创建字符串对象
string (size_t n, char c)
创建字符串,内容为n个字符c
string& operator= (const string& str)
给予字符串常量来创建字符串
string& operator= (const char* s)
拷贝一个字符串对象
void test()
{
string str; // ""
string copy(str); // ""
string str2("White"); // "White"
string substr(str2, 1, 2); //"hi"
string str3("White ShirtI", 5);//white
string str4(5, 'w'); //"wwwww"
str3 = "White ShirtI"; //"White ShirtI"
str4 = str3; //"White ShirtI"
}
常见的访问字符串操作
char& operator[] (size_t pos)
和数组一样通过下标去访问字符串内容,并且可以修改字符串内容(越界会报断言错误)
const char& operator[] (size_t pos) const
和上面接口一样,但是不能修改字符串的内容
char& at (size_t pos)
与[]一样通过索引访问字符串,且可以修改字符串内容(越界会抛异常)
const char& at (size_t pos) const
和上面接口一样,但是不能修改字符串的内容
char& front()
访问字符串第一个有效字符,可修改
const char& front() const
访问字符串第一个有效字符,不可修改
char& back()
访问字符串最后一个有效字符,可修改
const char& back() const
访问字符串最后一个有效字符,不可修改
void test()
{
string str = "White shirtI";
char& ref = str[7];
ref = 'S'; //ok
str.at(0) = 'w'; //ok
const string str2 = "White ShirtI";
const char& ref2 = str2[0];
ref2 = 'w'; //error 表示必须是可修改的左值
str2.at(0) = 'w';//error 表示必须是可修改的左值
}
string中迭代器的使用
正向迭代器
iterator begin()
指向字符串第一个有效元素,并可以修改
const_iterator begin() const
指向字符串第一个有效元素,不能修改
iterator end()
指向字符串最后一个有效元素的下一个位置,并可以修改
const_iterator end() const
指向字符串最后一个有效元素的下一个位置,不能修改
void test()
{
string str = "WhiteShirtI";
string::iterator it = str.begin();
for (; it != str.end(); ++it)
{
cout << *it; //WhiteShirtI
*it = 'w';
}
const string str2 = "WhiteShirtI";
string::const_iterator it2 = str.begin();
for (; it != str.end(); ++it)
{
cout << *it2;
*it2 = 'w'; // error 表达式必须为可修改的左值
}
}
反向迭代器
reverse_iterator rbegin()
指向字符串最后一个有效字符的位置,并且能修改
const_reverse_iterator rbegin() const
指向字符串第一个有效字符的位置,不能修改
reverse_iterator rend()
指向字符串第一个有效位置的前一个位置,并且能修改
const_reverse_iterator rend() const
指向字符串第一个有效位置的前一个位置,不能修改
void test()
{
string str = "12345";
string::reverse_iterator rit = str.rbegin();
while (rit != str.rend())
{
cout << *rit << " "; //5 4 3 2 1
*rit = 'w';
//反向迭代器,什么都是反的
++rit;
}
const string str2 = "12345";
string::const_reverse_iterator rit2 = str2.rbegin();
while (rit2 != str2.rend())
{
cout << *rit2 << " "; //5 4 3 2 1
*rit2 = 'w';//error 表达式必须为可修改的左值
//反向迭代器,什么都是反的
++rit2;
}
}
遍历字符串可以通过数组方式通过下边遍历,也可以通过范围for来遍历,范围for底层也是通过迭代器来实现的,获取头尾元素以及迭代器的自增
void test()
{
string str = "WhiteShirtI";
for (const auto& ch : str)
{
cout << ch;
}
}
string有关容量的常见接口
size_t size() const
获取有效字符的个数
size_t length() const
获取有效字符的个数
void resize (size_t n)
修改有效字符的个数,如果修改后比原有的有效字符个数多,多出的部分都置为字符’\0’(’\0’并非为有效字符的结束标志,这里’\0’也是有效字符串的其中一个)
void resize (size_t n, char c)
修改有效字符的个数,如果修改后比原有的有效字符个数多,多出的部分都置为字符c
void test()
{
string str = "White";
cout << str.size() << endl;
cout << str.length() << endl;
str.resize(10);
cout << str.size() << endl;
str.resize(2);
cout << str.size() << endl;
string str2 = "Shirt";
cout << str.size() << endl;
str2.resize(10, 'I'); //"ShirtIIIII"
cout << str.size() << endl;
str2.resize(5, 'I'); //有效字符为5,后面参数不起作用
}
capacity为已经开辟的空间大小容量,当前string中最多可以存放的元素个数,增容规则:增容到原来容量的1.5倍。
size_t capacity() const
获得字符串的容量
void reserve (size_t n = 0)
修改字符串的容量(只能调大不能调小,调小相当于没修改)
void test()
{
string str = "White";
cout << str.capacity() << endl; //默认为15
cout << str.size() << endl; //5
//修改容量不会影响有效元素个数
str.reserve(30);
cout << str.capacity() << endl; //30以上
cout << str.size() << endl; //5
//修改有效元素个数会影响容量,并且 cap > size
str.resize(60);
cout << str.capacity() << endl; //60以上
cout << str.size() << endl; //60
}
void clear()
清空有效字符,置size为0,但不影响容量大小
bool empty() const
判断字符串是否为空,为空返回NULL
void shrink_to_fit()
缩小容量为适合size的大小,优化。
void test()
{
string str = "White";
cout << str.size() << endl;
str.clear();
cout << str.size() << endl;
str.reserve(1000);
cout << str.capacity() << endl;
str.shrink_to_fit();
cout << str.capacity() << endl;
}
常见修改string字符串的接口
string& operator+= (const string& str)
在原来字符的后面添加str字符串的内容
string& operator+= (const char* s)
在原来字符的后面添加常量字符串s
string& operator+= (char c)
在原来字符的后面添加常量字符c
void test()
{
string str;
string str2 = "abc";
str += str2; //"abc"
str += "def"; //"abcdef"
str += 'g';//"abcdefg"
}
string& append (const string& str)
追加一个字符串的内容
string& append (const string& str, size_t subpos, size_t sublen)
追加一个字符串的内容,从该字符串的第subpos位置起追加sublen个字符
string& append (const char* s)
追加一个常量字符串
string& append (const char* s, size_t n)
追加一个常量字符串的前n个
string& append (size_t n, char c)
追加n个字符c
template <class InputIterator> string& append (InputIterator first, InputIterator last)
从一个字符串的first位置追加到last位置
void test()
{
string str;
string str2 = "abc";
str.append(str2);//"abc"
str.append(str2, 1, 2);//"abcbc"
str.append("abc"); //"abcbcabc"
str.append("123456789", 6);//"abcbcabc123456"
str.append(5, 'w'); // "abcbcabc123456wwwww"
char arr[] = "abc";
str.append(arr, arr + sizeof(arr) / sizeof(arr[0])); //"abcbcabc123456wwwwwabc"
str.append(str2.begin(), str2.end()); //"abcbcabc123456wwwwwabcabc"
}
string& assign (const string& str)
将内容修改为与str内容一样
string& assign (const string& str, size_t subpos, size_t sublen)
将内容修改为str字符串从subpos位置起添加sublen个字符
string& assign (const char* s)
将内容修改为与常量字符串内容一样
string& assign (const char* s, size_t n)
将内容修改为常量字符串的前n个
string& assign (size_t n, char c)
将内容修改为n个字符c
template <class InputIterator> string& assign (InputIterator first, InputIterator last)
将字符内容设置为从first位置带last位置的内容一样
void test()
{
string str;
string str2 = "abc";
str.assign(str2); //abc
str.assign(str2, 1, 2);// bc
str.assign("abc"); //abc
str.assign("abcde", 4); //abcd
str.assign(5, 'w'); //wwwww
str.assign(++str2.begin(), str2.end()); // bc
}
string& insert (size_t pos, const string& str)
在pos位置前插入字符串str的内容
string& insert (size_t pos, const string& str, size_t subpos, size_t sublen)
在pos位置前插入字符串subpos位置起sublen个字符
string& insert (size_t pos, const char* s)
在pos位置前插入常量字符串s的内容
string& insert (size_t pos, const char* s, size_t n)
在pos位置前插入常量字符串s的n个字符
string& insert (size_t pos, size_t n, char c)
在pos位置前添加n个字符c
void insert (iterator p, size_t n, char c)
在迭代器之前插入n个字符c
template <class InputIterator> void insert (iterator p, InputIterator first, InputIterator last)
在迭代器p位置之前插入first到last迭代器的内容
void test()
{
string str = "123";
string str2 = "abc";
str.insert(0, str2);//abc123
str.insert(3, str2, 1, 1);//abcb123
str.insert(str.size(), "www"); // abcb123www
str.insert(7, "abc", 2);//abcb123ab3www
str.insert(str.size(), 5, 'a');//abcb123ab3wwwaaaaa
str.insert(str.begin(), 2, '1');//11abcb123ab3wwwaaaaa
str.insert(str.end(), str2.begin(), str2.end());//11abcb123ab3wwwaaaaaabc
}
string& erase (size_t pos = 0, size_t len = npos)
从pos位置开始删除,删除npos个元素
iterator erase (iterator p)
删除迭代器所指向的位置的元素
iterator erase (iterator first, iterator last)
删除first到last之间的元素
void test()
{
string str = "Hello WhiteShirtI";
str.erase(1, 2);//"Hlo WhiteShirtI"
str.erase(str.begin());//"lo WhiteShirtI"
str.erase(++str.begin(), --str.end());//"II"
}
string& replace (size_t pos, size_t len, const string& str)
将pos位置开始,共len个元素全部替换成str
string& replace (size_t pos, size_t len, const string& str,size_t subpos, size_t sublen)
将pos位置开始,共len个元素全部替换成str中从subpos位置开始,sublen个元素
void swap (string& str)
调用者与str交换内容
void pop_back()
删除最后一个元素
void test()
{
string str = "abc";
string str2 = "123";
str.replace(0, 1, str2);//123bc
str.replace(0, 1, str2, 0, 2);//1223bc
str.swap(str2); //str:123 str2:1223bc
str.pop_back();//12
}
常见的string查找元素接口
const char* c_str()
返回一个C语言中带有\0的字符串的首地址
size_t find (const string& str, size_t pos = 0) const
查找一个字符串,从pos位置开始,找到字符串的第一个位置
size_t find (const char* s, size_t pos = 0)
查找一个常量字符串,从pos位置开始,找到字符串的第一个位置
size_t find (const char* s, size_t pos, size_t n)
查找一个常量字符串,从pos位置开始,匹配常量字符串的前n个字符就可以,返回第一个字符的位置
size_t find (char c, size_t pos = 0) const
查找字符c,返回第一次查到的位置
rfind与上面函数类似,也有4个接口,从后往前找
void test()
{
char* c = new char[20];
string str = "abc";
strcpy(c, str.c_str()); //c:"abc\0"
string str2 = "123abc123abc";
int pos = str2.find(str, 1); //3
pos = str2.find("bc", 1);//4
pos = str2.find("bcd", 1, 3); //-1
pos = str2.find("bcd", 1, 2); //4
pos = str2.find('c', 0); //5
pos = str2.rfind(str);//9
pos = str2.rfind("bc");//10
pos = str2.rfind("bcd", str2.size(), 3); //-1
pos = str2.rfind('b'); // 10
}
size_t find_first_of (const char* s, size_t pos, size_t n)
从前往后找,找到s中能匹配n个字符的位置,返回第一次遇到的位置
size_t find_last_of (const char* s, size_t pos, size_t n) const
从后往前,找到s中能匹配n个字符的位置,返回第一次遇到的位置
size_t find_first_not_of (const char* s, size_t pos = 0)
从前往后找,找到的第一个不出现在s中的第一个字符
size_t find_last_not_of (const char* s, size_t pos = npos)
从后往前找,找到的第一个不出现在s中的第一个字符
string substr (size_t pos = 0, size_t len = npos) const
从pos位置开始截取len个字符串,赋予新的字符串
void test()
{
//size_t find_first_of (const string& str, size_t pos = 0) const
string str = "abccba123abccba";
int pos = str.find_first_of("fbfc", 0, 2);//1
pos = str.find_last_of("fffb"); //13
pos = str.find_first_not_of("abc");//6
pos = str.find_last_not_of("abc");//8
string substr = str.substr(3, 3);//cba
//使用find与substr获得网站的域名
str = "https://blog.csdn.net/qq_44443986?spm=1011.2124.3001.5113";
int pos1 = str.find("://");
int pos2 = str.find("net");
substr = str.substr(pos1 + 3, pos2 - pos1);//blog.csdn.net
}
字符串常用的输入输出流
istream& operator>> (istream& is, string& str)
与内置类型一样去输入字符串,以换行为结束
istream& getline (istream& is, string& str)
与内置类型一样去输入字符串,以换行为结束
istream& getline (istream& is, string& str, char delim)
与上面函数相似,但是可以指定输入结束标志
ostream& operator<< (ostream& os, const string& str)
像内置类型一样输出字符串的内容
void test()
{
string str;
cin >> str; //换行结束
getline(cin, str); //换行结束
//输入WhirtShirtI
getline(cin, str, 'S'); //White
cout << str << endl;//White
}