string的增删
void string10()
{
string s1 = "hello world";
cout << s1 << endl;
s1.insert(0,"xxxxxx");
cout << s1 << endl;
}
这里insert最基本的用法就是第一个参数的位置处插入第二个参数的字符串内容 insert可以进行头插 但是一般不这样 挪动数据会造成效率降低
想要插入或者头插一个字符用上述的两个参数是行不通的 需要三个参数 第一个依旧是位置下标 第二个是要插入字符的数量 第三个是要插入的字符
void string10()
{
string s1 = "hello world";
cout << s1 << endl;
s1.insert(0,"xxxxxx");
cout << s1 << endl;
s1.insert(0,2,'c');
cout << s1 << endl;
}
除了用三个参数来插入字符之外 还有一种版本 第一个参数放入的是要插入的位置 不过不是用下标而是使用迭代器中的begin()成员函数来代替下标表示位置 第二个参数则放入将要插入的字符内容
void string10()
{
string s1 = "hello world";
cout << s1 << endl;
//s1.insert(0,"xxxxxx");
//cout << s1 << endl;
s1.insert(0,2,'c');
cout << s1 << endl;
s1.insert(s1.begin(),'r');
cout << s1 << endl;
}
还有一种三个参数都是迭代器版本
第一个参数的代表要插入的位置 第二个参数和第三个参数则表示要插入字符串内容的起点和终点
void string10()
{
string s1 = "hello world";
cout << s1 << endl;
//s1.insert(0,"xxxxxx");
//cout << s1 << endl;
/*s1.insert(0,2,'c');
cout << s1 << endl;
s1.insert(s1.begin(),'r');
cout << s1 << endl;*/
string s2;
s2.insert(s2.begin(),s1.begin(),s1.end()-1);
cout << s2 << endl;
}
assign本身相当于变相的赋值
void string11()
{
string s1("hello world");
cout << s1 << endl;
s1.assign("2222222");
cout << s1 << endl;
}
erase的作用是删除
第一个位置是下标 表示从这个位置开始删除 第二个参数是长度表示要从这个位置开始删除多少长度的内容 如果不写第二个参数 或者第二个参数已经大过了这个字符串数组有效内容的总长度那么就会从当前位置开始有多少删多少
erase可以实现头删
void string12()
{
string s1("hello world");
cout << s1 << endl;
s1.erase(0,1);
cout << s1 << endl;
}
当不写第二个参数或者第二个参数过大时
void string12()
{
string s1("hello world");
cout << s1 << endl;
s1.erase(5);
cout << s1 << endl;
//s1.erase(0,1);
//cout << s1 << endl;
}
void string12()
{
string s1("hello world");
cout << s1 << endl;
s1.erase(5,200);
cout << s1 << endl;
//s1.erase(0,1);
//cout << s1 << endl;
}
insert和erase 的第一个参数都是传下标位置 他们都不能传非法的下标位置 这样会进行报错
replace有三个参数 第一个参数是提供下标位置 第二个参数是要从当前位置之后开始替换的长度 第三个是要替换的内容
void string13()
{
string s1("hello world");
cout << s1 << endl;
s1.replace(5,1,"%20");
cout << s1 << endl;
}
使用replace还可以将所有的空格字符进行替换
void string13()
{
/*string s1("hello world");
cout << s1 << endl;
s1.replace(5,1,"%20");
cout << s1 << endl;*/
string s2("hello world helloc bit");
cout << s2 << endl;
for (int i = 0 ; i< s2.size();)
{
if (s2[i]==' ')
{
s2.replace(i,1,"%20");
i += 3;
}
else
{
i++;
}
}
cout << s2 << endl;
}
这种执行效率是很低的 应为要替换的内容长度和被替换的长度不匹配 需要进行挪动
void string14()
{
string s3;
string s2("hello world helloc bit");
cout << s2 << endl;
for (auto e:s2)
{
if (e != ' ')
{
s3 += e;
}
else
{
s3 += "%20";
}
}
cout << s3 << endl;
}
这种写法既可以完成替换 还可以提高效率 不需要挪动
string中的size capacity max_size 三种成员函数
void string15()
{
string s2("hello world helloc bit");
cout << s2.size() << endl;
cout << s2.capacity() << endl;
cout << s2.max_size() << endl;
}
clear会将string中的所有内容全部清除
empty会判断string是否为空
string的扩容规律(vs版本下)
第一次是二倍(与存在_buf数组有关) 之后是1.5倍
这其中capacity比实际空间少一个 用与存储斜杠零
如何扩容 c++标准没有明确的规定 取决于编译器实现
string中的resize和reserve()
其中resize是请求一个size的改变 reserve是请求一个capacity的改变
void string16()
{
string s1("11111111");
string s2("11111111111111111111111111");
cout << s1.capacity() << endl;
s1.reserve(100);
cout << s1.capacity() << endl;
}
这里我们可以看到reserve可以进行扩容 但是不会正确的扩容 扩容100 却扩容到111 (这里和编译器不同有关)
在vs编译器下 reserve不会进行缩容
void string16()
{
string s1("1111111111");
string s2("11111111111111111111111111");
cout << s1.capacity() << endl;
s1.reserve(100);
cout << s1.capacity() << endl;
s1.reserve(20);
cout << s1.capacity() << endl;
}
但不是所有的编译器都会缩容 与编译器有关
如果缩容的值大于15 那么不会缩容 如果小于15 那么则会缩容(在vs编译器下)
void string16()
{
string s1("1111111111");
string s2("11111111111111111111111111");
cout << s1.capacity() << endl;
s1.reserve(100);
cout << s1.capacity() << endl;
s1.reserve(10);
cout << s1.capacity() << endl;
}
如果知道需要的空间有多大 可以使用reserve提前开好 这样就不会存在扩容
void string17()
{
string s1;
s1.resize(5,'0');
s1[4] = '7';
s1[3] = '6';
s1[2] = '5';
s1[1] = '4';
s1[0] = '3';
cout << s1 << endl;
}
两个版本一个参数的版本是只可以修改size 且会填入默认字符 也就是斜杠零
而两个参数的版本不仅可以修改size还可以对内容进行统一的初始化
void string17()
{
/*string s1;
s1.resize(5,'0');
s1[4] = '7';
s1[3] = '6';
s1[2] = '5';
s1[1] = '4';
s1[0] = '3';
cout << s1 << endl;*/
string s2("hello world");
s2.resize(20,'6');
cout << s2 << endl;
s2.resize(5);
cout << s2 << endl;
}
resize在如果原有的内容上进行扩容 不会修改原有的内容 而会将扩大的空白内容中填充
resize如果在原有的内容上进行缩容 会删除多余的内容 保留下来的内容不会就行改变
string中使用shrink_to_fit来进行缩容
缩容的原理 是开一片更小的空间 然后将内容拷贝到新空间上 之后在释放旧的空间
at是访问pos位置的字符 他与[]的功能是一样的
区别是[]是暴力检查 at是通过抛异常解决
void string17()
{
/*string s1;
s1.resize(5,'0');
s1[4] = '7';
s1[3] = '6';
s1[2] = '5';
s1[1] = '4';
s1[0] = '3';
cout << s1 << endl;*/
string s2("hello world");
s2.resize(5);
try
{
s2.at(10);
}
catch (const exception&e)
{
cout << e.what() << endl;
}
}
c_str是用来获取底层指向字符串的那个指针
void string19()
{
string s1("string.cpp.zip");
size_t pos = s1.find('.');
string s2;
s2 = s1.substr(pos,2);
cout << s2 << endl;
}
void string19()
{
string s1("string.cpp.zip");
size_t pos = s1.find('.');
string s2;
s2 = s1.substr(pos);
cout << s2 << endl;
}
void string20()
{
string s1("https://gitee.com/bitpg/class112--c-training-camp-2");
size_t pos1 = s1.find(':');
string s2 = s1.substr(0,pos1-0);
cout << s2 << endl;
size_t pos2 = s1.find('/',pos1+3);
string s3 = s1.substr(pos1+3,pos2-(pos1+3));
cout << s3 << endl;
string s4 = s1.substr(pos2+1);
cout << s4 << endl;
}
find_first_of()是按正序寻找与参数字符串中第一个相同字符的位置并返回
find_last_of() 是按倒序寻找与参数字符串中第一个相同字符的位置并返回
find_first_not_of()是按正序寻找与参数字符串中第一个不相同字符的位置并返回
find_last_not_of() 是按倒序寻找与参数字符串中第一个不相同字符的位置并返回
void string21()
{
string str("5641635146541531513");
size_t found = str.find_first_of("567");
while (found != std::string::npos)
{
str[found] = '*';
found = str.find_first_of("567",found+1);
}
cout << str << endl;
}
重载+不可以char与char相加 因为char是内置类型 重载必须要有一个自定义类型
字符串是按照首个字符的ascll码比较大小的 字典序比较
若第一个相同在比较第二个的大小
<< 和<存在优先级问题
void string22()
{
string s1 = ("546548749");
string s2 = ("54657777");
cout << (s1 <s2) << endl;
}
scanf和cin流提取都有一个特点 那就是遇到空格或者换行符就结束 默认规定空格和换行是多个值之间的分割 这在一些需要输入带空格的字符串是会遇到问题
解决方法
getline 获取一行字符串
getline(cin,str)通过这个方法可以解决字符串中存在空格无法正常输入的问题 这是getline默认是遇到换行结束分割 其中第三个参数还可以改变进行分割的表示符
整型转字符串to_string()
void string23()
{
int x;
int y;
cin >> x >> y;
string s1 = to_string(x+y);
cout << s1 << endl;
}
字符串转整型
stoi()其中如果是大数不能转 会超过范围