前言
string作为我们最先了解的stl,我们需要很深入很全面的学习,方便以后学习其他的stl。
typedef basic_string<char> string;首先我们看到string是一个类模板,经过封装之后呈现出来的。
学习string我们要从使用string类、理解string类、模拟实现string类的底层。
string类的使用
1.string类对象的常见构造
接下来是对这些常见构造的代码使用。
#include<string>
#include<iostream>
using namespace std;
int main()
{
//string() (重点),小括号可以省略
string s1();
//string(const char* s) (重点)
string s2("abcd");
//string(const string&s) (重点) ,拷贝构造
string s3(s2);
return 0;
}
2. string类对象的容量操作
1.size(返回字符串的有效字符长度)
#include<string>
#include<iostream>
using namespace std;
int main()
{
string s1 = "asdfd";
//string::size()与string::length()作用相同,但是后面的stl均用string::size(),所以 string::length()不作为重点。
cout << s1.size() << endl;//5
cout << s1.length() << endl;//5
return 0;
}
2.empty(检测字符串释放为空串,是返回true,否则返回false)
#include<string>
#include<iostream>
using namespace std;
int main()
{
string s1 = "asdfd";
cout << s1.empty() << endl;//0
string s2;
cout << s2.empty() << endl;//1
return 0;
}
3.clear(清空有效字符)
#include<string>
#include<iostream>
using namespace std;
int main()
{
string s1 = "asdfd";
cout << s1.empty() << endl;//0
s1.clear();
cout << s1.empty() << endl;//1
return 0;
}
4.string的扩容(reserve和resize)
#include<string>
#include<iostream>
using namespace std;
void TestPushBack()
{
string s;
size_t sz = s.capacity();
cout << "capacity changed: " << sz << '\n';
cout << "making s grow:\n";
for (int i = 0; i < 100; ++i)
{
s.push_back('c');
if (sz != s.capacity())
{
sz = s.capacity();
cout << "capacity changed: " << sz << '\n';
}
}
}
int main()
{
TestPushBack();
return 0;
}
当有效字符长度小于16时,字符会存入_Buf空间中,大于16时再存入_Ptr空间中。在VS下为1.5倍扩容,然而在linux操作系统下buffer的概念,与顺序表类似为二倍扩容。
测试:string s1("11111111"); string s2("1111111111111111111111111111111111");
int main()
{
string s1;
//此时开辟空间位置的数据为默认字符
s1.resize(5);
string s2;
//此时开辟空间位置的数据为字符‘5’
s2.resize(5, '5');
return 0;
}
注意:
1. size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一 致,一般情况下基本都是用size()。
2. clear()只是将string中有效字符清空,不改变底层空间大小。
3. resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字 符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的 元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大 小,如果是将元素个数减少,底层空间总大小不变。
4. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于 string的底层空间总大小时,reserver不会改变容量大小。
5.capacity()比实际空间少一个,有一个多的预留给了‘\0’。
6.在VS下默认不缩容
3. string类对象的访问及遍历操作
1.operator[](返回pos位置的字符,const string类对象调用)
int main()
{
string s1("11111222");
for (int i = 0; i < s1.size(); i++)
{
cout << s1[i] << " ";//1 1 1 1 1 2 2 2
}
cout << endl;
return 0;
}
2.迭代器(begin+end)
int main()
{
string s1("11111222");
string::iterator it = s1.begin();
while (it != s1.end())
{
cout << *it << endl;//1 1 1 1 1 2 2 2
it++;
}
return 0;
}
现阶段可以把迭代器理解为指针。
3.反向迭代器(rbegin+rend)
int main()
{
string s1("11111222");
string::reverse_iterator rit = s1.rbegin();
while (rit != s1.rend())
{
cout << *rit << " ";//2 2 2 1 1 1 1 1
++rit;
}
cout << endl;
return 0;
}
4.范围for(C++11支持更简洁的范围for的新遍历方式)
int main()
{
string s1("liuzhi66");
//使用引用会使效率更高,尤其是对于自定义类型
for (const auto& e : s1)
{
cout << e ;//liuzhi66
}
cout << endl;
return 0;
}
4. string类对象的修改操作
1.operator+=(在字符串后追加字符串str)
int main()
{
string s1("llliiuuzzhi");
cout << s1 << endl;//llliiuuzzhi
s1 += "sdafsd";
cout << s1 << endl;//llliiuuzzhisdafsd
return 0;
}
2.c_str(返回C格式字符串)
// strings and c-strings
#include <iostream>
#include <cstring>
#include <string>
int main ()
{
std::string str ("Please split this sentence into tokens");
char * cstr = new char [str.length()+1];
std::strcpy (cstr, str.c_str());
// cstr now contains a c-string copy of str
char * p = std::strtok (cstr," ");
while (p!=0)
{
std::cout << p << '\n';
p = std::strtok(NULL," ");
}
delete[] cstr;
return 0;
}
3.find(从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置)
// string::find
#include <iostream> // std::cout
#include <string> // std::string
int main ()
{
std::string str ("There are two needles in this haystack with needles.");
std::string str2 ("needle");
// different member versions of find in the same order as above:
std::size_t found = str.find(str2);
if (found!=std::string::npos)
std::cout << "first 'needle' found at: " << found << '\n';
found=str.find("needles are small",found+1,6);
if (found!=std::string::npos)
std::cout << "second 'needle' found at: " << found << '\n';
found=str.find("haystack");
if (found!=std::string::npos)
std::cout << "'haystack' also found at: " << found << '\n';
found=str.find('.');
if (found!=std::string::npos)
std::cout << "Period found at: " << found << '\n';
// let's replace the first needle:
str.replace(str.find(str2),str2.length(),"preposition");
std::cout << str << '\n';
return 0;
}