最便宜的网站空间,电子商务岗位有哪些,学做ps的软件的网站,南京装修公司做网站文章目录 目录1. STL简介1.1 什么是STL1.2 STL的版本1.3 STL的六大组件 2. 为什么学习string类3. 标准库中的string类3.1 string类3.2 string类的常用接口说明 目录
STL简介为什么学习string类标准库中的string类string类的模拟实现现代版写法的String类写时拷贝
1. STL简介 … 文章目录 目录1. STL简介1.1 什么是STL1.2 STL的版本1.3 STL的六大组件 2. 为什么学习string类3. 标准库中的string类3.1 string类3.2 string类的常用接口说明 目录
STL简介为什么学习string类标准库中的string类string类的模拟实现现代版写法的String类写时拷贝
1. STL简介
1.1 什么是STL
STL(standard template libaray-标准模板库)是C标准库的重要组成部分不仅是一个可复用的组件库而且是一个包罗数据结构与算法的软件框架。
1.2 STL的版本
原始版本
Alexander Stepanov、Meng Lee 在惠普实验室完成的原始版本本着开源精神他们声明允许任何人任意运用、拷贝、修改、传播、商业使用这些代码无需付费。唯一的条件就是也需要向原始版本一样做开源使用。HP 版本–所有STL实现版本的始祖。
P. J. 版本
由P. J. Plauger开发继承自HP版本被Windows Visual C采用不能公开或修改缺陷可读性比较低符号命名比较怪异。
RW版本
由Rouge Wage公司开发继承自HP版本被C Builder 采用不能公开或修改可读性一般。
SGI版本
由Silicon Graphics Computer SystemsInc公司开发继承自HP版本。被GCC(Linux)采用可移植性好可公开、修改甚至贩卖从命名风格和编程风格上看阅读性非常高。我们后面学习STL要阅读部分源代码主要参考的就是这个版本。
1.3 STL的六大组件 2. 为什么学习string类
C语言中字符串是以’\0’结尾的一些字符的集合为了操作方便C标准库中提供了一些str系列的库函数但是这些库函数与字符串是分离开的不太符合OOP的思想而且底层空间需要用户自己管理稍不留神可能还会越界访问。
3. 标准库中的string类
3.1 string类
string类的具体信息可以通过cplusplus网站进行查阅
在使用string类时必须包含#include头文件以及using namespace std;
3.2 string类的常用接口说明
我们先来总的看一下string类的常用接口
string类对象的常见构造 string类对象的容量操作 string类对象的访问及遍历操作 string类对象的修改操作 string类非成员函数 接下来我们通过一些具体的场景来学习如何使用这些接口
如何构造一个string类对象
#include iostream
#include stringusing namespace std;void test_string1()
{//常用string s1;string s2(hello world);string s3(s2);//不常用 了解string s4(s2, 3, 5);string s5(s2, 3);string s6(s2, 3, 30);string s7(hello world, 5);string s8(10, x);cout s1 endl;cout s2 endl;cout s3 endl;cout s4 endl;cout s5 endl;cout s6 endl;cout s7 endl;cout s8 endl;cin s1;cout s1 endl;
}int main()
{test_string1();return 0;
}补充
void push_back(const string s)
{}void test_string2()
{//构造string s1(hello world);//隐式类型转换string s2 hello world;const string s3 hello world;push_back(s1);push_back(hello world);
}int main()
{test_string2();return 0;
}string的遍历
第一种方法
//class string
//{
//public:
// //引用返回
// //1. 减少拷贝
// //2. 修改返回对象
// char operator[](size_t i)
// {
// assert(i _size);
//
// return _str[i];
// }
//private:
// char* _str;
// size_t _size;
// size_t _capacity;
//};void test_string3()
{string s1(hello world);cout s1.size() endl;//11//cout s1.length() endl;//11for (size_t i 0; i s1.size(); i){s1[i];}s1[0] x;//越界检查//s1[20];for (size_t i 0; i s1.size(); i){//cout s1.operator[](i) ;cout s1[i] ;}cout endl;const string s2(hello world);//不能修改//s2[0] x;
}int main()
{test_string3();return 0;
}注 size() 与 length() 方法底层实现原理完全相同引入 size() 的原因是为了与其他容器的接口保持一致一般情况下基本都是用 size() 。
第二种方法
void test_string4()
{string s1(hello world);//遍历方式2迭代器string::iterator it1 s1.begin();while (it1 ! s1.end()){*it1 3;cout *it1 ;it1;}cout endl;//cout typeid(it1).name() endl;
}int main()
{test_string4();return 0;
}void test_string4()
{listint lt1;lt1.push_back(1);lt1.push_back(2);lt1.push_back(3);listint::iterator it lt1.begin();while (it ! lt1.end()){cout *it ;it;}cout endl;
}int main()
{test_string4();return 0;
}第三种方法
void test_string4()
{string s1(hello world);//遍历方式3范围for通用的//底层角度它就是迭代器for (auto e : s1){e;//不会影响s1中的数据它是一个赋值拷贝要加上引用才会改变s1中的数据cout e ;}cout endl;cout s1 endl;listint lt1;lt1.push_back(1);lt1.push_back(2);lt1.push_back(3);for (auto e : lt1){cout e ;}cout endl;
}int main()
{test_string4();return 0;
}注 除了普通迭代器之外还有
const迭代器
void test_string5()
{const string s1(hello world);//string::const_iterator it1 s1.begin();auto it1 s1.begin();while (it1 ! s1.end()){//不能修改//*it1 3;cout *it1 ;it1;}cout endl;
}int main()
{test_string5();return 0;
}反向迭代器
void test_string5()
{string s2(hello world);string::reverse_iterator it2 s2.rbegin();//auto it2 s2.rbegin();while (it2 ! s2.rend()){*it2 3;cout *it2 ;it2;}cout endl;const string s3(hello world);string::const_reverse_iterator it3 s3.rbegin();//auto it3 s3.rbegin();while (it3 ! s3.rend()){//不能修改//*it3 3;cout *it3 ;it3;}cout endl;
}int main()
{test_string5();return 0;
}按字典序排序
#include algorithmvoid test_string6()
{string s1(hello world);cout s1 endl;//s1按字典序ASCII码排序//sort(s1.begin(), s1.end());//第一个和最后一个不参与排序//sort(s1.begin(), --s1.end());//前5个排序sort(s1.begin(), s1.begin() 5);cout s1 endl;
}int main()
{test_string6();return 0;
}插入字符
void test_string7()
{string s1(hello world);cout s1 endl;s1.push_back(x);cout s1 endl;s1.append( yyyyyy!!);cout s1 endl;string s2(111111);s1 y;s1 zzzzzzzz;s1 s2;cout s1 endl;
}int main()
{test_string7();return 0;
}注 在string尾部追加字符时s.push_back(‘c’) / s.append(1, ‘c’) / s ‘c’ 三种的实现方式差不多一般情况下string类的 操作用的比较多 操作不仅可以连接单个字符还可以连接字符串。
关于修改的一些接口
void test_string8()
{string s1(hello world);cout s1 endl;s1.assign(111111);cout s1 endl;//慎用因为效率不高 - O(N)//实践中需求也不高string s2(hello world);s2.insert(0, xxxx);cout s2 endl;s2.insert(0, 1, y);cout s2 endl;s2.insert(s2.begin(), y);cout s2 endl;s2.insert(s2.begin(), s1.begin(), s1.end());cout s2 endl;
}int main()
{test_string8();return 0;
}void test_string9()
{string s1(hello world);cout s1 endl;//erase效率不高慎用和insert类似要挪动数据s1.erase(0, 1);cout s1 endl;//s1.erase(5);s1.erase(5, 100);cout s1 endl;//replace效率不高慎用和insert类似要挪动数据string s2(hello world);s2.replace(5, 1, %20);cout s2 endl;string s3(hello world hello bit);for (size_t i 0; i s3.size(); ){if ( s3[i]){s3.replace(i, 1, %20);i 3;}else{i;}}cout s3 endl;string s4(hello world hello bit);string s5;for (auto ch : s4){if (ch ! ){s5 ch;}else{s5 %20;}}cout s5 endl;
}int main()
{test_string9();return 0;
}我们来做几个题目
仅仅反转字母
class Solution
{
public:bool isLetter(char ch){if (ch a ch z){return true;}if (ch A ch Z){return true;}return false;}string reverseOnlyLetters(string s){if (s.empty()){return s;}size_t begin 0, end s.size() - 1;while (begin end){while (begin end !isLetter(s[begin])){begin;}while (begin end !isLetter(s[end])){--end;}swap(s[begin], s[end]);begin;--end;}return s;}
};字符串中的第一个唯一字符 class Solution
{
public:int firstUniqChar(string s){int count[26] { 0 };//统计次数for (auto ch : s){count[ch - a];}for (size_t i 0; i s.size(); i){if (1 count[s[i] - a]){return i;}}return -1;}
};验证回文串
class Solution
{
public:bool isLetterOrNumber(char ch){return (ch 0 ch 9)|| (ch a ch z);}bool isPalindrome(string s){for (auto ch : s){if (ch A ch Z){ch 32;}}int begin 0, end s.size() - 1;while (begin end){while (begin end !isLetterOrNumber(s[begin])){begin;}while (begin end !isLetterOrNumber(s[end])){--end;}if (s[begin] ! s[end]){return false;}else{begin;--end;}}return true;}
};字符串相加
法一
//时间复杂度O(N^2) 因为头插的效率太低
class Solution
{
public:string addStrings(string num1, string num2){int end1 num1.size() - 1;int end2 num2.size() - 1;string str;int next 0;//进位while (end1 0 || end2 0){int x1 end1 0 ? num1[end1--] - 0: 0;int x2 end2 0 ? num2[end2--] - 0: 0;int x x1 x2 next;//处理进位next x / 10;x x % 10;//头插//str.insert(0, 1, 0 x);str.insert(str.begin(), 0 x);}if (1 next){str.insert(str.begin(), 1);}return str;}
};法二
//时间复杂度O(N)
class Solution
{
public:string addStrings(string num1, string num2){int end1 num1.size() - 1;int end2 num2.size() - 1;string str;int next 0;//进位while (end1 0 || end2 0){int x1 end1 0 ? num1[end1--] - 0: 0;int x2 end2 0 ? num2[end2--] - 0: 0;int x x1 x2 next;//处理进位next x / 10;x x % 10;//尾插str (0 x);}if (1 next){str 1;}reverse(str.begin(), str.end());return str;}
};string类对象的容量操作
void TestPushBack()
{string s;size_t sz s.capacity();cout capacity changed: sz \n;cout making s grow:\n;for (int i 0; i 200; i){s.push_back(c);if (sz ! s.capacity()){sz s.capacity();cout capacity changed: sz \n;}}
}void test_string10()
{string s1(hello world hello bit);cout s1.size() endl;cout s1.capacity() endl;cout s1.max_size() endl;TestPushBack();string s1(111111111);string s2(11111111111111111111111111111111111111111111111111);
}int main()
{test_string10();return 0;
}void TestPushBack()
{string s;//知道需要多少空间提前开好s.reserve(200);size_t sz s.capacity();cout capacity changed: sz \n;cout making s grow:\n;for (int i 0; i 200; i){s.push_back(c);if (sz ! s.capacity()){sz s.capacity();cout capacity changed: sz \n;}}
}void test_string10()
{ TestPushBack();string s1(111111111);string s2(11111111111111111111111111111111111111111111111111);cout s1.capacity() endl;s1.reserve(100);cout s1.capacity() endl;s1.reserve(20);cout s1.capacity() endl;
}int main()
{test_string10();return 0;
}void test_string11()
{string s1;//s1.resize(5, 0);s1.resize(5);s1[4] 3;s1[3] 4;s1[2] 5;s1[1] 6;s1[0] 7;//76543//插入空间不够会扩容string s2(hello world);s2.resize(20, x);//删除s2.resize(5);//s2[10];try{s2.at(10);}catch (const exception e){cout e.what() endl;}
}int main()
{test_string11();return 0;
}注
clear()只是将string中有效字符清空不改变底层空间大小。代码中没有演示resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个不同的是当字符个数增多时resize(n)用0来填充多出的元素空间resize(size_t n, char c)用字符c来填充多出的元素空间。注意resize在改变元素个数时如果是将元素个数增多可能会改变底层容量的大小如果是将元素个数减少底层空间总大小不变。reserve(size_t res_arg0)为string预留空间不改变有效元素个数当reserve的参数小于string的底层空间总大小时reserver不会改变容量大小。对string操作时如果能够大概预估到放多少字符可以先通过reserve把空间预留好。 string类的一些其他操作
#define _CRT_SECURE_NO_WARNINGS 1void test_string12()
{string file(test.cpp);FILE* fout fopen(file.c_str(), r);char ch fgetc(fout);while (ch ! EOF){cout ch;ch fgetc(fout);}
}int main()
{test_string12();return 0;
}void test_string12()
{string file(string.cpp.zip);size_t pos file.rfind(.);//string suffix file.substr(pos, file.size() - pos);string suffix file.substr(pos);cout suffix endl;
}int main()
{test_string12();return 0;
}void test_string12()
{string url(https://gitee.com/ailiangshilove/cpp-class/blob/master/%E8%AF%BE%E4%BB%B6%E4%BB%A3%E7%A0%81/C%E8%AF%BE%E4%BB%B6V6/string%E7%9A%84%E6%8E%A5%E5%8F%A3%E6%B5%8B%E8%AF%95%E5%8F%8A%E4%BD%BF%E7%94%A8/TestString.cpp);size_t pos1 url.find(:);string url1 url.substr(0, pos1 - 0);cout url1 endl;size_t pos2 url.find(/, pos1 3);string url2 url.substr(pos1 3, pos2 - (pos1 3));cout url2 endl;string url3 url.substr(pos2 1);cout url3 endl;
}int main()
{test_string12();return 0;
}void test_string13()
{string str(Please, replace the vowels in this sentence by asterisks.);size_t found str.find_first_of(aeiou);while (found ! string::npos){str[found] *;found str.find_first_of(aeiou, found 1);}cout str \n;
}int main()
{test_string13();return 0;
}void SplitFilename(const string str)
{cout Splitting: str \n;size_t found str.find_last_of(/\\);cout path: str.substr(0, found) \n;cout file: str.substr(found 1) \n;
}int main()
{string str1(/usr/bin/man);string str2(c:\\windows\\winhelp.exe);SplitFilename(str1);SplitFilename(str2);return 0;
}void test_string14()
{string s1 hello;string s2 world;string ret1 s1 s2;cout ret1 endl;string ret2 s1 xxxxx;cout ret2 endl;string ret3 xxxxx s1;cout ret3 endl;//字典序比较cout (s1 s2) endl;
}int main()
{test_string14();return 0;
}一个题目
字符串最后一个单词的长度 #include iostream
using namespace std;int main()
{string str;//默认规定空格或者换行是多个值之间分割//cin str;//获取一行中包含空格不能用getline(cin, str);size_t pos str.rfind( );cout str.size() - (pos 1) endl;return 0;
}输入多行字符依次打印
int main()
{//默认规定空格或者换行是多个值之间分割string str;//ctrl z 就可以结束while (cin str){cout str endl;}return 0;
}字符串转整形整形转字符串
int main()
{//atoi itoa//to_stringint x 0, y 0;cin x y;string str to_string(x y);cout str endl;int z stoi(str);return 0;
}