南浦电商网站建设,网上商店也叫做,php做的购物网站,网站建设归哪个部门目录 STL简介 STL的版本 STL的六大组件 string类 标准库中的string类 string类的常用接口 string类对象对容量的操作 size()函数与length()函数 capacity()函数 capacity的扩容方式 reserve()函数 resize()函数 string类对象的操作 push_back()函数 append()函数 operator()函数… 目录 STL简介 STL的版本 STL的六大组件 string类 标准库中的string类 string类的常用接口 string类对象对容量的操作 size()函数与length()函数 capacity()函数 capacity的扩容方式 reserve()函数 resize()函数 string类对象的操作 push_back()函数 append()函数 operator()函数运算符重载函数 operator()函数运算符重载函数 assign()函数 insert()函数 erase()函数 replace()函数 find()函数 swap()函数 c_str()函数 substr()函数 rfind()函数 find_first_of()函数 relational operators系列函数 getline()函数 string类对象的访问及遍历操作 operator[]与at()函数 string类迭代器遍历 正向遍历 逆向遍历 STL简介 STL(standard template libaray-标准模板库)是C标准库的重要组成部分不仅是一个可复用的组件库而且是一个包罗数据结构与算法的软件框架 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的六大组件 在上面的图中空间配置器实际上就是在内存池中申请空间。另外string类型本不属于STL因为出现得早没被划分到STL中但是其接口基本上和STL中其他容器的接口类似故将其列入上图中的STL容器部分 string类 在C语言中字符串是以\0结尾的字符数组为了操作方便C语言还提供了和字符串相关的函数放在string.h中但是在C语言中函数和字符串类型是分割的不符合面向对象编程的思想并且在操作字符串的过程中还需要注意防止越界 标准库中的string类 字符串是表示字符序列的类标准的字符串类提供了对此类对象的支持其接口类似于标准字符容器的接口但添加了专门用于操作单字节字符字符串的设计特性string类是使用char(即作为它的字符类型使用它的默认char_traits和分配器类型(关于模板的更多信息请参阅basic_string)string类是basic_string模板类的一个实例它使用char来实例化basic_string模板类并用char_traits和allocator作为basic_string的默认参数(根于更多的模板信息请参考basic_string) 注意这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列这个类的所有成员(如长度或大小)以及它的迭代器将仍然按照字节(而不是实际编码的字符)来操作。 总结 string是表示字符串的字符串类该类的接口与常规容器的接口基本相同再添加了一些专门用来操作string的常规操作。string在底层实际是basic_string模板类的别名typedef basic_stringchar, char_traits, allocator string;不能操作多字节或者变长字符的序列。 在使用string类时必须包含#include头文件以及using namespace std;或者展开需要使用的内容 string类的常用接口 构造函数 函数原型 无参构造函数 string(); 拷贝构造函数 string (const string str); 子串构造函数 string (const string str, size_t pos, size_t len npos); 使用字符串构造函数 string (const char* s); 使用部分字符串构造函数字符 string (const char* s, size_t n); //无参构造函数
#include iostream
using namespace std;int main()
{string s1;return 0;
}//使用字符串构造函数
#include iostream
using namespace std;int main()
{string s2(hello world);cout s2 endl;return 0;
}
输出结果
hello world//使用部分字符串构造函数
#include iostream
using namespace std;int main()
{string s3(hello world, 5);cout s3 endl;return 0;
}
输出结果
hello//子串构造函数
#include iostream
using namespace std;int main()
{string s4 hello world;//当构造函数没有explicit时可以使用赋值string s5(s4, 0, 7);cout s5 endl;return 0;
}
输出结果
hello w 对于函数string (const string str, size_t pos, size_t len npos);来说pos为起始位置len为需要取的字符串的长度如果len参数大于字符串的可提供的长度那么会一直取到字符串结尾如果使用缺省值npos缺省值为-1那么同样会取到字符串结尾 string类也有析构函数~string()和赋值运算符重载函数 赋值运算符重载函数 string operator (const string str);对象赋值 string operator (const char* s);字符串赋值 string operator (char c);字符赋值 string类对象对容量的操作 函数 功能 size() 返回字符串有效字符长度 length() 返回字符串有效字符长度 capacity() 返回当前为字符串开辟的空间大小 reserve() 为字符串预留指定的空间 resize() 将有效字符的个数修改成指定个数多出的空间默认使用\0填充也可以使用指定字符填充 size()函数与length()函数 对于计算字符串有效字符长度的函数来说不会计算\0并且size()和length()的效果相同 #include iostream
using namespace std;int main()
{string s1(hello world);cout s1.size() endl;cout s1.length() endl;return 0;
}
输出结果
11
11 capacity()函数 #include iostream
using namespace std;int main()
{string s1 hello world;cout s1.size() endl;cout s1.capacity() endl;return 0;
}
输出结果
11
15 在上面的代码中size()和capacity()并不相等所以size()不等同于capacity()可以类比到数据结构中顺序表的有效数据个数size和capacity capacity的扩容方式 在VS环境下面运行下面的代码可以大致估算得到capacity的扩容倍数 #include iostream
using namespace std;int main()
{string s ;size_t sz s.capacity();cout start 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;}}return 0;
}
输出结果
start15
making s grow:
capacity changed: 31
capacity changed: 47
capacity changed: 70
capacity changed: 105 计算capacity时不会计算\0所存在的空间 在上面的代码中因为并没有计算\0所在的空间所以实际结果为 start16
making s grow:
capacity changed: 32
capacity changed: 48
capacity changed: 71
capacity changed: 106 观察到除了第一次和第二次以外其余均为大致1.5倍增长但是第一次和第二次的增长并不是2倍而是因为VS将第一次存储字符串的位置分成了两部分第一个部分是_buf[16]数组第二个部分是*ptr指向超过16个字符时存储的动态开辟的内存空间 对于下面的代码中有一个11个字符不包括\0的字符串 #include iostream
using namespace std;int main()
{string s hello world;size_t sz s.capacity();cout start 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;}}return 0;
}
输出结果
start15
making s grow:
capacity changed: 31
capacity changed: 47
capacity changed: 70
capacity changed: 105
capacity changed: 157 此时hello world\0存储的位置在_buf[16]数组中 如果字符串的长度大于16时则不会存储到_buf[16]中而是存储到ptr指针指向的内存空间 可以推测出在设计string类时底层的成员变量有下面几种 class string
{
private:char _buf[16];//长度为16的数组char* ptr;//指向存储char类型元素的空间size_t size;size_t capacity;
}; 所以在VS下第一次和第二次之间是两倍的关系并不是扩容两倍而是改变了存储位置 reserve()函数 使用reserve()函数可以为字符串预留指定大小的空间此时当指定大小远大于前面扩容的大小时一般不会再进行扩容 #include iostream
using namespace std;int main()
{string s hello world;s.reserve(100);size_t sz s.capacity();cout start 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;}}return 0;
}
输出结果
start111
making s grow: 在VS下使用reserve()函数指定的大小一般会被编译器扩大一小部分但是在GCC下指定多少就是多少所以在上面的代码中虽然指定的大小为100但是实际的大小为111 但是不论时哪种编译平台都要至少保证开辟的大小不能小于指定大小 使用reserve()函数时如果已经有空间时对原始空间进行扩容时不会改变有效字符长度size值只会改变capacity的值从而达到扩容的效果 注意若扩容的值小于原始空间时那么此时reserve()函数不起任何效果 #include iostream
using namespace std;int main()
{string s hello world;size_t sz s.capacity();cout start_capacity sz \n;cout start_size s.size() \n;s.reserve(200);cout after_capacity s.capacity() \n;cout after_size s.size() \n;return 0;
}
输出结果
start_capacity15
start_size11
after_capacity207
after_size11 在扩容之后尽管原始字符串的大小小于_buf[16]数组的长度也会被移动到ptr指向的空间如图所示 执行reserve()函数前 执行reserve()函数后 resize()函数 不同于reserve()函数使用resize()函数可以将原始空间扩容并且初始化扩容的空间默认初始化字符为\0当指定为某一个字符后则将初始化对应字符 #include iostream
using namespace std;int main()
{string s hello world;cout start_capacity s.capacity() \n;cout start_size s.size() \n;s.resize(200);cout after_capacity s.capacity() \n;cout after_size s.size() \n;return 0;
}
输出结果
start_capacity15
start_size11
after_capacity207
after_size200 在上面的代码中使用resize()函数时会同时改变size的大小和capacity的大小size的大小刚好为resize()函数的参数值并且默认将其余部分初始化为\0 也可以指定某一个字符 #include iostream
using namespace std;int main()
{string s hello world;cout start_capacity s.capacity() \n;cout start_size s.size() \n;s.resize(200, *);cout after_capacity s.capacity() \n;cout after_size s.size() \n;return 0;
} 使用resize()函数还可以达到删除字符的效果当扩容值参数的大小小于已经存在的字符串的长度时 #include iostream
using namespace std;int main()
{string s hello world;cout start_capacity s.capacity() \n;cout start_size s.size() \n;s.resize(5);cout s endl;cout after_capacity s.capacity() \n;cout after_size s.size() \n;return 0;
}
输出结果
start_capacity15
start_size11
hello
after_capacity15
after_size5 注意尽管使用resize()函数后改变了size的大小但是对于capacity来说一旦在开始确定好了大小那么使用resize()改变size的值使其小于已经设定的值此时不会改变capacity的大小因为缩容是非法的如果支持缩容那么证明可以支持free释放部分空间 string类对象的操作 此处展示部分可能用得到的成员函数全部成员函数参考文档string - C Reference (cplusplus.com) 函数 功能 函数原型 push_back 在字符串后尾插指定字符 void push_back (char c); append 在字符串后追加一个字符串 string append (const char* s);常用 operator 在字符串后追加字符串或字符 string operator (const string str);追加string类对象 string operator (const char* s); 追加字符串 string operator (char c); 追加字符 push_back()函数 使用push_back()函数可以在字符串后追加字符 #include iostream
using namespace std;int main()
{string s hello;s.push_back(w);cout s endl;return 0;
}
输出结果
hellow append()函数 使用append()函数可以在字符串后追加字符串 #include iostream
using namespace std;int main()
{string s hello;s.append( world);cout s endl;return 0;
}
输出结果
hello world operator()函数运算符重载函数 使用operator()函数可以达到append()和push_back()的效果 #include iostream
using namespace std;int main()
{string s hello world;string s1 CPP;//追加字符s c;cout s endl;//追加字符串s hello;s world;cout s endl;//追加对象s hello ;s s1;cout s endl;return 0;
}
输出结果
hello worldc
hello world
hello CPP operator()函数运算符重载函数 使用operator()函数可以将两个字符串相加即合并但不改变原来的字符串 函数 函数原型 operator() string operator (const string lhs, const string rhs); 将两个string类对象的字符串相加 string operator (const string lhs, const char* rhs); string operator (const char* lhs, const string rhs); 将字符串和对象的字符串相加 string operator (const string lhs, char rhs); string operator (char lhs, const string rhs); 将字符和对象的字符串相加 #include iostream
using namespace std;int main()
{string s1 hello;string s2 world;string s3 s1 s2;cout s1 endl;cout s2 endl;cout s3 endl;return 0;
}
输出结果
helloworld
hello world assign()函数 使用assign()函数可以将一个对象或者字符串赋值给另一个对象 函数 函数原型 assign() string assign (const string str);对象赋值给调用对象 string assign (const string str, size_t subpos, size_t sublen npos);赋值对象中的部分字符给调用对象 string assign (const char* s);将字符串赋值给调用对象 string assign (const char* s, size_t n);将部分字符串赋值给调用对象 string assign (size_t n, char c);使用字符c填充调用对象的空间 //对象赋值给调用对象
#include iostream
using namespace std;int main()
{string s1 hello;string s2(world);s1.assign(s2);//将s2中的内容覆盖s1对象中的内容cout s1 endl;return 0;
}
输出结果
world//赋值对象中的部分字符给调用对象
#include iostream
using namespace std;int main()
{string s1 world;string s2 Linux;s1.assign(s2, 2, 2);//从第二个位置开始赋值2个字符给s1对象包括第二个位置的字符cout s1 endl;return 0;
}
输出结果
nu//将字符串赋值给调用对象
#include iostream
using namespace std;int main()
{string s1 xxxxxxx;cout s1 endl;s1.assign(hello world);cout s1 endl;return 0;
}
输出结果
xxxxxxx
hello world//将部分字符串赋值给调用对象
#include iostream
using namespace std;int main()
{string s1 xxxxxx;s1.assign(hello world, 5);//默认从0开始拷贝5个字符包括0位置的字符cout s1 endl;return 0;
}
输出结果
hello//使用字符c填充调用对象的空间
#include iostream
using namespace std;int main()
{string s1 xxxxx;s1.assign(5, C);cout s1 endl;return 0;
}
输出结果
CCCCC insert()函数 使用insert()函数可以指定插入某个内容到字符串指定位置中 在插入过程中会涉及挪动数据以及扩容问题所以不建议大量使用 函数 函数原型 insert() string insert (size_t pos, const string str); 在调用对象的字符串pos位置中插入对象中的字符串 string insert (size_t pos, const string str, size_t subpos, size_t sublen npos); 在调用对象的pos位置插入对象中subpos位置开始的指定个数的字符串 string insert (size_t pos, const char* s);在调用对象pos位置插入字符串s string insert (size_t pos, const char* s, size_t n); 在调用对象pos位置插入指定个数个字符串中的字符 string insert (size_t pos, size_t n, char c);在调用对象pos位置插入n个字符c void insert (iterator p, size_t n, char c);迭代器p位置开始插入n个字符c iterator insert (iterator p, char c);在调用对象迭代器p指向位置插入字符c 注意插入字符串时不会覆盖原来pos位置存在的字符原来pos位置及以后的字符向后移动 //在调用对象的字符串pos位置中插入对象中的字符串
#include iostream
using namespace std;int main()
{string s1 hello-world;string s2 my ;s1.insert(5, s2);cout s1 endl;return 0;
}
输出结果
hello my -world//在调用对象的pos位置插入对象中subpos位置开始的指定个数的字符串
#include iostream
using namespace std;int main()
{string s1 hello world;string s2 hello Linux;s1.insert(5, s2, 5, 6);cout s1 endl;return 0;
}
输出结果
hello Linux world//在调用对象pos位置插入字符串s
#include iostream
using namespace std;int main()
{string s1 hello world;s1.insert(6, CPP );cout s1 endl;return 0;
}
输出结果
hello CPP world//在调用对象pos位置插入指定个数个字符串中的字符
#include iostream
using namespace std;int main()
{string s1 hello world;s1.insert(6, CPP is, 4);cout s1 endl;return 0;
}
输出结果
hello CPP world//迭代器p位置开始插入n个字符c
#include iostream
using namespace std;int main()
{string s1 hello world;s1.insert(s1.begin() 6, 3, c);//在下标6位置开始连续插入字符ccout s1 endl;return 0;
}
输出结果
hello cccworld//在调用对象迭代器p指向位置插入字符c
#include iostream
using namespace std;int main()
{string s1 hello world;s1.insert(s1.begin() 5, c);//在下标5位置插入字符ccout s1 endl;return 0;
}
输出结果
helloc world erase()函数 使用erase()函数可以删除指定对象中的内容 函数 函数原型 erase() string erase (size_t pos 0, size_t len npos); 删除调用对象pos位置开始len长度的字符 iterator erase (iterator p); 删除迭代器p指向位置的字符 因为删除字符会涉及到挪动数据所以不推荐大量使用erase()函数 //删除调用对象pos位置开始len长度的字符
#include iostream
using namespace std;int main()
{string s1 hello world;s1.erase(5, 3);cout s1 endl;return 0;
}
输出结果
hellorld//删除迭代器p指向位置的字符
#include iostream
using namespace std;int main()
{string s1 hello world;s1.erase(s1.begin() 5);cout s1 endl;return 0;
}
输出结果
helloworld replace()函数 使用replace()函数可以替换调用对象的字符串中的字符 因为替换的字符串可能比被替换的字符串长所以可能涉及到空间的扩容和数据的移动不推荐大量使用replace()函数 函数 函数功能 replace() string replace (size_t pos, size_t len, const string str); 使用对象中的字符串替换调用对象pos位置开始len长度的字符串 string replace (size_t pos, size_t len, const string str, size_t subpos, size_t sublen); 使用对象中的subpos位置开始的sublen长度的字符串替换调用对象pos位置开始的len长度的字符串 string replace (size_t pos, size_t len, const char* s); 使用字符串s替换调用对象pos位置开始的len长度的字符串 string replace (size_t pos, size_t len, const char* s, size_t n); 使用字符串中的n个字符替换调用对象pos位置开始的len长度的字符串 string replace (size_t pos, size_t len, size_t n, char c); 使用n个字符替换调用对象pos位置开始的len长度的字符串 //使用对象中的字符串替换调用对象pos位置开始len长度的字符串
#include iostream
using namespace std;int main()
{string s1 hello world;string s2 Linux;s1.replace(6, 5, s2);cout s1 endl;return 0;
}
输出结果
hello Linux//使用对象中的subpos位置开始的sublen长度的字符串替换调用对象pos位置开始的len长度的字符串
#include iostream
using namespace std;int main()
{string s1 hello world;string s2 hello CPP;s1.replace(6, 3, s2, 6, 3);cout s1 endl;s1.replace(6, 5, s2, 6, 3);cout s1 endl;return 0;
}
输出结果
hello CPPld
hello CPP//使用字符串s替换调用对象pos位置开始的len长度的字符串
#include iostream
using namespace std;int main()
{string s1 hello world;s1.replace(6, 3, Linux);cout s1 endl;return 0;
}
输出结果
hello Linuxld//使用字符串中的n个字符替换调用对象pos位置开始的len长度的字符串
#include iostream
using namespace std;int main()
{string s1 hello world;s1.replace(6, 3, Linux, 3);cout s1 endl;return 0;
}
输出结果
hello Linld//使用n个字符替换调用对象pos位置开始的len长度的字符串
#include iostream
using namespace std;int main()
{string s1 hello world;s1.replace(6, 5, 5, c);cout s1 endl;return 0;
}
输出结果
hello ccccc find()函数 使用fine()函数可以在string对象中从前往后找某一个字符或者字符串 函数 函数原型 string() size_t find (const string str, size_t pos 0) const; 在调用对象的字符串中从pos位置开始找出现对象字符串的开始位置 size_t find (const char* s, size_t pos 0) const; 在调用对象的字符串中从pos位置找出出现字符串的开始位置 size_t find (const char* s, size_t pos, size_t n) const; 在调用对象的字符串中从pos位置开始找字符串s中的n个字符的开始位置 size_t find (char c, size_t pos 0) const; 在调用对象的字符串中从pos位置开始找字符c的开始位置 //在调用对象的字符串中从pos位置开始找出现对象字符串的开始位置
#include iostream
using namespace std;int main()
{string s1 This is a test string: hello world.;string s2 test;size_t index s1.find(s2);cout index endl;return 0;
}
输出结果
10//在调用对象的字符串中从pos位置找出出现字符串的开始位置
#include iostream
using namespace std;int main()
{string s1 This is a test string: hello world.;size_t pos s1.find(is);while (pos ! string::npos){cout pos endl;pos s1.find(is, pos 1);//注意1更改pos位置防止死循环}return 0;
}
输出结果
2
5//在调用对象的字符串中从pos位置开始找字符串s中的n个字符的开始位置
#include iostream
using namespace std;int main()
{string s1 this is a test string: hello world.;size_t pos s1.find(this is a test string, 0, 1);while (pos ! string::npos){cout pos ;pos s1.find(this is a test string, pos 1, 1);}return 0;
}
输出结果
0 10 13 16//在调用对象的字符串中从pos位置开始找字符c的开始位置
//替换对象的字符串中的空格为--
#include iostream
using namespace std;int main()
{string s1 this is a test string: hello world.;size_t pos s1.find( );while (pos ! string :: npos){s1.replace(pos, 1, --);pos s1.find( );//因为替换了空格所以每一次从头找时不会死循环}cout s1 endl;return 0;
}
输出结果
this--is--a--test--string:--hello--world. 针对第三个题目做出的一点优化包含之前的接口函数的使用 第一种优化 #include iostream
using namespace std;int main()
{string s1 this is a test string: hello world.;size_t pos s1.find( );//第一优化思路提前开辟足够大小的空间避免replace的扩容//统计空格的个数int count 0;for (auto ptr : s1){if (ptr ){count;}}s1.reserve(s1.size() count);//因为替换的字符由两个去掉替换的空格的位置之后多出来的空间即为需要的额外空间while (pos ! string::npos){s1.replace(pos, 1, --);pos s1.find( , pos 2);//第二优化思路因为空格被替换为了--为了使pos指向下一个要找的位置//直接让pos跳过替换字符个数个下标}cout s1 endl;return 0;
}
输出结果
this--is--a--test--string:--hello--world. 第二种优化思路以空间换时间 #include iostream
using namespace std;int main()
{string s1 this is a test string: hello world.;string newString;for (auto ptr : s1){if (ptr ! ){newString ptr;}else{newString --;}}cout newString endl;return 0;
}
输出结果
this--is--a--test--string:--hello--world. swap()函数 使用swap()函数可以交换调用对象的字符串和另一个对象中的字符串 对于任意类型标准库中还有个全局函数swap()对比于string类中的swap()来说类string中的swap()函数执行效率会被全局函数swap()效率更高因为全局的swap()函数在拷贝过程中会调用对应对象类的拷贝构造函数此时会有额外的空间和时间消耗 全局函数swap()定义 在前面推测过字符串存储的位置可能是数组或者指针但是不论是那种实际上都是地址只要改变指向两个字符串的指针的指向即可完成交换所以效率会比全局函数的swap()高 函数 函数原型 swap() void swap (string str); #include iostream
using namespace std;int main()
{string s1 hello world;string s2 hello Linux;cout 交换前 s1 endl;cout 交换前 s2 endl;s1.swap(s2);cout 交换后 s1 endl;cout 交换后 s2 endl;return 0;
}
输出结果
交换前hello world
交换前hello Linux
交换后hello Linux
交换后hello world c_str()函数 使用c_str()函数可以按照C语言字符串的形式返回调用对象中的字符串 函数 函数原型 c_str() const char* c_str() const; #include iostream
using namespace std;int main()
{string s1(hello world);s1 \0;s1 \0;s1 -----;//s1 --\0----;//注意这样子写编译器会认为是\0字符串的终止后面内容不会读入cout s1 endl;//调用重载的operator函数打印自定义类型cout s1.c_str() endl;//使用内置打印按照size的大小打印cout (void*)s1.c_str() endl;//打印字符串所在地址找\0结束return 0;
}
输出结果
hello world-----
hello world
0000016D82281D70 使用场景 //打开文件
#include iostream
#include cassert
using namespace std;int main()
{string filename text.txt;FILE* fout fopen(filename.c_str(), w);assert(fout);return 0;
} substr()函数 使用substr()函数可以截取字符串中的某一部分字符串作为子字符串返回 函数 函数原型 subStr() string substr (size_t pos 0, size_t len npos) const; //找文件的后缀名
#include iostream
using namespace std;int main()
{string s1 text.txt;//先找到后缀点size_t pos s1.find(.);//再取pos位置开始的字符到结尾string suffix s1.substr(pos);cout suffix endl;return 0;
}
输出结果
.txt//找网站域名
#include iostream
using namespace std;int main()
{string s1 https://blog.csdn.net/m0_73281594?spm1010.2135.3001.5343;//首先跳过网站协议部分size_t pos s1.find(//);//再找网站第二个/size_t pos1 s1.find(/, pos 2);//取域名string web s1.substr(pos 2, pos1 - (pos 2));cout web endl;return 0;
}
输出结果
blog.csdn.net rfind()函数 使用rfinde()函数可以从字符串的最后一个字符向前找指定字符或字符串 函数 函数原型与find()类似 rfind() size_t rfind (const string str, size_t pos npos) const; size_t rfind (const char* s, size_t pos npos) const; size_t rfind (const char* s, size_t pos, size_t n) const; size_t rfind (char c, size_t pos npos) const; //使用rfind()函数优化找文件后缀
#include iostream
using namespace std;int main()
{string s1 test.txt.tar.zip;//找最后一个后缀点位置size_t pos s1.rfind(.);//取pos位置开始到结尾的字符串string suffix s1.substr(pos);cout suffix endl;return 0;
}
输出结果
.zip find_first_of()函数 使用find_first_of()函数可以在对象字符串中匹配指定字符串中的内容 函数 函数原型 find_first_of() size_t find_first_of (const string str, size_t pos 0) const; 从pos位置开始在调用对象的字符串中匹配对象的字符串中的字符 size_t find_first_of (const char* s, size_t pos 0) const; 从pos位置开始在调用对象的字符串中匹配字符串中的字符 size_t find_first_of (const char* s, size_t pos, size_t n) const; 从pos位置开始在调用对象的字符串中匹配字符串中n位置之前的字符串的字符 size_t find_first_of (char c, size_t pos 0) const; 从pos位置开始在调用对象的字符串中匹配字符c //从pos位置开始在调用对象的字符串中匹配对象的字符串中的字符
//返回aeiou五个字符在字符串中出现的下标位置
#include iostream
using namespace std;int main()
{string s1 this is a test string: hello world.;string s2 aeiou;size_t index[50] {0};size_t count 0;int i 0;while (count ! string::npos){count s1.find_first_of(s2, count 1);index[i] count;}for (auto num : index){if (num ! 0 num ! string::npos){cout num ;}}return 0;
}
输出结果
2 5 8 11 18 24 27 30//从pos位置开始在调用对象的字符串中匹配字符串中的n个字符
#include iostream
using namespace std;int main()
{string s1 this is a test string: hello world.;size_t index[50] { 0 };size_t count 0;int i 0;while (count ! string::npos){count s1.find_first_of(iscpp, count 1, 2);index[i] count;}for (auto num : index){if (num ! 0 num ! string::npos){cout num ;}}return 0;
}
输出结果
2 3 5 6 12 15 18 同样的函数还有 find_last_of()函数在字符串中匹配指定字符串的字符最后一次在原始字符串中的位置find_first_not_of()函数在字符串中找出指定字符串中不存在的字符第一次出现的位置find_last_not_of()函数在字符串中找出指定字符串中不存在的字符最后一次在原始字符串中的位置 relational operators系列函数 比较字符串之间关系的运算符底层调用compare()函数 函数 函数原型 operator() bool operator (const string lhs, const string rhs);bool operator (const char* lhs, const string rhs);bool operator (const string lhs, const char* rhs); 判断两个字符串/对象的字符串是否相等 operator!() bool operator! (const string lhs, const string rhs); bool operator! (const char* lhs, const string rhs); bool operator! (const string lhs, const char* rhs); 判断两个字符串/对象的字符串是否不相等 operator() bool operator (const string lhs, const string rhs);bool operator (const char* lhs, const string rhs);bool operator (const string lhs, const char* rhs); 判断第一个字符串/对象的字符串是否小于第二个字符串/对象的字符串 operator() bool operator (const string lhs, const string rhs); bool operator (const char* lhs, const string rhs); bool operator (const string lhs, const char* rhs); 判断第一个字符串/对象的字符串是否小于等于第二个字符串/对象的字符串 operator() bool operator (const string lhs, const string rhs); bool operator (const char* lhs, const string rhs); bool operator (const string lhs, const char* rhs); 判断第一个字符串/对象的字符串是否大于第二个字符串/对象的字符串 operator() bool operator (const string lhs, const string rhs); bool operator (const char* lhs, const string rhs); bool operator (const string lhs, const char* rhs); 判断第一个字符串/对象的字符串是否大于等于第二个字符串/对象的字符串 getline()函数 使用getline()函数可以获取到指定字符默认\n结尾之前的字符串 不同于cincin遇到空白字符时就会停止读入getline()函数遇到\n或者指定字符才结束 函数 函数原型 getline() istream getline (istream is, string str, char delim); 获取以字符delim结尾之前的字符串放入对象str中 istream getline (istream is, string str); 获取以字符\n结尾之前的字符串放入对象str中 #include iostream
#include string
using namespace std;int main()
{string s1;string s2;getline(cin, s1);cin s2;cout s1 endl;cout s2 endl;return 0;
}
输入
hello world[Enter]
hello world[Enter]
输出结果
hello world
hello 使用getline()函数需要包头文件string getline()函数的使用练习字符串最后一个单词的长度_牛客题霸_牛客网 (nowcoder.com) 参考代码 #include cstddef
#include iostream
#include string
using namespace std;int main() {string str;getline(cin, str);//倒着找空格size_t pos str.rfind( );//取出字符if(pos ! string::npos){string str1 str.substr(pos);cout str1.size() - 1 endl;}else{cout str.size() endl;}
} string类对象的访问及遍历操作 函数 功能 operator[] 返回pos位置的字符const string类对象调用 beginend begin获取一个字符的迭代器 end获取最后一个字符下一个位置的迭代器 范围for C11支持更简洁的范围for的新遍历方式 at() 访问字符串中指定位置的字符 注意迭代器中的end为最后一个字符的下一个位置一般指向\0形成左闭右开区间 #include iostream
using namespace std;int main()
{string s hello world;//下标遍历for (size_t i 0; i s.size(); i){cout s[i] ;}cout endl;//迭代器遍历//获取起始地址for (string::iterator ptr s.begin(); ptr ! s.end(); ptr){cout *ptr -;}cout endl;//范围forfor (auto ptr : s){cout ptr *;}cout endl;//at()函数for (int i 0; i s1.size(); i){cout s1.at(i) ;}return 0;
}
输出结果
h e l l o w o r l d
h-e-l-l-o- -w-o-r-l-d-
h*e*l*l*o* *w*o*r*l*d*
h e l l o w o r l d 在上面的代码中是使用了三种遍历字符串的方式但是实际上常用的方式为下标访问的方式并且范围for的本质也是迭代器auto ptr本质就是调用s.begin()函数给string : iterator ptrs的本质即为s.end()通过汇编代码可以验证这一点 直接使用迭代器 范围for operator[]与at()函数 对于string类来说可以使用下标进行访问 #include iostream
using namespace std;int main()
{string s hello world;//下标遍历for (size_t i 0; i s.size(); i){cout s[i] ;}cout endl;//at()函数for (int i 0; i s1.size(); i){cout s1.at(i) ;}return 0;
}
输出结果
h e l l o w o r l d
h e l l o w o r l d operator[]和at()函数均可以使用下标的形式访问字符串但是at()函数可以在对字符串进行越界访问时抛出异常而不是像operator[]越界访问一样断言终止程序 //operator[]
#include iostream
using namespace std;int main()
{string s1 hello world;cout s1[100] endl;return 0;
} operator[]越界访问断言报错 #include iostream
using namespace std;int main()
{string s1 hello world;try{//使用try_catch捕获越界访问异常cout s1.at(100) endl;}catch (const exception e){cout e.what() endl;}return 0;
}
输出结果
invalid string position string类迭代器遍历 正向遍历 使用begin和end可以从前往后遍历字符串使用迭代器iterator 函数 函数原型 begin() iterator begin();针对于普通对象 const_iterator begin() const;针对于const对象 end() iterator end();针对于普通对象 const_iterator end() const;针对于const对象 #include iostream
using namespace std;int main()
{string s1 hello world;string::iterator ptr s1.begin();while (ptr ! s1.end()){cout *ptr ;ptr;}return 0;
}
输出结果
h e l l o w o r l d 在上面的代码中因为begin()和end()均返回iterator所以迭代器类型需要选择iterator 对于const对象来说需要使用const类型的迭代器 #include iostream
using namespace std;int main()
{const string s2 hello world;string::const_iterator cptr s2.begin();while (cptr ! s2.end()){cout *cptr ;cptr;}
}
输出结果
h e l l o w o r l d 在上面的代码中使用了const类型的迭代器但是注意该迭代器对于指针来说只是修饰指针指向的内容不可以修改但是指针可以改变指向 对于const修饰的迭代器来说还可以使用cbegin()和cend() 逆向遍历 使用rbegin和rend可以从后往前遍历字符串此时使用的迭代器为reverse_iterator 函数 函数原型 rbegin() reverse_iterator rbegin();针对普通对象 const_reverse_iterator rbegin() const;针对const对象 rend() reverse_iterator rend();针对普通对象 const_reverse_iterator rend() const;针对const对象 #include iostream
using namespace std;int main()
{string s1 hello world;string::reverse_iterator ptr1 s1.rbegin();while (ptr1 ! s1.rend()){cout *ptr1 ;ptr1;}return 0;
} 在上面的代码中使用rbegin()和rend()返回类型为reverse iterator故迭代器类型需要选择reverse_iterator 注意此时ptr1并不是--而是因为此时的rbegin为字符串最后一个有效字符的前一个位置而rend为字符串第一个有效字符的前一个位置形成左闭右开 当使用迭代器的对象为const修饰时迭代器需要同样使用const修饰的迭代器 #include iostream
using namespace std;int main()
{string::const_reverse_iterator cptr1 s2.rbegin();while (cptr1 ! s2.rend()){cout *cptr1 ;cptr1;}return 0;
}
输出结果
d l r o w o l l e h 在上面的代码中使用了const类型的迭代器但是注意该迭代器对于指针来说只是修饰指针指向的内容不可以修改但是指针可以改变指向 对于const修饰的迭代器来说还可以使用crbegin()和crend()