目录

STL简介:

stl容器的头文件和std标准库的关系:

string的介绍:

<1>string类和char*转换:—————补充————————

(1)string转char*

(2)char*转string

<2>char*转int

(1)atoi:

(2)stoi

(3)strtol

<3>int转char*

———————————————————————————————

string类对象大小

string类对象的输入——getline(cin, a); 新增!

一.string类对象的常见构造函数

(2)单参数的构造函数支持隐式类型转换

二.string类对象的常见析构函数

三.string类对象的赋值 std::string::operator=

四.std::string::operator[]

1.有两个函数重载:

2.使用

【1】题目1:遍历对象的每一个字符,三种做法:

(1)用 std::string::operator[](解决“遍历对象的每一个字符”①)

(2)迭代器(解决“遍历对象的每一个字符”②)

(3)范围for—语法糖(解决“遍历对象的每一个字符”③)

【2】相关练习题目:917. 仅仅反转字母

(1)做法一:利用下标+[]   (已知物理空间是连续的,如果是链表就只能用迭代器)

(2)迭代器做法

3.std::string::operator[] 和 std::string::at

五.迭代器(共四种迭代器)

1.正向迭代器

(1)正向迭代器

2.反向迭代器

(1)反向迭代器

3.const正向迭代器 和 4. const反向迭代器

六.string类中的其他用法

string类可以用==判断相等

1.几个小用法

2.std::string::reserve

3.std::string::resize

(1)例一

(2)例二

4.push_back; append  operator+=

5.插入数据: insert()

题目:415. 字符串相加

6.删除数据: erase()

7.交换对象:swap()

8.返回C格式字符串 c_str

9.std::string::find 和 rfind

(1)find

(2)rfind 从后往前取

10. std::string::substr

11.std::getline (string)

题目:HJ1 字符串最后一个单词的长度

12.std::string::find_first_of

题目:387. 字符串中的第一个唯一字符


STL简介:

1. 什么是 STL
STL(standard template libaray- 标准模板库 ) : C++ 标准库的重要组成部分 ,不仅是一个可复用的组件库,而且 是一个包罗数据结构与算法的软件框架
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 Systems , Inc 公司开发,继承自 HP 版 本。被 GCC(Linux) 采用,可移植性好,
可公开、修改甚至贩卖,从命名风格和编程 风格上看,阅读性非常高。 我们后面学习 STL 要阅读部分源代码, 主要参考的就是这个版本。
3. STL 的六大组件

stl容器的头文件和std标准库的关系:

头文件:#include<string>   (不加.h,C语言中有string.h,防止和C语言的重复)<iostream>头文件除输入输入函数以外也包含<utility>和stl的所有容器的定义部分容器的声明部分容器的声明解释:有的容器在std标准库中有声明,有的stl容器在std标准库中没声明。例如string在std标准库中有声明,unordered_map在std标准库中无声明,即:<iostream>头文件包含了string的声明,但不包含unordered_map的声明,所以不加#include<string>,不加using namespace std;不放开标准库,直接用#include<iostream> ,只需要加上std这个域:std::string就可以正常使用,因为<iostream>头文件有string的声明;但是对于unordered_map,因为<iostream>不包含unordered_map的声明,所以你必须加上#include<unordered_map>里面有声明,才能正常使用unordered_map:

在加上<iostream>前提下,如果加#include<unordered_map>声明,但不加using namespace std; 不把标准库打开,就需要std::限定才能用否则不能用;如果加using namespace std; 打开了标准库,则std::加不加都可以。

若不加#include<unordered_map>,则没有声明,即使加上 std::限定 也用不了。

string的介绍:

typedef basic_string<char> string;  (string是一个类模板)

1.解释:Strings are objects that represent sequences of characters. (strings 是管理字符串的一个类)

2.作用:管理动态增长字符数组,这个字符串以\0结尾

3.底层:类似于下面这样:底层是new一个新空间,再拷贝常量字符串进去,为什么不能直接

_str=str  ? 这样做不行,他们指向同一块空间,都是指向常量字符串了,常量字符串无法实现增删查改

namespace bit
{template<class T>class basic_string{public:basic_string(const T* str){// 开空间存储字符串,方便增删查改size_t len = strlen(str);_str = new T[len + 1];strcpy(_str, str);}private:const T* _str;size_t _size;size_t _capacity;};
}typedef basic_string<char> string;int main(){string s("hello world");}

<1>string类和char*转换:—————补充————————

(1)string转char*

std::string str = "string";
const char *cstr = str.c_str();

(2)char*转string

可以直接赋值。

char *cstr = “hello”;

string sss;

sss = cstr;

<2>char*转int

(1)atoi:

(2)stoi

#include <cstdlib>
int main()
{//int a=atoi("123");int a=stoi("123");printf("%d\n",a);return 0;
}

(3)strtol

<3>int转char*

(1)to_string

———————————————————————————————

string类对象大小

string类对象的输入——getline(cin, a); 新增!

cin和cout写输入输出非常方便,但是用cin输入string字符串时,默认遇到空格回车制表符等空白字符即字符串输入结束。

#include <iostream>
#include <string>
using namespace std;int main() {string a, b;cin >> a >> b;cout << "a:" << a << endl;cout << "b:" << b << endl;return 0;
}/*
输入:
abc 123
输出:
a:abc
b:123
*/

但是遇到带空格字符的字符串就不是很友好了,则需要用到getline函数,getline()是遇回车符输入结束。

#include <iostream>
#include <string>
using namespace std;int main() {string a, b;getline(cin, a);getline(cin, b);cout << "a:" << a << endl;cout << "b:" << b << endl;return 0;
}/*
输入:
abc 123
123 abc
输出:
a:abc 123
b:123 abc
*/

一.string类对象的常见构造函数

(1)

1.string(); 是无参的构造函数。

2.string (const char* s); 是有参构造函数。

3.string (const string& str); 是拷贝构造函数。

4.string (const char* s, size_t n); 是用字符串s的前n个字符初始化

5.string(size_t n, char c);初始化成n个字符c

6.string (const string& str, size_t pos,size_ t len = npos);用string类型对象str的第pos个位置后的len个字符初始化(pos是position位置的缩写,缺省参数npos是 static const size_t npos = -1; 也就是正数里面的最大值,是4294967295:如果pos后面不够取,str太短了,那就取完为止,npos意思是把pos位置后面的取完)

#include<iostream>
#include<string>
using namespace std;
int main()
{string s1;                  // 1.string();    相当于string s1(""); string s2("hello world");   // 2.string (const char* s); string s3(s2);              // 3.string (const string& str); string s4 = s2;             // 3.string (const string& str); string s5("aaabbbcccddd",3);// 4.string (const char* s, size_t n);string s6(10, 'x');         // 5.string(size_t n, char c);
// 6.string (const string& str, size_t pos,size_ t len = npos);string s7(s2, 6, 3);       string s8(s2, 6, 100);cout << s1 << endl;cout << s2 << endl;cout << s3 << endl;cout << s4 << endl;cout << s5 << endl;cout << s6 << endl;cout << s7 << endl;cout << s8 << endl;
}

(2)单参数的构造函数支持隐式类型转换

string s="hello"; 这句,字符串"hello"会先进行隐式类型转换,直接构造一个string类型的"hello",然后这个string类的"hello"拷贝构造给s,但会被编译器优化成直接构造,先构造再拷贝构造——>通过编译器优化就成了直接构造

string s("hello");
string s="hello";

详情见:此文章的大标题三——>小标题2
(88条消息) C++:1.流插入与流提取的运算符重载,2.初始化列表,3.explicit关键字,4.静态成员变量与非静态成员变量用法 详解_beyond.myself的博客-CSDN博客_流插入流提取

二.string类对象的常见析构函数

用途是清理动态资源,不用管,自动调用

三.string类对象的赋值 std::string::operator=

string& operator= (const string& str); 把string类对象赋值成另一个string类对象str(这个是最常用的)
string& operator= (const char* s); 把string类对象赋值成字符串s
string& operator= (char c);  把string类对象赋值成字符c

void test_string2()
{string s1("hello");string s2("xxx");s1 = s2;        //string& operator= (const string& str);s1 = "yyy";     //string& operator= (const char* s);s1 = "y";       //string& operator= (char c);
}
int main()
{test_string2();return 0;
}

四.std::string::operator[]

s1[i] 就相当于 s1.operator[](i); string类对象s1的第i个字符

1.有两个函数重载:

char& operator[](size_t pos)        可读可写

const char& operator[](size_t pos) const          只读

底层逻辑:

​
namespace bit
{class string{public:// 值修改返回对象char& operator[](size_t pos){assert(pos <= _size);    //检查是否越界return _str[pos];}const char& operator[](size_t pos) const{assert(pos <= _size);return _str[pos];}private:char* _str;size_t _size;size_t _capacity;};
}
void test_string4()
{    string s1("hello");          //调用可读可写const string s2("hello");    //调用只读}
int main()
{test_string4();return 0;
}

2.使用

以前的内置类型[]:

    const char* s2 = "world";s2[i]; // *(s2+i)

string中的自定义类型用 std::string::operator[]:

【1】题目1:遍历对象的每一个字符,三种做法:

第一种方式,下标+[]

第二种方式,迭代器

第二种方式,范围for

( s1.size()是计算对象中的字符个数,不包含\0)

(1)用 std::string::operator[](解决“遍历对象的每一个字符”①)

void test_string3()
{// 遍历string的每一个字符string s1("hello");cout << s1.size() << endl;// 第一种方式,下标+[]for (size_t i = 0; i < s1.size(); i++){// s1.operator[](i);cout << s1[i] << " ";}cout << endl;
}
int main()
{test_string3();return 0;
}

(2)迭代器(解决“遍历对象的每一个字符”②)

例1:遍历对象的每一个字符:第二种方式,迭代器

介绍:迭代器是什么? -像指针一样的东西或者就是指针(像指针一样的访问数据结构的东西)

各个类都有独自的迭代器 iterator ,所以要指定是哪个类的,string类中的迭代器写作

string: : iterator

s1.begin()返回第一个位置的指针(或者说第一个位置的迭代器)

s1.end()返回最后一个数据的下一个位置,下面这里的 s1.end() 就是\0的位置

void test_string3()
{// 遍历string的每一个字符string s1("hello");cout << s1.size() << endl;// 迭代器string::iterator it = s1.begin();    //it是s1的首元素地址while (it != s1.end())               //遍历打印,直到it为 \0 停止{            cout << *it << " ";++it;}cout << endl;
}
int main()
{test_string3();return 0;
}

小疑问:这里 while (it != s1.end()) 可以写成 while (it < s1.end())吗?

答:这里是可以,因为是顺序表,存储空间连续,如果像后面的链表形式存储空间不连续就只能用标准的 while (it != s1.end()) 。

例2:vector顺序表

#include<iostream>
#include<vector>
#include<string>
using namespace std;void test_string3()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);vector<int>::iterator vit = v.begin();while (vit != v.end()){cout << *vit << " ";++vit;}cout << endl;
}
int main()
{test_string3();return 0;
}

(3)范围for—语法糖(解决“遍历对象的每一个字符”③)

范围for -- 底层:编译器替换成了迭代器 (这里简答了解一下)

void test_string3()
{// 遍历string的每一个字符string s1("hello");cout << s1.size() << endl;// 范围for -- 原理:替换成迭代器for (auto ch : s1)        //自动取s1中的数据赋值给ch,自动判断结束{cout << ch << " ";}cout << endl;
}
int main()
{test_string3();return 0;
}

【2】相关练习题目:917. 仅仅反转字母

给你一个字符串 s ,根据下述规则反转字符串:

所有非英文字母保留在原有位置。
所有英文字母(小写或大写)位置反转。
返回反转后的 s 。

示例 1:

输入:s = "ab-cd"
输出:"dc-ba"
示例 2:

输入:s = "a-bC-dEf-ghIj"
输出:"j-Ih-gfE-dCba"
示例 3:

输入:s = "Test1ng-Leet=code-Q!"
输出:"Qedo1ct-eeLg=ntse-T!"

(1)做法一:利用下标+[]   (已知物理空间是连续的,如果是链表就只能用迭代器)

class Solution {
public:bool isletter(char ch){if(ch>='a'&&ch<='z')return true;else if(ch>='A'&&ch<='Z')return true;elsereturn false;}string reverseOnlyLetters(string s) {int left=0,right=s.size()-1;while(left<right){while(left<right && !isletter(s[left])) left++;while(left<right && !isletter(s[right]))right--;swap(s[left],s[right]);left++;right--;}    return s;   }
};

(2)迭代器做法

class Solution {
public:bool isletter(char ch){if(ch>='a'&&ch<='z')return true;else if(ch>='A'&&ch<='Z')return true;elsereturn false;}string reverseOnlyLetters(string s) {string::iterator leftIt=s.begin();string::iterator rightIt=s.end()-1;    //end()是\0, s.end()-1 是最后一个字符while(leftIt<rightIt){while(leftIt<rightIt && !isletter(*leftIt)) leftIt++;while(leftIt<rightIt && !isletter(*rightIt))rightIt--;swap(*leftIt,*rightIt);leftIt++;rightIt--;}    return s;   }
};

3.std::string::operator[] 和 std::string::at

用法一样,处理方式不一样,越界时 operator[]通过断言抛异常,at抛越界异常

void test_string4()
{string s1("hello");const string s2("hello");s1[0];s1.at(0);s1[0] = 'x';//s2[0] = 'x';s1.at(0) = 'y';
}
int main()
{test_string4();return 0;
}

五.迭代器(共四种迭代器)

介绍:迭代器是什么? -像指针一样的东西或者就是指针

各个类都有独自的迭代器 iterator ,所以要指定是哪个类的,string类中的迭代器写作

string: : iterator

s1.begin()返回第一个位置的指针(或者说第一个位置的迭代器)

s1.end()返回最后一个数据的下一个位置

1.正向迭代器

(1)正向迭代器

还是以 题目1:遍历对象的每一个字 为例

void test_string5()
{// 遍历string的每一个字符string s1("hello");cout << s1.size() << endl;// 迭代器string::iterator it = s1.begin();    //it是s1的首元素地址while (it != s1.end())               //遍历打印,直到it为 \0 停止{            cout << *it << " ";++it;}cout << endl;
}
int main()
{test_string5();return 0;
}

2.反向迭代器

(1)反向迭代器

void test_string5()
{// 正向迭代器string s("hello world");string::iterator it = s.begin();while (it != s.end()){cout << *it << " ";++it;}cout << endl;// 反向迭代器string::reverse_iterator rit = s.rbegin();    // s.rbegin() 表示最后一个字母d的指针while (rit != s.rend())                       // s.rend() 表示首字母h的指针{cout << *rit << " ";++rit;                    //反向迭代器也是++}cout << endl;
}int main()
{test_string5();return 0;
}

3.const正向迭代器 和 4. const反向迭代器

常规的正向迭代器和反向迭代器是可以修改string类对象的内容的:

void test_string5()
{// 正向迭代器string s("hello world");string::iterator it = s.begin();while (it != s.end()){(*it) += 1;            //修改string类对象的内容cout << *it << " ";++it;}cout << endl;cout << s << endl;// 反向迭代器string::reverse_iterator rit = s.rbegin();while (rit != s.rend()){(*rit) -= 1;            //把string类对象的内容改回去cout << *rit << " ";++rit;}cout << endl;cout << s << endl;
}int main()
{test_string5();return 0;
}

const正向迭代器和const反向迭代器:

const正向迭代器:

此处调用只读类型的 const_iterator begin() const;

只读类型的  const_iterator end() const;

const反向迭代器:

调用只读类型的 const_reverse_iterator begin() const;

只读类型的  const_reverse_iterator rend() const;

void Func(const string& rs)        //传参时转为const类型
{string::const_iterator it = rs.begin(); while (it != rs.end()){//*it += 1;     × 不可以修改cout << *it << " ";++it;}cout << endl;//string::const_reverse_iterator rit = rs.rbegin(); 前面类型太长可以考虑用autoauto rit = rs.rbegin();while (rit != rs.rend()){//(*rit) -= 1;    × 不可以修改cout << *rit << " ";++rit;}cout << endl;
}void test_string6()
{// 正向迭代器string s("hello world");Func(s);
}

六.string类中的其他用法

string类可以用==判断相等

#include<iostream>
using namespace std;
#include<string>
int main()
{string s1("hello");string s2("hello");if (s1 == s2){cout << "相等";}return 0;
}

1.几个小用法

length() 和 size() 一样,都是显示对象中字符串长度,size常用(length是早起写法,不常用)

max_ size() 显示字符串最大能开多长,没什么用

capacity() 显示对象的总容量

2.std::string::reserve

reserve:提前开好n字节空间,不一定是正好n个字节,为了对齐还要多开几个

利用s.push_back( ); 向对象中添加字符,每次容量满了就会扩容1.5倍,很麻烦,已知要添加1000个字符,所以用 reserve:提前开好1000字节空间

void test_string6()
{string s;size_t sz = s.capacity();cout << "making s grow:\n";cout << "capacity changed: " << sz << '\n';for (int i = 0; i < 1000; ++i){s.push_back('c');if (sz != s.capacity()){sz = s.capacity();cout << "capacity changed: " << sz << '\n';}}}
int main()
{test_string6();return 0;
}

用 reserve:提前开好1000字节空间

void test_string6()
{string s;size_t sz1 = s.capacity();cout << "capacity changed: " << sz1 << '\n';  //查看初始容量s.reserve(1000);                //提前开好1000字节空间size_t sz = s.capacity();cout << "making s grow:\n";cout << "capacity changed: " << sz << '\n';    //查看reserve后的容量for (int i = 0; i < 1000; ++i){s.push_back('c');if (sz != s.capacity()){sz = s.capacity();cout << "capacity changed: " << sz << '\n';}}}
int main()
{test_string6();return 0;
}

3.std::string::resize

resize是开空间并初始化

(1)例一

void test_string6()
{string s1;string s2;//s.reserve(1000); // 扩空间s1.resize(1000); // 扩空间+初始化s2.resize(1000, 'x'); // 扩空间+初始化}
int main()
{test_string6();return 0;
}

(2)例二

VS下:reverse不能缩小容量;resize也不能缩小容量,但能去掉前10个后面所有的内容

void test_string6()
{string s1;string s2;s1.resize(100, 'c');s2.resize(100, 'x');s1.reserve(10);s2.resize(10);}
int main()
{test_string6();return 0;
}

4.push_back; append  operator+=

插入一个字符用push_back;插入字符串用append;最好用的还是+=

void test_string6()
{string s;s.push_back('x');s.append("hello");string str("world");s.append(str);cout << s << endl;s += 'x';s += "hello";s += str;cout << s << endl;
}
int main()
{test_string6();return 0;
}

+=:

void test_string8()
{string s("hello");s += " ";s += "world";cout << s << endl;
}
int main()
{test_string8();return 0;
}

5.插入数据: insert()

void test_string8()
{string s("hello");s.insert(0, 1, 'a');        //在第0个位置插入一个字符as.insert(s.begin(), 'b');   //在第0个位置插入一个字符acout << s << endl;s.insert(3, 1, 'x');s.insert(s.begin()+3, 'y');    //里面放迭代器cout << s << endl;
}
int main()
{test_string8();return 0;
}

insert 如果头插的话,第二次头插数据把后面1个挪动1次,第三次头插数据把后面2个挪动1次,……,第n次头插数据把后面n-1个挪动1次,等差数列相加后时间复杂度是O(N²),不如使用+=后逆置reverse( retStr.begin(), retStr.end()); 可以使时间复杂度降低到O(N) :

题目:415. 字符串相加

class Solution {
public:string addStrings(string num1, string num2) {int end1=num1.size()-1;int end2=num2.size()-1;int carry=0;string retStr;while(end1>=0||end2>=0){int val1= end1>=0?num1[end1]-'0':0;int val2= end2>=0?num2[end2]-'0':0;int ret=val1+val2+carry;if(ret>9){carry=1;ret-=10;}elsecarry=0;retStr+=ret+'0';  //这里如果用retStr.insert(retStr.begin(),ret+'0')效率低end1--;end2--;}if(carry==1){retStr+='1';}reverse( retStr.begin(), retStr.end());return retStr;}
};

6.删除数据: erase()

void test_string8()
{string s("hello world");cout << s << endl;s.erase(s.begin());    //删除迭代器所在位置的字符,删除首字符cout << s << endl;s.erase(s.begin() + 3);    //删除第3个字符cout << s << endl;s.erase(3, 2);        //删除包括第3个字符开始后面的2个字符cout << s << endl;//s.erase(3);         //删除包括第3个字符开始后面所有值,因为缺省值npos是最大正数s.erase(3, 100);      //超出就有多少删多少cout << s << endl;
}
int main()
{test_string8();return 0;
}

当用第三种时,删除区间是左闭右开

void test_string14()
{string s("hello world");cout << s << endl;s.erase(s.begin(),s.begin()+2);    cout << s << endl;}
int main()
{test_string14();return 0;
}

7.交换对象:swap()

void test_string9()
{string s1("hello world");string s2("string");// C++98s1.swap(s2);   // 效率高:直接交换指针swap(s1, s2);  // 效率低:库中的交换函数,是深拷贝交换
}
int main()
{test_string9();return 0;
}

STL中的swap函数底层是深拷贝交换:

8.返回C格式字符串 c_str

const char* c_str() const;

获取C字符串等效
返回指向数组的指针,该数组包含以空结尾的字符序列(即C字符串),表示字符串对象的当前值。

此数组包含构成字符串对象值的相同字符序列,最后添加一个终止空字符(“\0”)。

    string s1("hello world");cout << s1 << endl;cout << s1.c_str() << endl;

注意:他返回的是指针,例如下面的对象a和b就算值一样,但他们的返回值是指针,即a.c_str()==b.c_str()比较的是存储字符串位置的地址,不相同,a.c_str() == b.c_str()为假。


int main(int argc, char* argv[])
{string a = "hello world";string b = a;if (a.c_str() == b.c_str()){cout << "true" << endl;}else cout << "false" << endl;return 0;
}

9.std::string::find 和 rfind

(1)find

从字符串 pos 位置开始往后找字符 c ,返回该字符在字符串中的位置
pos缺省值是0:默认从0开始找字符c

返回找的第一个字符的起始位置,找不到就返回npos(npos=42亿9千万...)

file.find('.');   对应第四种用法:size_t find (char c, size_t pos = 0) const; ,'.'对应char c,size_t pos = 0 缺省值是0说明默认从0开始找字符c

void test_string10()
{// 要求取出文件的后缀string file("string.cpp");size_t pos = file.find('.');    //size_t find (char c, size_t pos = 0) const;if (pos != string::npos){//string suffix = file.substr(pos, file.size() - pos);    string suffix = file.substr(pos);    //和下面一样,都是取完后面所有的字符cout << file << "后缀:" << suffix << endl;}else{cout << "没有后缀" << endl;}
}
int main()
{test_string10();return 0;
}

(2)rfind 从后往前取

void test_string10()
{string file("string.c.tar.zip");size_t pos = file.rfind('.');if (pos != string::npos){string suffix = file.substr(pos);//string suffix = file.substr(pos,file.size()-pos);cout << file << "后缀:" << suffix << endl;}else{cout << "没有后缀" << endl;}
}
int main()
{test_string10();return 0;
}

10. std::string::substr

string substr (size_t pos = 0, size_t len = npos) const;

从pos位置往后取(包括pos位置字符)len个字符,返回取出的这一串string类型的字符。默认缺省参数npos是最大正值。

int main()
{std::string str("Please, replace the vowels in this sentence by asterisks.");std::cout << str.substr(6,8) << '\n';return 0;
}

void test_string11()
{// 取出url中的域名string url1("http://www.cplusplus.com/reference/string/string/find/");string url2("https://leetcode.cn/problems/design-skiplist/solution/tiao-biao-probabilistic-alternative-to-b-0cd8/");string& url = url1;// 协议 域名 uristring protocol;size_t pos1 = url.find("://");if (pos1 != string::npos){protocol = url.substr(0, pos1);cout << "protocol:" << protocol << endl;}else{cout << "非法url" << endl;}string domain;size_t pos2 = url.find('/', pos1 + 3);if (pos2 != string::npos){domain = url.substr(pos1 + 3, pos2 - (pos1 + 3));cout << "domain:" << domain << endl;}else{cout << "非法url" << endl;}string uri = url.substr(pos2 + 1);cout << "uri:" << uri << endl;
}
int main()
{test_string11();return 0;
}

11.std::getline (string)

用法是:cin遇到空格或换行就会停下,getline只认换行,遇到空格不会停

题目:HJ1 字符串最后一个单词的长度

#include <iostream>
#include <string>
using namespace std;int main(){string str;getline(cin,str);            //getline用法size_t pos = str.rfind(' ');cout << str.size()-pos-1;return 0;
}

12.std::string::find_first_of

在string类对象中找到第一个出现的字符c,返回此字符的下标值。

int main()
{std::string str("Please, replace the vowels in this sentence by asterisks.");std::size_t found = str.find_first_of("e");int a = 4;while (a--){str[found] = '*';found = str.find_first_of("e", found + 1);}std::cout << str << '\n';return 0;
}

如果找字符串的话,找到包含字符中出现的第一个,并返回下标值

int main()
{std::string str("Please, replace the vowels in this sentence by asterisks.");std::size_t found = str.find_first_of("aeiou");int a = 4;while (a--){str[found] = '*';found = str.find_first_of("aeiou", found + 1);}std::cout << str << '\n';return 0;
}

题目:387. 字符串中的第一个唯一字符

class Solution {
public:int firstUniqChar(string s) {int count[26]={0};for(char ch:s){count[ch-'a']++;}for(int i=0;i<s.size();i++){if(count[s[i]-'a']==1)return i;}return -1;}
};

C++: string讲解 前序相关推荐

  1. 简单讲解前序遍历,中序遍历,后序遍历和层次遍历

    如果你按照 根节点 -> 左孩子 -> 右孩子 的方式遍历,即「先序遍历」,每次先遍历根节点,遍历结果为:1   2   4   5   3   6    7: 同理,如果你按照 左孩子 ...

  2. java根据前序和中序建树_(Java实现)二叉树---根据前序、中序、后序数组还原二叉树...

    概述在上一篇文章中讲到顺序存储二叉树,一般是用于完全二叉树,通过统一的数学公式可以将数组还原成完全二叉树 而对于普通的二叉树来说,也可以根据前序.中序和后序遍历得到的数组,还原二叉树 还原还原的情况分 ...

  3. String、StringBuffer和StringBuilder的详解

    目录 一.String讲解 1.String(String字符串常量) 2.String 拼接方式与性能的影响 二.StringBuffer 和 StringBuilder 讲解 1.StringBu ...

  4. 二叉树 ---- 前序 中序 后序 知二求一

    二叉树 ---- 前序 中序 后序 知二求一 先说一下什么是二叉树的前中后序; 根:根节点 左代表遍历左子树 右代表遍历右子树 前序:根-左---右 中序:左-根---右 后序:左-右---根 如图求 ...

  5. Java数据结构与算法:二叉树

    原文链接:http://www.cnblogs.com/skywang12345/p/3576452.html 1. 二叉查找树简介 二叉查找树(Binary Search Tree),又被称为二叉搜 ...

  6. 二叉查找树(二)之 C++的实现

    二叉查找树(二)之 C++的实现 概要 上一章介绍了"二叉查找树的相关理论知识,并通过C语言实现了二叉查找树".这一章给出二叉查找树的C++版本.这里不再对树的相关概念进行介绍,若 ...

  7. 二叉查找树(一)之 C语言的实现

    二叉查找树(一)之 图文解析 和 C语言的实现 概要 本章先对二叉树的相关理论知识进行介绍,然后给出C语言的详细实现.关于二叉树的学习,需要说明的是:它并不难,不仅不难,而且它非常简单.初次接触树的时 ...

  8. 【编程3】二叉树遍历(LeetCode.102)

    文章目录 一.二叉树的层次遍历 1.题目描述--LeetCode.102 2.分析 3.实现 二.二叉树(Binary Tree) 1.相关概念 二叉树 满二叉树 完全二叉树 区分 2.二叉树的表示( ...

  9. DP专练1( [NOIP 2003]加分二叉树 + 太空梯 )

    我们先慢慢来 加分二叉树 题目 题解 简单讲解前序//中序//后序遍历 代码实现 太空梯 题目 题解 代码实现 加分二叉树 题目 题解 简单讲解前序//中序//后序遍历 其实说白了,这个*序就是根ro ...

最新文章

  1. 024_Word知识汇总
  2. mysql中usage是什么权限?
  3. 【vue】webpack打包vue项目并且运行在Tomcat里面
  4. 灯的开关 Bulb Switcher II
  5. 2017年第八届蓝桥杯C/C++ C组国赛 —— 第四题:小数第n位
  6. silverlight: [HtmlPage_NotEnabled] 调试资料字符串不可用的解决
  7. C#的特性Attribute
  8. ubuntu下,rubyonrails环境搭建
  9. 做H5页面用什么软件比较好?
  10. SQLMAP注入拖库过程 1
  11. 自用frp服务器分享及客户端配置连接教程
  12. mysql deadlock found_MySQL遇到Deadlock found when trying to get lock,解决方案
  13. LaTeX引文.bib方式插入——misplaced alignment tab character . ...ock{\em IEEE Transactions onSystems Man
  14. android 自定义心电图,Android动态滚动波形图(心电图)的实现
  15. 什么是集成测试?集成测试方法有哪些?
  16. 计算机无法信任的英文,关于信任的英语名言佳句语录
  17. 管人就是管情绪——从《纸牌屋》中的心理操控说起
  18. 要玩就玩最好的棋牌游戏
  19. MQTT+ActiveMQ实现消息推送(移动端)
  20. 华为HiLink智慧家庭生态发布 引领未来智能生活

热门文章

  1. Java Socket udp协议在网络读卡器上的使用
  2. Linux 中 exit 的意思
  3. java 用数组存储书籍信息_有大神会编下这样的简单系统嘛,Java的,用数组存储信息!...
  4. cf进不去服务器 正在连接,Win7电脑CF连接服务器失败如何解决 CF连接不到服务器怎么办...
  5. 高德地图轨迹展示样式修改
  6. 关键周!非农携众多重量级数据来袭、黄金多头冲击千八大关!
  7. BIOS SETUP UTILITY
  8. 一瓶汽水1块钱,3个瓶盖换一瓶汽水,2个空瓶换一瓶汽水,假如手里有5块钱,能喝多少瓶汽水
  9. 红魔馆爆炸了---湖南科技大学oj1975---尺取法
  10. 有关Maven依赖中的version