目录
一.string的大小和容量成员函数
1.1size()和length()
1.2capacity()
1.3resize()
1.4reserve()
1.5clear()和empty()
编辑 二.string元素的访问
2.1operator[]和at()
2.2范围for
三.string中迭代器相关函数
3.1begin()和end()
3.2rbegin()和rend()
四.string与字符串之间的转换
五.string中子串的提取
5.1substr()
5.2通过copy()提取子串。
六.string中的运算符重载
6.1operator+操作符
6.2输入输出操作符
七.string中getline函数
八.后记
一.string的大小和容量成员函数
1.1size()和length()
在C语言中,我们可以通过下式来计算字符数组中有多少个元素
sizeof(arr[0]) / sizeof(arr);
在string库中,有如下两个接口可以计算元素个数:
size();
length();
如下图所示:
虽然这两个函数都可以完成对元素个数的计算,但我们更推荐使用size()函数计算元素的个数。
这是因为在STL中,都重载了size()这个函数,却没有重载length()函数。
1.2capacity()
capacity()函数用来获取字符串开的空间。
size_t capacity() const;
在这里需要大家注意的是,capacity表示开辟的空间大小,而size求出的是开辟的空间内的元素个数。因此这两个数是可以不相等的。
如下图:
我们发现,我们开了15个空间存储这个字符串,但是只用了其中的七个空间。
1.3resize()
resize是改变当前字符串有效字符个数的函数。
void resize (size_t n);
void resize (size_t n, char c);
resize规则:
- 当n大于对象当前的size时,将size扩大到n,扩大的字符为c,若c未给出,则默认为’\0’。
- 当n小于对象当前的size时,将size缩小到n。
我们可以通过下图的代码来验证上述规则:
另外,值得一提的是,如果resize给出的值大于capacity的值的话,会调用扩容函数。
1.4reserve()
reserve()是操作设置capacity的函数。函数原型如下:
void reserve (size_t n = 0);
reserve规则:
- 当n大于对象当前的capacity时,将capacity扩大到n或大于n。
- 当n小于对象当前的capacity时,将capacity缩小或什么也不做。
我们可以通过下图来验证上图的规则:
这里需要我们大家注意两点内容
- reserer()函数并不会影响到字符串内的字符数据。
- reserve()在一些编译器中也可能会缩容。
1.5clear()和empty()
clear()函数用来清空字符串内的字符数据。
void clear();
clear规则:
- 字符数据清除掉,使其成为空字符串
- size设置为0
实例如下:
empty函数进行判空,即判断字符串是否为空字符串。
bool empty() const;
如果字符串为空的话,则返回真。
如果字符串不为空的话,则返回假。
二.string元素的访问
2.1operator[]和at()
string元素的访问有两种方式,我们可以通过重载的[]访问,也可以通过at函数访问。
char& operator[] (size_t pos);
const char& operator[] (size_t pos) const;
char& at (size_t pos);
const char& at (size_t pos) const;
由于两者都是传引用返回,因此两者都可以修改数据。
我们先使用operator[]来进行实践:
现在我们通过at来进行实践:
2.2范围for
同样的,我们也可以通过范围for来访问和修改字符串内的数据。
我们可以使用下图中的方式来访问数据:
但是,在使用范围for修改数据时,则需要我们传引用了,否则e只是对象元素的拷贝,对e的修改不会影响到对象的元素。
因此,使用范围for修改数据的正确方法如下:
for (auto& e : str)
{
e = 'x';
}
三.string中迭代器相关函数
3.1begin()和end()
begin函数:返回一个指向字符串第一个字符的迭代器。
end函数:返回一个指向字符串结束字符的迭代器,即’\0’。
函数原型如下:
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
我们同样可以通过迭代器来访问和修改数据,如下所示:
string str("xiaoqiulaoshi");
string::iterator it1 = str.begin();
while (it1 != str.end())
{
cout << *it1 << ' ';
it1++;
}
cout << endl;//x i a o q i u l a o s h i
string::iterator it2 = str.begin();
while (it2 != str.end())
{
*it2='x';
it2++;
}
cout << str << endl;//xxxxxxxxxx
3.2rbegin()和rend()
在string库中,还提供了反向迭代器rbegin和rend。
rbegin函数:返回指向字符串最后一个字符的反向迭代器。
rend函数:返回指向字符串第一个字符前面的理论元素的反向迭代器。
函数原型如下:
iterator rbegin();
const_iterator rbegin() const;
iterator rend();
const_iterator rend() const;
为了方便大家理解,我们来画图表示rbegin和rend的指向。
四.string与字符串之间的转换
在学习过数据结构之后,我们知道实现一个string类,私有成员需要有char* 、size、capacity。
如果我们只需要char*的话,则可以通过c_str()函数来进行转换。
我们将c_str()转换过来的字符串称为C字符串/C风格字符串。也就是我们上文中说的字符序列。
函数原型如下:
const char* c_str() const;
使用方法如下:
const char* str2 = s.c_str();
五.string中子串的提取
我们有两种方法提取子串,分别是通过substr提取以及通过copy出一个字符串的部分字符到另外一个字符串中。
5.1substr()
函数原型如下:
string substr (size_t pos = 0, size_t len = npos) const;
我们可以通过下面的代码提取子串:
int main()
{
string s1("abcdef");
string s2;
//substr(pos, n)提取pos位置开始的n个字符序列作为返回值
s2 = s1.substr(2, 4);
cout << s2 << endl; //cdef
return 0;
}
5.2通过copy()提取子串。
函数原型如下:
size_t copy (char* s, size_t len, size_t pos = 0) const;
我们可以通过如下方法来提取子串:
int main()
{
string s("abcdef");
char str[20];
//copy(str, n, pos)复制pos位置开始的n个字符到str字符串
size_t length = s.copy(str, 4, 2);
//copy函数不会在复制内容的末尾附加'\0',需要手动加
str[length] = '\0';
cout << str << endl; //dcef
return 0;
}
六.string中的运算符重载
我们在前面的内容中已经介绍了很多操作符,现在我们再介绍几个操作符。
6.1operator+操作符
operator+操作符和operator+=操作符的作用是类似的。
重载后的+操作符支持如下操作:
string类 + string类
string类 + 字符串
字符串 + string类
string类 + 字符
字符 + string类
譬如如下代码:
int main() {
// 定义字符串和字符
string str1 = "Hello";
string str2 = "World";
const char* cstr = " C++";
char ch = '!';
// 1. string类 + string类
string result1 = str1 + str2;
cout << "string + string: " << result1 << endl; // 输出 "HelloWorld"
// 2. string类 + 字符串 (C风格字符串)
string result2 = str1 + cstr;
cout << "string + C-style string: " << result2 << endl; // 输出 "Hello C++"
// 3. 字符串 + string类
string result3 = cstr + str2; // C风格字符串 + string类
cout << "C-style string + string: " << result3 << endl; // 输出 " C++World"
// 4. string类 + 字符
string result4 = str1 + ch;
cout << "string + char: " << result4 << endl; // 输出 "Hello!"
// 5. 字符 + string类
string result5 = ch + str1; // char + string类
cout << "char + string: " << result5 << endl; // 输出 "!Hello"
return 0;
}
6.2输入输出操作符
我们的string中也重载了输入输出操作符。
void test15()
{
string s;
cin >> s;//输入
cout << s<< endl;//输出
}
我们可以通过这个操作来输入和输出函数。
但是,我们发现了一个问题,如果我们输入的字符串中有空格的话 则空格后的字符会进入缓冲区。
因此,我们便可以用到getline函数。
七.string中getline函数
在用>>进行输入操作时,当>>读取到空格便会停止读取,基于此,我们将不能用>>将一串含有空格的字符串读入到string对象中。
这时,我们就需要用getline函数完成一串含有空格的字符串的读取操作了。
getline()函数的原型如下:
istream& getline (istream& is, string& str);
getline函数将从is中提取到的字符存储到str中,直到读取到换行符’\n’为止。
int main()
{
string s;
getline(cin, s); //输入:hello k
cout << s << endl; //输出:hello k
return 0;
}
同样的,getline也可以自定义分隔符delim终止。
这个版本的getline原型如下:
istream& getline (istream& is, string& str, char delim);
这个函数将从is中提取到的字符存储到str中,直到读取到分隔符delim或换行符’\n’为止。
int main()
{
string s;
getline(cin, s, 'D'); //输入:hello CSDN
cout << s << endl; //输出:hello CS
return 0;
}
八.后记
string类的接口上是这篇博文:string接口上
有关string类的模拟实现可参考此片博文:string的模拟实现
如果你想更深入的了解string类函数的使用方法,可参考cpp官网:cpp官网
码字不易,给个点赞收藏叭~~~