【C++】string类常用函数接口
在使用库函数中的string类时,需要包含头文件#include 。
1.构造函数和拷贝构造
string s1;
string s2("hello world");
string s3(s2);
下面通过VS调试的监视窗口看一下初始化之后的内容:
还有一种构造函数,是拷贝一个字符串的一部分:string (const string& str, size_t pos, size_t len = npos);
string s4(s3, 0, 5);
cout << s4 << endl;
string s5(s3, 0);
cout << s5 << endl;
第一个参数是被拷贝的对象,第二个是拷贝开始的位置(注意是从0开始,而不是从1开始);第三个参数是拷贝的字符个数,默认的是npos; npos是一个无符号的-1,补码为全1,是一个非常大的数,也就是说如果我们不传拷贝的长度的话,那么就是从拷贝位置开始,知道字符串结束。
最后还有一种是通过n个char进行构造:string (size_t n, char c);
string s6(10, 'c');
cout << s6 << endl;
下面介绍一种不同的构造写法:
string s7 = “hello world”;在构造函数中是没有这种的,但是这样写实际上进行了隐式类型的转化,”hello world”先构造了一个临时的string对象,临时string对象再拷贝给s7;编译器这时会进行优化,优化为直接构造。
2.operator>>和operator<<
string类中是重载了流插入和流提取运算符的,所以可以直接来使用;
cin >> s1;
cout << s1;
3.operator=
string (1)
string& operator= (const string& str);
c-string (2)
string& operator= (const char* s);
character (3)
string& operator= (char c);
string类型的赋值支持三种形式:
string s1;
string s2("hello world");
s1 = s2;
s1 = "xxxx";
s1 = 'x';
4.operator[ ]
char& operator[] (size_t pos);
const char& operator[] (size_t pos) const;
string对象是可以像数组一样进行访问的:
void test_string3()
{
string s1("hello world");
for (size_t i = 0; i < s1.size(); i++)
{
cout << s1[i];
}
cout << endl;
}
注意string中的size函数是返回string对象的字符个数,返回的类型是size_t。可以借助size函数直接对string对象进行遍历;由于operator[ ]返回的是一个char的引用,所以可以对string对象进行修改,而且引用返回还有一个作用就是减少了拷贝。
const对象会调用 const char& operator[] (size_t pos) const;是不能修改的,只能进行访问。
最后,提到operator[ ]就不得不说另一个方法,at功能和operator[ ]是一样的,但是只能作为函数调用;并且operator[ ]越界会直接assert断言终止程序,at越界会抛异常。
5.Iterator
迭代器: 迭代器 有时又称 光标 是程序设计的 软件设计模式 ,可在容器对象上遍访的接口,设计人员无需关心容器对象的内存分配的实现细节, 各种语言实现迭代器的方式皆不尽同。
void test_string4()
{
string s("iterator");
string::iterator it = s.begin();
while (it != s.end())
{
cout << *it << " ";
it++;
}
cout << endl;
}
iterator是一个像指针一样的类型,有可能就是指针,有可能不是指针,但是用法上像指针。
s.begin()返回的是第一个字符的位置,s.end()返回的是最后一个字符的下一个位置,所以可以通过s.begin()、s.end()对string对象进行遍历。
还有一个点需要注意:while循环的 !=不要写成 < ;因为 <需要物理地址空间连续,在string和vector中可以使用,但是迭代器是所有容器通用的遍历方式,比如list物理空间一定是连续的,那么此时就不能用 < ,只能用 !=。
既然提到了迭代器,就需要介绍一下另一种简单的遍历方式,范围for:这种遍历方式的底层就是迭代器,但是写起来很简单,下面以遍历我们在test_string4中的string对象s为例。
for (auto ch : s)
{
cout << ch << " ";
}
cout << endl;
范围for会自动迭代,自动判断结束;会依次取s的每个字符,赋值给ch。
有了正向的迭代器,也有反向的迭代器,反向迭代器会反向的取数据:
void test_string5()
{
string s("reverse_iterator");
string::reverse_iterator rit = s.rbegin();
while (rit != s.rend())
{
cout << *rit;
rit++;
}
cout << endl;
}
在使用上正向和反向迭代器其实是一样的,需要注意的是无论是正向迭代器还是反向迭代器都需要标明类域,因为迭代器就是在类域当中的。
一般的迭代器会有两种形式:iterator begin(); const_iterator begin() const; 这在反向迭代器中其实也是有的,在C++标准库中既有一般的迭代器,也有const迭代器,const迭代器就是适合const对象使用的;对const迭代器指向的内容进行修改是会出现错误的。
6.push_back append operator+=
void push_back (char c); push_back只能一个字符一个字符的尾插,空间不够会自动扩容。
string& append (const char* s); append可以尾插一个字符串。
void test_string6()
{
string s("hello");
s.push_back('-');
s.push_back('-');
s.append("world");
cout << s << endl;
}
相比于上面两个接口,operator+=用起来会更好用,string& operator+= (const char* s);
string& operator+= (char c);可以直接+=一个字符或者一个字符串,用起来比较简单。
void test_string6()
{
string s("hello");
s += ' ';
s += "world";
cout << s << endl;
}
operator+=的底层就是调用push_back和append。
append还有一种追加方式是使用迭代器区间:template string& append (InputIterator first, InputIterator last);
string s1("我来啦");
s.append(s1.begin(), s1.end());
cout << s << endl;
在追加的时候不一定只是追加一个string对象,也可以只追加一部分,这时候需要对迭代器区间进行修改。
7.insert erase
insert和erase在string中并不常用,因为效率很低,但是不排除一些特殊场景需要用到:
string s("wo lai le");
把所有的空格替换成20%:
void test_string7()
{
string s("wo lai le");
//string& insert (size_t pos, const char* s);
for (size_t i = 0; i < s.size(); i++)
{
if (s[i] == ' ')
{
s.insert(i, "20%");
i += 3;
}
}
//string& erase (size_t pos = 0, size_t len = npos);
for (size_t i = 0; i < s.size(); i++)
{
if (s[i] == ' ')
{
s.erase(i, 1);
}
}
cout << s << endl;
}
还没有评论,来说两句吧...