一.为什么学习string类
(1) C语言中的字符串
C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。
在OJ中,有关字符串的题目基本以string类的形式出现,而且在常规工作中,为了简单、方便、快捷,基本都使用string类,很少有人去使用C库中的字符串操作函数。
(2)标准库里面的string类
string类文档
1.字符串是表示字符序列的类
2.标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作单字节字符字符串的设计特性。
3.string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型(关于模板的更多信息,请参阅basic_string)。
4.string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits和allocator作为basic_string的默认参数(根于更多的模板信息请参考basic_string)。
5.注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。
总结:
1. string是表示字符串的字符串类
2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
3. string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator>string;
4. 不能操作多字节或者变长字符的序列
在使用string类时,必须包含#include头文件以及using namespace std;
二. string类的常用接口说明
(1)string类对象的常见构造
#include<iostream> #include<string> using namespace std; int main() { //创建空字符串 string str1; cout << str1 << endl; //使用字符串构造对象 string str2("hello world"); cout << str2 << endl; //使用n个字符构造对象 string str3(15, '*'); cout << str3 << endl; //拷贝构造函数 string str4(str2); cout << str4 << endl; return 0; }
(2)string类对象的容量操作
课件代码/C++课件V6/string的接口测试及使用/TestString.cpp · will/C++上课 - Gitee.com
1.size(),length().
size()和lenth都是返回字符串有效长度的。
注意:我们一般表示字符串的长度时使用length,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size()。
int main() { string str("hello world"); cout << str.size() << endl; cout << str.length() << endl; return 0; }
2. capacity()
capacity()是返回字符串对象的总空间大小的,因为string自己本身是可以扩容的。
int main() { string str("hello world"); cout << str.size() << endl; cout << str.length() << endl; cout << str.capacity() << endl; return 0; }
3.empty()
检测字符串释放为空串,是返回true,否则返回false。
int main() { string str("hello world"); string str1; cout << str.empty() << endl; cout << str1.empty() << endl; return 0; }
4.clear()
清楚有效字符。
注意:clear()只是将string中有效字符清空,不改变底层空间大小。
int main() { string str("hello world hello world hello "); cout << "clear前:" << str <<" 容量:" << str.capacity() << endl; str.clear(); cout << "clear前:" << str << "容量:" << str.capacity() << endl; return 0; }
5.reserve()
为字符串预留空间,我们直到在一些情况下如果我们提前知道了字符串的大小,就可以提前为字符串开好空间,避免后面的扩容带来的效率上的消耗。
注意:实际上的申请后的空间会比我们申请的空间大一些,这也是一种保护机制。但是我们如果我们预留的空间比原本的空间还要小时,此时函数会进行优化,个根据我们存储的串的长度经行合适的改表。
6.resize()
resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。如果 n 小于字符串长度,就删去字符串保留前 n 个。
int main() { string str("abcde"); cout << str << endl; //扩容+初始化 str.resize(str.size() + 5, '#'); cout << str << endl; //减小长度 str.resize(4); cout << str << endl; return 0; }
(3)string类对象的访问及遍历操作
1.operator[ pos ] ,at(size_t pos)
operator [ ] 都是返回pos位置的字符,const string类对象调用。operater[ ]是对[ ]的运算符重载,就像数组一样的访问。
注意:两者的区别在,处理越界方面,operator[ ]使用断言处理,而 at(pos) 是抛出一个异常。
int main() { string str("hello"); for (int i = 0; i < str.size(); i++) { cout << str[i] << " "; } cout << endl; for (int i = 0; i < str.size(); i++) { cout << str.at(i) << " "; } return 0; }
2.back(),front()
back():返回最后一字符,front():返回第一个字符。