1.为什么要学习string类
- c语言的字符串是以’\0’结尾的一些字符的集合,比如存储你的家庭住址,修改成为新的住址,原来的住址短,现在的住址长,之前的字符串数组存不下,不能很好按需修改
- c++提供一个类来管理字符串,这个类就叫string
2.标准库中的string类
1.string分类
- string 是一个类模板,原型是一个 basic_string的类模板由typedef成为string
- char(重点使用)
- char:1个字节 ,即一个字符1个字节
- 宽字符存在(使用相对偏少)
- wchar_t :2个字节 ,即一个字符2个字节
- C++11提供u16string和u32string(了解)
- char16_t:2个字节 即一个字符2个字节
- char32_t: 4个字节 即一个字符4个字节
上述多种string形式说明有管理不同字符数组的需求
ASCII是美国标准信息交换代码,用来在计算机里面存储和显示英文信息,通过26个字母、数字、标点符号,来建立关系形成映射表从而生成了编码表,调用对应的ASCII值来生成对应的符号,ASCII表只有128个字符,一个字节8个bit位就够了
为了支持显示除了英文以外的文字显示,就发明出了unicode (万国码),为每种语言的每个字符设定了统一并且唯一的二进制编码
- 使用2个字节进行统一编码
- 使用4个字节进行统一编码
- UTF-16对应u16string ,UTF-32对应 u32string
2.string类对象的常见构造
- 必须包含头文件< string >
1.string
- string()——构造空的string类对象,即空字符串
- string(const char*s) ——用常量字符串构造string字符串
#include<iostream> #include<string> using namespace std; int main() { string s1; string s2("hello"); //遍历数组并使每个字符+1 for (size_t i = 0; i < s2.size();i++) { s2[i]++; } cout << s2 << endl;// 通过重载流提取(<<),string可以直接进行打印 //ifmmp return 0; }
string(const string&str,size_t pos,size_t len=npos);—— 拷贝str从pos开始的len个字符
如果len长度大于pos位置后的字符个数,则有多少取多少
若len没有给值,则会自动默认缺省值npos
- size_t npos=-1,由于是无符号整形,实际上是-1的补码即整形最大值
#include<iostream> #include<string> using namespace std; int main() { string s1("hello world"); string s2(s1, 6, 5);//拷贝s1从第6个位置开始取5个字符 string s3(s1, 6, 15);//由于pos为指向后取只有5个字符,小于15,有多少取多少 string s4(s1, 6);//len缺省值为整形最大值,则一直从pos位置取到结尾 cout<<s2<<endl; cout<<s3<<endl; cout<<s4<<endl; }
string(size_t n,char c); ——填string类对象前n个字符
int main() { string s(10, '.');// 前10个字符为 . cout << s << endl;//.......... return 0; }
3. string类对象的容量操作
1.size
#include<iostream> #include<string> using namespace std; int main() { string s("hello world"); cout << s.size() << endl;//11 cout << s.length() << endl;//11 return 0; }
- size和length两者功能相同,由于string发展历史造成的,最开始字符串的长度为length,后来为了和数据结构其他保持一致使用size更符合,所以推荐使用size
2.capacity
#include<iostream> #include<string> using namespace std; int main() { string s("hello world"); cout << s.size() << endl;//11 cout << s.capacity() << endl;//15 return 0; }
- 有11个字符,但是空间大小为15(不包含/0)
3.reserve
#include<iostream> #include<string> using namespace std; //扩容问题 int main() { string s; //s.reserve(100);//提前开辟100个空间 size_t sz = s.capacity();//sz代表原来的容量 cout << "making a grow" << endl; for (int i = 0; i < 100; i++) { s.push_back('c');//不断在字符串后插入字符c if (sz != s.capacity())//扩容后,将sz值更新 { sz = s.capacity(); cout << "capacity changed:" << sz << endl; } } }
- 提前开辟空间,减少扩容,提高效率
#include<iostream> #include<string> using namespace std; int main() { string s("hello"); s.reserve(100); cout << s.size() << endl;//5 cout << s.capacity() << endl;//111 return 0; }
- reserve只会改变capacity,不会改变size
- size值没有改变依旧为5,capacity被提前开辟100个空间
4.resize
扩容+初始化
#include<iostream> #include<string> using namespace std; int main() { string s("hello"); s.resize(100); cout << s.size() << endl;//100 cout << s.capacity() << endl;//111 return 0; }
- reserve既改变capacity,也会改变size
- size值被改变为100,被修改的部分填的是缺省值’\0’,
capacity值也被改变为111
#include<iostream> #include<string> using namespace std; int main() { string s("hello"); s.resize(10,'x');//将size修改的值填成x return 0; }
- 可以手动添加字符填成自己想给的值
删除数据
#include<iostream> #include<string> using namespace std; int main() { string s("hello"); s.resize(2);//2<5,所以只保留前2个字符 cout << s << endl;//he cout << s.capacity() << endl;//15 return 0; }
- 若resize值小于size值,可以删除数据,但不会改变容量
4. string类对象的修改操作
1.push_back
- 在字符串后插入字符
#include<iostream> #include<string> using namespace std; int main() { string s("hello"); s.push_back(' '); s.push_back('!'); cout << s << endl;//hello ! return 0; }
2.append
- 在字符串后插入字符串
#include<iostream> #include<string> using namespace std; int main() { string s("hello"); s.append(" world!"); cout << s << endl;//hello world! return 0; }
3.operator+=
- 字符串后插入字符/字符串/对象
#include<iostream> #include<string> using namespace std; int main() { string s("hello"); s += ' ';//字符 s+='!'; s += "world";//字符串 string s2("abc"); s += s2;//对象 cout << s << endl;//hello !worldabc return 0; }
相比于push_back 插入字符和append插入字符串,operator+=方式更容易使用