为什么学习string类?
C语言中的字符串
标准库中的string类
string类(了解)
小知识:string类是在STL之前设计出来的,设计的接口有些冗余。
string类的常用接口说明
1.string类对象的常见构造和赋值
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s0;
string s1("hello world");
string s2(s1);
string s3(s1, 5, 3);
string s4(s1, 5, 10);
string s5(s1, 5);
string s6(10, '#');
cout << s0 << endl;
cout << s1 << endl;
cout << s2 << endl;
cout << s3 << endl;
cout << s4 << endl;
cout << s5 << endl;
cout << s6 << endl;
s0 = s6;
cout << s0 << endl;
return 0;
}
2. string类对象的容量操作
string::size - C++ 参考 (cplusplus.com) 返回字符串有效字符长度
string::length - C++ 参考 (cplusplus.com) 返回字符串有效字符长度(主要针对string类)
string::max_size - C++参考 (cplusplus.com) 返回字符串的最大大小
string::capacity - C++ 参考 (cplusplus.com) 返回空间总大小 。不同系统的扩容机制不同(vs下1.5倍扩容,g++下2倍扩容)
string::clear - C++ 参考 (cplusplus.com) 清空有效字符,但不改变空间,即空间总大小不变
string::empty - C++ 参考 (cplusplus.com) 测试字符串是否为空
void test_string4()
{
string s1("hello world");
cout << s1.size() << endl;
cout << s1.length() << endl;
cout << s1.max_size() << endl;
cout << s1.capacity() << endl;
// 查看扩容机制
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';
}
}
cout << s1 << endl;
cout << s1.capacity() << endl;
cout << s1.size() << endl;
s1.clear();
cout << s1 << endl;
cout << s1.capacity() << endl;
cout << s1.size() << endl;
}
int main()
{
test_string4();
return 0;
}
string::shrink_to_fit - C++参考 (cplusplus.com) 缩容。C++ 标准库的规定,对于 shrink_to_fit
方法,并不保证一定会收缩容量,具体是否收缩取决于标准库的实现。
void test_string4()
{
string s1("hello worldxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
cout << s1.capacity() << endl;
cout << s1.size() << endl;
s1.clear();
cout << s1 << endl;
cout << s1.capacity() << endl;
cout << s1.size() << endl;
// 缩容
s1.shrink_to_fit();
cout << s1.capacity() << endl;
cout << s1.size() << endl;
}
int main()
{
test_string4();
return 0;
}
string::reserve - C++ 参考 (cplusplus.com) 为字符串预留空间,生成的字符串容量可能等于或大于n (不同平台下实现机制不一样)
void test_string5()
{
string s1("hello worldxxxxxx");
cout << s1.size() << endl;
cout << s1.capacity() << endl<<endl;
// 比当前capacity大才会扩容
s1.reserve(200);
cout << s1.size() << endl;
cout << s1.capacity() << endl;
}
int main()
{
test_string5();
return 0;
}
string::resize - C++ 参考 (cplusplus.com) 调整字符串大小
void test_string5()
{
string s2("hello worldxxxxxx");
cout << s2.size() << endl;
cout << s2.capacity() << endl << endl;
s2.resize(10);
cout << s2.size() << endl;
cout << s2.capacity() << endl << endl;
s2.resize(20);
cout << s2.size() << endl;
cout << s2.capacity() << endl << endl;
s2.resize(100, 'x');
cout << s2.size() << endl;
cout << s2.capacity() << endl << endl;
}
int main()
{
test_string5();
return 0;
}
string::at - C++ 参考 (cplusplus.com)
void test_string6()
{
string s1("xhello world");
cout << s1[5] << endl;
cout << s1.at(5) << endl;
//对于越界访问的检查不同
s1[15];
s1.at(15);
}
int main()
{
test_string6();
return 0;
}
3.string类对象的访问及遍历操作
operator[](访问使用连续的内存空间来存储元素,如数组,顺序表)
// a[i] 等价于 *(a+i)
void test_string2()
{
string s1("hello world");
// 下标+[]
for (size_t i = 0; i < s1.size(); i++)
{
cout << s1[i] << " ";
//cout << s1.operator[](i) << " ";
}
cout << endl;
for (size_t i = 0; i < s1.size(); i++)
{
s1[i]++;
}
cout << endl;
string s3("hello world");//可读可写
s3[0]++;
cout << s3 << endl;
const string s2("hello world");//只读
//s2[0]++;
cout << s2 << endl;
}
int main()
{
test_string2();
return 0;
}
迭代器行为像指针一样的类型对象
(迭代器是访问的主流选择,通用)
void test_string2()
{
string s3("hello world");
string::iterator it3 = s3.begin();
while (it3 != s3.end())
{
*it3 -= 3;
++it3;
}
cout << endl;
it3 = s3.begin();
while (it3 != s3.end())
{
cout << *it3 << " ";
++it3;
}
cout << endl;
}
int main()
{
test_string2();
return 0;
}
范围for
void test_string2()
{
string s3("hello world");
// 底层就是迭代器
for (auto e : s3)
{
cout << e << " ";
}
cout << endl;
}
int main()
{
test_string2();
return 0;
}
反向迭代器
void test_string3()
{
string s1("hello world");
string::reverse_iterator rit = s1.rbegin();
while (rit != s1.rend())
{
cout << *rit << " ";
++rit;
}
cout << endl;
// 可读可写
string::reverse_iterator it2 = s1.rbegin();
while (it2 != s1.rend())
{
*it2 += 3;
cout << *it2 << " ";
++it2;
}
cout << endl;
// 只读
const string s3("hello world");
string::const_reverse_iterator it3 = s3.rbegin();
while (it3 != s3.rend())
{
// *it3 += 3;
cout << *it3 << " ";
++it3;
}
cout << endl;
}
int main()
{
test_string3();
return 0;
}
4. string类对象的修改操作
push_back 在字符串后尾插字符c
string::append - C++ 参考 (cplusplus.com) 在字符串后追加一个字符串
string::operator+= - C++ 参考 (cplusplus.com) 在字符串后追加字符串str(常用)
void test_string7()
{
string s1("xhello world");
s1.push_back('!');
cout << s1 << endl;
s1.append("hello bit");
cout << s1 << endl;
s1.append(10, 'x');
cout << s1 << endl;
string s2(" apple ");
//s1.append(s2);
//cout << s1 << endl;
s1.append(++s2.begin(), --s2.end());
cout << s1 << endl;
string s3("hello world");
s3 += ' ';
s3 += "apple";
cout << s3 << endl;
}
string::assign - C++ 参考 (cplusplus.com) 为字符串分配一个新值,替换其当前内容。
string::insert - C++ 参考 (cplusplus.com) 在字符串中插入其他字符, pos(或 p)指示的字符位置之前。
string::erase - C++ 参考 (cplusplus.com) 从字符串中删除字符
string::replace - C++ 参考 (cplusplus.com) 替换字符串部分
void test_string8()
{
string s1("xhello world");
cout << s1 << endl;
s1.assign(" xxxxx");
cout << s1 << endl;
s1.insert(0, "yyyy");
cout << s1 << endl;
s1.erase(5, 3);
cout << s1 << endl;
s1.erase();
cout << s1 << endl;
string s2("hello world hello bit");
//s2.replace(5, 1, "20%");
//cout << s2 << endl;
size_t pos = s2.find(' ');
while (pos != string::npos)
{
s2.replace(pos, 1, "20%");
pos = s2.find(' ');
}
cout << s2 << endl;
}
int main()
{
test_string8();
return 0;
}
// insert/erase/replace
// 能少用就要少用,因为基本都要挪动数据,效率不高
void test_string9()
{
string s1("hello world");
string filename("test.cpp");
FILE* fout = fopen(filename.c_str(), "r");
}
string::find - C++ 参考 (cplusplus.com) 从字符串pos位置开始往后找字符c或字符串,返回该字符在字符串中的位置
string::rfind - C++ 参考 (cplusplus.com) 从字符串pos位置开始往前找字符c或字符串,返回该字符在字符串中的位置
string::substr - C++ 参考 (cplusplus.com) 在str中从pos位置开始,截取n个字符,然后将其返回
string::npos - C++ 参考 (cplusplus.com) size_t的最大值
string::find_first_of - C++参考 (cplusplus.com) 在字符串中搜索与其参数中指定的任何字符匹配的第一个字符。
string::find_last_of - C++参考 (cplusplus.com) 在字符串中搜索与其参数中指定的任何字符匹配的最后一个字符。
//[0, 9]
//[0, 10) 左闭右开,右-左是个数
void test_string10()
{
//string s1("file.cpp");
string s1("file.c.tar.zip");
// 拿到文件的后缀
size_t pos1 = s1.rfind('.');
if (pos1 != string::npos)
{
string suffix = s1.substr(pos1);
//string suffix = s1.substr(pos1, s1.size()-pos1);
cout << suffix << endl;
}
else
{
cout << "没有后缀" << endl;
}
string url1("https://legacy.cplusplus.com/reference/string/string/substr/");
string protocol, domain, uri;
size_t i1 = url1.find(':');
if (i1 != string::npos)
{
protocol = url1.substr(0, i1 - 0);
cout << protocol << endl;
}
// strchar
size_t i2 = url1.find('/', i1 + 3);
if (i2 != string::npos)
{
domain = url1.substr(i1 + 3, i2 - (i1 + 3));
cout << domain << endl;
uri = url1.substr(i2 + 1);
cout << uri << endl;
}
cout << endl;
std::string str("Please, replace the vowels in this sentence by asterisks.");
cout << str << endl;
// strtok
std::size_t found = str.find_first_of("aeiou");
while (found != std::string::npos)
{
str[found] = '*';
found = str.find_first_of("aeiou", found + 1);
}
cout << str << endl;
}
int main()
{
test_string10();
return 0;
}
5. string类非成员函数
operator+ (string) - C++ 参考 (cplusplus.com) 尽量少用,因为传值返回,导致深拷贝效率低
关系运算符(字符串) - C++ 参考 (cplusplus.com) 大小比较
operator>> (string) - C++参考 (cplusplus.com) 输入运算符重载
operator<< (string) - C++参考 (cplusplus.com) 输出运算符重载
getline (string) - C++ 参考 (cplusplus.com) 获取一行字符串,遇到 ' \n' 结束;也可以自定义结束符。
void test_string10()
{
string ss1 = "xxx";
string ss2 = "yyy";
string ret = ss1 + ss2;
cout << ret << endl;
cout << (ss1 < ss2) << endl;
string ret1 = ss1 + "yyyy";
string ret2 = "yyyy" + ss2;
}
int main()
{
test_string10();
return 0;
}
字符串转换
to_string - C++ Reference (cplusplus.com) 将数值转换为字符串
stoi - C++ 参考 (cplusplus.com) 将字符串转换为整数
stod - C++ 参考 (cplusplus.com) 将字符串转换为双精度
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
using namespace std;
int main()
{
int i = 1234;
double d = 11.22;
string s1 = to_string(i);
string s2 = to_string(d);
string s3("45.55");
double d3 = stod(s3);
cout << d3;
return 0;
}
浅拷贝
深拷贝
写时拷贝(了解)
vs和g++下string结构的说明 (了解即可)
union _Bxty
{ // storage for small buffer or pointer to larger one
value_type _Buf[_BUF_SIZE];
pointer _Ptr;
char _Alias[_BUF_SIZE]; // to permit aliasing
} _Bx;
struct _Rep_base
{
size_type _M_length;
size_type _M_capacity;
_Atomic_word _M_refcount;
};