当前位置: 首页 > news >正文

企业网站制作模板网页制作模板源代码免费

企业网站制作模板,网页制作模板源代码免费,台州网站制作系统分析怎么写,东营网站制作公司层楼终究误少年#xff0c;自由早晚乱余生。你我山前没相见#xff0c;山后别相逢… 文章目录一、编码#xff08;ascll、unicode字符集、常用的utf-8编码规则、GBK#xff09;1.详谈各种编码规则2.汉字在不同的编码规则中所占字节数二、string类的基本使用1.string类的本质…层楼终究误少年自由早晚乱余生。你我山前没相见山后别相逢… 文章目录一、编码ascll、unicode字符集、常用的utf-8编码规则、GBK1.详谈各种编码规则2.汉字在不同的编码规则中所占字节数二、string类的基本使用1.string类的本质管理字符的动态顺序表2.string类对象的常见构造3.三种遍历string类对象的操作3.1 [ ] 下标operator[ ]的重载函数3.2 基于范围的for循环C11新增特性auto自动类型推导3.3 迭代器正向、反向、const正向、const反向3.4 类中哪些函数需要实现两个版本哪些不需要呢4.string类对象的容量操作reserve( ):对比vs和g对于扩容采取策略的差异5.string类对象的元素访问6.string类对象的修改操作operator 才是yyds7.string类对象的字符串操作String operations8.string类的非成员函数重载一、编码ascll、unicode字符集、常用的utf-8编码规则、GBK 1.详谈各种编码规则 ASCII码表里的字符总共有多少个?转载自百度知道博主教育达人小李的文章 百度百科统一码Unicode 百度百科UTF-8编码 UTF-8兼容ascll编码linux下默认使用的就是UTF-8的编码方式。 百度百科GBK字库 vs编译器默认使用的编码方式是GB2312编码。 下面这篇文章写的非常不错十分推荐大家看看。我的建议是搞懂UTF-8的编码规则即可UTF-16和32不常用所以掌握UTF-8的编码原理就足够了因为这些知识只要了解即可知道有这么回事就行不必过于细究。 Unicode、UTF-8、UTF-16 终于懂了转载自知乎博主程序员十三的文章 2.汉字在不同的编码规则中所占字节数 utf-8中的汉字占用多少字节转载自博客园博主醉人的文章 我的vs编译器默认的编码规则就是GB2312编码字母和数字都是一个字节汉字占用2个字节。 各种编码的中文占用几个字节Unicode、ISO 10646、UTF-8、GB-2312、GBK的区别是什么转载自csdn博主天上的云川的文章 字符编码ASCII,GB2312,GBK,Unicode,UTF-8转载自知乎博主sunny的文章 二、string类的基本使用 1.string类的本质管理字符的动态顺序表 1. 最常用的类就是string这些类都是基于类模板basic_string由于类模板参char16_t、char32_t、wchar_t、的不同实例化出对应不同需求的类例如u16stringu32stringwstring。 我应该用std::string、std::u16string还是std::u32string转载自知乎博主王万霖的文章 2. 最常用的类就是string实际上string就是我们数据结构初阶学习的动态顺序表在理解上只需要将其看成一个动态开辟的柔性数组即可。 动态增长的字符数组string可以看成是一个管理字符的顺序表 templateclass T class my_basic_string {private:T* _str;size_t _size;size_t _capacity; }; typedef my_basic_stringchar string;//存UTF-8的所以模板参数传char。如果是UTF-16那就传char16_t。2.string类对象的常见构造 1. string的constructor构造函数里面重载了许多的string类的构造函数其中包括多个构造函数和拷贝构造函数由于第一次学STL所以我们将string这个类讲的细致全面一些以便于了解STL是怎么学习的后面的其他容器包括string实际上只需要掌握常见的重要接口即可遇到其他不常见的接口只需要查询C文献即可。 2. 我们所使用的string类被包含在 string 头文件里面而string头文件的内容又被封装在std命名空间里面大型项目里面建议使用域作用限定符不展开命名空间std但在我们自己平常的学习过程中无需太过繁琐展开std命名空间即可。 3. 最常用的构造函数就是string类默认的无参构造函数和以常量字符串为参数的构造函数。 s2和s3对象的构造结果是一样的只是书写的形式不同s3形式看起来更像赋值重载但他其实是进行了隐式类型转换编译器做了优化本质实际上是构造拷贝构造先根据常量字符串构造出一个string类对象然后再将这个对象拷贝构造给对象s3。 从拷贝构造和赋值重载的定义也可以知道s3是拷贝构造因为赋值重载是已经存在的两个对象之间的赋值而拷贝构造是已经存在的对象去初始化创建另外一个对象对象s3明显不是已经存在的所以s3是拷贝构造编译器在这里会优化为直接构造。 编译器对于拷贝构造的优化 4. 其他可以了解一下的接口还有字符和个数作为参数的构造函数s4即为被10个字符*初始化构造的对象。 string类中重载了函数函数也有三种重载函数形式分别为以常量字符串、string类对象的引用、普通字符为参数的三个运算符重载函数这就可以方便我们将自定义类型当作内置类型使用极大的提高了代码可读性。 string类还重载了流提取和流插入运算符这也可以帮助我们快速的看到string类对象的内容也提升了代码的可读性。 由此可见重载函数和运算符重载真是C的伟大之处。 5. 除构造函数外string类肯定还有拷贝构造默认成员函数常见用法就是用一个已经存在的string类对象拷贝构造出一个新对象例如s5和s6。拷贝构造的另一种写法就是看起来比较像赋值重载但本质和拷贝构造无差别仅仅是代码形式不同而已。 实际上这里还涉及到深拷贝的问题底层实现中在内存里一定是存在两份动态字符数组的如果仅仅是浅拷贝那么在析构的时候会出现同一块内存释放两次的情况这就会导致越界访问已经还给操作系统的内存势必会导致程序崩溃。当然现在我们不需要关心这些问题因为string类已经有人帮我们写好了但如果我们自己实现时就需要考虑这样的问题了。后面我们会自己模拟实现string类。 还有一种适当了解的构造函数形式就是常量字符串和字符串的前n个字符作为参数的构造的重载函数例如s7我用计算机网络的前6个字符来构造对象s7因为vs默认的编码规则是GB2312所以s7的内容就是计算机。 6. 还有一种拷贝构造的重载形式就是从pos位置开始横跨我们指定的字符长度用str串的子串来进行构造新的string类对象并且这个重载函数的参数是半缺省参数按照从右向左连续缺省的原则这个参数就是npos默认值是-1但是类型是size_t无符号整型也就是unsigned int所以这个值实际上就是四十二亿九千万多那就意味着如果我们不指定len的大小则构造对象时默认使用的是从pos位置开始直到str的结尾的字串。 如果len的指定大小过大超出str的字符长度则以str的末尾作为结束标志如果指定过小则舍去相应的字符即可。 7.上面说了这么多重载函数的用法但只要重点掌握三个函数即可即为无参常量字符串等参数的构造函数和类对象引用作为参数的拷贝构造。 注意拷贝构造的参数必须是类对象的引用否则将引发无穷递归调用疯狂建立拷贝构造的函数栈帧。 #include iostream #include string #include vector #include list using namespace std;//库文件string的内容也是被封装在std命名空间里面的。 void test_string1() {string s1;string s2(今天是个);//传参构造string s3 操作系统;//这里支持隐式类型转换因为string类的拷贝构造函数没有explicit修饰构造 拷贝构造 直接优化为构造。//上面代码看起来像是赋值重载但实际上是构造拷贝构造编译器在这个地方会做优化。详情见文章类和对象核心总结编译器的优化string s4(10, *);s2 好日子;//运算符重载的本质实际上是在堆上有一个数组这个数组是动态开辟的。cout s1 endl;//string类当中支持了流插入运算符重载。所以我们可以将自定义类型当作内置类型使用。cout s2 endl;cout s3 endl;cout s4 endl;string s5(s3);//拷贝构造string s6 s3;//这个也是拷贝构造只不过写法不一样。//这里的拷贝构造涉及深拷贝的问题因为两个指针指向同一数组在释放时会出现越界访问已经还给操作系统的内存。cout s5 s6 endl;string s7(计算机网络, 6);//GBK编码中汉字占2字节utf8汉字占用3字节或4字节。cout s7 endl;string s8(s7, 0);//参数案例:4、3、30、最后一个参数不给函数也有缺省值npos这个npos是类里面声明的静态成员变量定义在类外面。//static const size_t npos -1;size_t修饰的无符号整型的-1是四十二亿九千万大小所以可以直接看成取到字符串的末尾。//从第0个位置开始走4个字节的长度那么s8就是计算。如果走3字节长度则s8就是计。如果长度过大到达末尾即结束。cout s8 endl;//****只需重点了解无参常量字符串等参数的构造函数和类对象引用作为参数的拷贝构造稍微知道字符和字符个数做参的构造函数即可**** }3.三种遍历string类对象的操作 3.1 [ ] 下标operator[ ]的重载函数 1. 如果我们现在遇到一个需求让对象s1里面的每个字符的ascll码值都1那我们势必要对对象s1进行遍历操作这个时候就可以用到operator[ ]string类中给我们实现了两个版本一个用于普通对象表示可以修改和访问string类对象的内容。另一个用于const修饰的对象表示只能访问string类对象内容不可以修改。 这两个版本的返回值是相同的都是返回string类对象的字符的引用。利用普通版本便可以遍历操作对象s1中的每一个字符并进行修改。 2. size()函数返回有效字符的个数不包括\0\0是标识字符。 void test_string2() {string s1(1234);//需求:让对象s1里面的每个字符都加1//如果要让字符串的每个字符都加1肯定离不开遍历下面学习三种遍历string的方式。//1.下标 []for (size_t i 0; i s1.size(); i){s1[i];//本质上}cout s1 endl;//GB2312兼容ascll编码所以后的结果为2345. }3.2 基于范围的for循环C11新增特性auto自动类型推导 1. C11新特性auto自动类型推导在基于范围的for循环情况下可以使用auto引用来操作数组s1里面的每个元素。 void test_string2() {//2.范围forfor (auto ch : s1)//自动推导s1数组的每个元素后用元素的引用作为迭代变量通过引用达到修改s1数组元素的目的。{ch;}cout s1 endl;//在上面这种需求下范围for看起来似乎更为方便 }2. 但在将需求改为翻转字符串之后基于范围的for循环就不适用了而下标加方括号的方式还可以使用并且交换函数也不用我们实现std命名空间里面有函数模板swap通过我们所传参数函数模板便可以进行隐式的实例化。 函数模板的两种实例化方式隐式和显示实例化 3. 对于翻转我们还可以使用reverse算法和迭代器来实现这个放到以后的文章去讲现在只是提一下有个印象就好。 //新需求:反转一下字符串。size_t begin 0, end s1.size() - 1;//有效字符是不包含\0的所以end下标要再往前挪动一个位置。//\0不是有效字符而是标识字符。while (begin end)//begin和end相等的时候不用交换了{swap(s1[begin], s1[end--]);//利用库函数swap}cout s1 endl;reverse(s1.begin(), s1.end());//reverse算法和迭代器后面会讲到这里只是提一下cout s1 endl;3.3 迭代器正向、反向、const正向、const反向 1. 迭代器实际上具有普适性对于大多数容器都可以适用而[ ]下标这样的使用方式只对于vector和string适用后面学习到的list、树等就不适用了而迭代器由于其强大的普适性依旧可以适用这也正是迭代器学习的意义。 2. 迭代器在使用的方式和行为上比较像指针但是它和指针还是有区别的它既有可能是指针又有可能不是指针。在定义时要指定类域譬如it1的定义就需要指定类域里面的iterator类型begin()会返回获取第一个字符的迭代器end()会返回最后一个字符下一个位置的迭代器一般情况下就是标识字符\0其实在使用上就是类似于指针解引用迭代器就可以获得相应的字符然后就可以对字符进行操作从下面代码可以看出it1不仅可以访问而且还可以修改对象s1的内容。并且除string外vector和list也可以照常使用iterator这也验证了iterator的普适性。 void test_string2() {//3.迭代器:通用的访问形式 iterators --- 行为上像指针一样的东西有可能是指针也有可能不是指针string::iterator it1 s1.begin();// string类域里面的迭代器iterator类型定义出it1迭代器变量。while (it1!s1.end())//end返回的是最后一个有效数据的下一个位置一般情况下是\0{*it1 1;it1;}it1 s1.begin();while (it1 ! s1.end())//end返回的是最后一个数据的下一个位置的迭代器{cout *it1 ;it1;}cout endl;vectorint v;vectorint::iterator vit v.begin();while (vit ! v.end()){cout *vit ;vit;}cout endl;listint lt;listint::iterator ltit lt.begin();while (ltit ! lt.end()){cout *ltit ;ltit;}cout endl;//****只有string和vector这两个容器能用[]后面的list、树等容器就不支持[]了。**** }3. 除begin()和end()外还有rbegin()和rend()前面两个返回的是正向迭代器后面这两个返回的是相应字符的反向迭代器也就是从末尾开始到开头结束和正常的方向反过来在使用上和正向迭代器没有任何区别。 如果嫌string::reverse_iterator 写起来比较麻烦的话可以用auto来进行类型的自动推导但不建议这么干因为这会降低代码的可读性。 4. 实现Print函数时参数采用了引用和const因为传值拷贝需要中间变量一旦涉及资源的传递则代价会非常大堆上需要重新给中间变量开辟空间所以我们采用了传引用拷贝。但如果你用普通的迭代器类型接收begin()返回的字符迭代器实际上会报错仔细观察报错信息就会发现是const和非const之间无法转换这实际上就是因为对象s被用const修饰所以begin()返回的是const迭代器类型而你用普通的迭代器接收就会出现无法正常转换的问题所以需要用string::const_iterator来接收。 5. const迭代器的内容只支持读不支持修改非const迭代器的内容既可以读也可以修改。对于begin()end()rbegin()rend()他们每个函数都实现了两个版本一个用于普通string对象一个用于const修饰的对象。 6. const修饰的是迭代器的内容而不是迭代器本身。相当于const修饰的是指针指向的内容而不是指针本身。 //迭代器分类 //正向 反向 --- 普通对象可以遍历读写容器数据 //const正向 const反向 --- const修饰对象只能遍历读不能修改容器数据。void Print(const string s)//涉及深拷贝时用传值拷贝代价非常大需要在堆上重新开一份空间所以我们用传引用拷贝并加const修饰。 {//普通迭代器的内容支持读和写无论是正向还是反向迭代器。//const迭代器的内容仅仅支持遍历读而不支持写。string::const_iterator cit s.begin();//普通迭代器编译无法通过因为const修饰的对象s里的begin返回时需要用const迭代器来接收。//const修饰的是迭代器变量所指向的内容相似于指针指向的内容而不是修饰迭代器本身也就是指针本身因为迭代器需要向后遍历。while (cit ! s.end()){//*it 1;cout *cit ;cit;}cout endl;//string::const_reverse_iterator rcit s.rbegin();auto rcit s.rbegin();//如果嫌长可以用auto推导一下。因为s是const修饰rbegin又代表反向迭代器auto能推导出来类型。while (rcit ! s.rend()){cout *rcit ;rcit;}cout endl; } void test_string3() {string s1(1234);string::iterator it s1.begin();//正向迭代器while (it ! s1.end()){cout *it ;it;}cout endl;//string::reverse_iterator rit s1.rbegin();//反向迭代器auto rit s1.rbegin();//auto用于类型的自动推导rbegin()返回的是反向迭代器。while (rit ! s1.rend()){cout *rit ;rit;}cout endl;Print(s1); }7. 在C11中iterators新添了4个版本的函数在原来的4个版本上加了前缀c表示这四个版本的函数针对于const修饰的对象所使用但实际上这是多此一举没啥用原来的四个版本完全够使用了可能有的人类和对象重载函数等知识没学好搞不清什么时候调用const版本什么时候调用非const版本。 3.4 类中哪些函数需要实现两个版本哪些不需要呢 1. 在迭代器部分可以看到C98标准的4个函数都实现了两个版本const和非const所以只要修改数据的函数就应该实现两个版本这是否正确呢 2. 从push_back只实现了一个版本就可以看出上面的推论实际是不正确的其实是否需要实现两个版本要看函数的具体功能是什么。 push_back肯定不具有读的功能所以只需要实现非const版本即可。而那些迭代器既有可能读又有可能写所以那些函数具有读写功能需要实现两个版本。 4.string类对象的容量操作reserve( ):对比vs和g对于扩容采取策略的差异 1. length()和size()返回的大小都是容器有效字符的个数但为什么会出现两个功能相同的函数呢这其实是因为某些历史原因C只能向前兼容原本length()是比较适用于string类的但是用在其他的类上就有些奇怪比如树树的长度怪不怪所以为了增强普适性增加了size()来表示各个容器的大小这样就舒服很多了。 2. clear()用于抹去容器中的数据但内存空间是不会释放的从clear()之后调用的capacity的结果可以看到内存上开辟的空间是没有释放的但size会被置为0所以在打印s时的结果为空。 void test_string4() {string s(hello world);cout s.length() endl;//早期就是叫做length而不是sizecout s.size() endl;//为了容器的普适性用size更好一点因为哈希表、树等容器叫做length不太好叫size更好一些。//所以后面用size更舒服一些容器的大小。cout s.capacity() endl;//空间满了就扩容和数据结构里的动态顺序表很相似。cout s.max_size() endl;//max_size是写死的具体大小看编译器的底层实现我的编译器是四十二亿九千万的一半。string ss;cout ss.max_size() endl;//这是个垃圾函数不需要我们关心。cout s endl;cout s.capacity() endl;s.clear();//clear是否释放s字符数组的空间是不确定的因为不同的编译器采用的STL版本是不同的底层实现上有区别。cout s endl;cout s.size() endl;cout s.capacity();//通过capacity函数的返回值我们可以知道vs编译器下的clear是不会释放字符串对象s的空间的。 }3. 下面的代码可以帮助我们看到在容器空间大小不够时vs编译器对于扩容采取的具体策略将这段代码放到linux的g编译器下我们也可以看到g对于扩容采取的具体策略。 4. 从上面可以看到两个编译器进行扩容的过程但我们知道扩容的代价实际上是非常大的因为异地扩容还需要进行原来数据的拷贝会降低程序的效率所以能不能在已知空间大小的情况下一次性提前开辟好呢避免多次的扩容造成的效率降低。 这个时候可以使用reserve()接口来提前指定好capacity的大小一次就开辟好对应大小的空间为字符串预留好空间。 由于对齐因素vs编译器底层实际开辟的空间要稍微大一些。 void TestPushBack() {string s;s.reserve(1000);//reserve的价值就是在已知插入数据的个数前提下提前开辟好一份空间避免开始时多次的扩容导致的效率降低。//在已知容器所需最大空间的情况下我们实际可以提前开好最大空间这样就不需要扩容了因为扩容的代价很大尤其是异地扩容。//但是capacity()接口是只读的不可被修改所以通过capacity接口来指定容器的最大空间是不行的这个时候就可以使用接口reserve来指定。//vs由于对齐会将扩容的空间开辟的比我们显示的要大一些这是因为内存对齐原则后面学习到内存池的空间配置器时就知道为什么对齐了//提前预留的空间不够时push_back还是会自动扩容的继续扩大capacity的值我们不用担心。size_t sz s.capacity();cout capacity changed: sz \n;cout making s grow:\n;for (int i 0; i 1000; i){s.push_back(c);if (sz ! s.capacity()){sz s.capacity();cout capacity changed: sz \n;}} } void test_string5() {TestPushBack(); }5. reserve()改变容器的capacityresize()改变容器的size对于字符串hello world来说传参n的大小对应了resize有三种情况。 void test_string6() {string s1(hello world);s1.resize(5);//删除数据只保留前5个字符后面的字符是都被替换为\0还是仅仅替换第6个字符为\0是不重要的这取决于编译器的实现者。 cout s1.size() endl;cout s1.capacity() endl;cout s1 endl endl;string s2(hello world);s2.resize(15,x);//插入数据如果不指定字符c则默认用空字符\0来填充。cout s2.size() endl;cout s2.capacity() endl;cout s2 endl endl;string s3(hello world);s3.resize(20,x);//发生扩容capacity会改变。cout s3.size() endl;cout s3.capacity() endl;cout s3 endl endl;}6. C11新引进的shrink_to_fit()函数用于将capacity减少到和size相等 5.string类对象的元素访问 1. operator[]和at的作用一致都是返回动态顺序表某一位置的字符。 但发生越界访问时operator[]采用assert断言报错的方式进行解决而at会抛异常。 2. C11引入的back和front用于返回动态数组的首尾元素但这两个函数实际上不怎么常用因为operator[0]和operator[s.size()-1]便可以取到顺序表的首尾元素。 6.string类对象的修改操作operator 才是yyds 1. push_back()用于单个字符的尾插如果要向容器中增加字符串的话利用push_back()的效率就非常低因为我们需要一个一个字符的尾插。 2. append函数重载实际和我们的构造函数非常的相似就好比你在路上碰到一个姑娘你觉得她非常的眼熟你焦急的跑过去看她的脸庞结果发现她竟和你的初恋长的一模一样你满怀期待的细细询问发现此女子并非当初的那个她仅仅只是模样十分相似罢了你心灰意冷的走开逐渐开始回味你们美好的当初但一切好似黄粱一梦终散为烟…… 黄昏里你又踏上了孤独的旅途终究还是要回到路上… append就是那个姑娘构造函数就是你的初恋。append最常用的接口依旧是参数为常量字符串其他接口含义这里不做介绍因为与前面所讲的构造函数十分相似。 3. operator是非常好用的string类对象修改操作函数运算符重载帮助我们使用自定义类型在形式上十分像使用内置类型这极大的提升了代码的可读性堪称string类对象修改函数的yyds其重载函数有三种形式分别是常量字符串string类对象的引用char型字符c。 void test_string7() {/*string s1(hello world );//函数重载的强大s1.push_back(x);s1.push_back(x);s1.append( hello linux);cout s1 endl;string s2( hello C);s1.append(s2);cout s1 endl;*/string s1(hello world );//运算符重载的强大s1 !;s1 hello windows;cout s1 endl;string s2( hello C);s1 s2;cout s1 endl; } 4. insert和erase用于在数组的某个具体位置插入或删除字符但对于string类不建议使用insert和erase因为我们知道对于顺序表string类对象来说发生插入和删除数组中某个数据时要进行其他数据的挪动代价非常大所以不到万不得已不要轻易的使用这两个函数。 erase有自己的缺省值如果我们用缺省值那就是npos-1的补码也就是全1全1被当作无符号整型处理将会非常大所以如果不给erase指定删除字符的个数则会从指定位置pos处后面的所有字符进行删除。 void test_string8() {string s(hello world);s.insert(0, wyn);//头部插入要挪动数据效率不好频繁头插会降低效率。cout s endl;s.erase(0, 3);cout s endl;s.erase(5, 100);//给的数字过大则有多少删多少。cout s endl;s.erase(0);//npos默认值是二十一亿多所以直接删完。-1存的是补码也就是全1全1看作无符号整数就会非常大。cout s; }5. assign用于将原有字符串用新的字符串进行替代参数格式与构造函数也非常的相似assign实际上对比的是赋值重载因为赋值重载只能将一个字符串完整的赋值给另一个字符串而assign不仅可以操作完整的字符串字符串的substr也可以进行操作例如代码中我用了hello wyn lalala的前9个字符取代了原来的字符串s1. replace与assign不同的是replace进行的不是整体字符串的替代而是字符串中部分字符的替换。例如下面代码中的s2的前5个字符被替换为hi 6. 以前在学习C语言时比较常见的一道题是将字符串中的空格替换为类似于20%这样的字符串在C语言阶段由于原地替换的代价较大我们一般会采用重新开辟一块数组然后从前向后遍历字符串将每个字符尾插到新的数组里面遇到空格时就将20%分开尾插到新数组里面直到字符串遍历结束。 在C阶段中这样的问题就显得比较简单了因为我们有库提供的string我们可以用find接口配合replace接口来进行字符串中空格的替换题目解决起来就简单了许多。 除这样的方法也是可以采用新开辟数组的方式C中只要新创建一个string类对象即可我们用范围for进行遍历循环利用尾插的思想进行空格的替换有operator和范围for的帮助解决起来同样很轻松。 void test_string9() {//assign和replace的功能差别巨大string s1(hello linux and windows);string s2(hello linux and windows);string s3(s2);string s4(s2);//assign对比的是赋值重载赋值重载只能将一个对象完整的赋值给另一个对象assign可以将一个对象的某部分进行赋值。s1.assign(hello wyn lalala,9);cout s1 endl;s2.replace(0, 5, hi);//还是不建议用replace因为他还是要挪动数据导致效率降低。cout s2 endl;//将s3中的所有空格替换为百分号size_t pos s3.find( , 0);while (pos ! string::npos){s3.replace(pos, 1, 20%);//replace的效率非常低pos s3.find( , pos);}cout s3 endl;string ret;ret.reserve(s4.size() 10);//提前开好空间大小避免扩容带来的效率降低for (auto ch : s4){if (ch ! )ret ch;elseret 20%;}cout ret endl;}7.string类对象的字符串操作String operations 1. find和rfind用于进行字符串中某部分字符的查找查找的对象可以是字符string类对象常量字符串等等我们可以指定开始查找的位置等等如果不指定pos则默认从字符串的开头进行查找rfind与find一样只不过rfind会将最后一个字符认定为开始倒着去进行查找有点像reverse_iterator反向迭代器 2. substr可以用来截取字符串中的某一部分并将这一部分重新构造出一个string类对象然后返回需要我们指定开始截取的位置和需要截取的长度如果不指定截取长度则默认从截取位置向后将所有的字符串进行截取因为缺省值是npos. 3. 如果要让我们截取某一字符串的后缀名我们就可以用find和substr配合进行使用截取到字符串的后缀名。 在linux中的文件名后缀有很多组合在一起的所以这时候如果要查找字符’.的位置我们可以从后往前查利用rfind即可做到。 void test_string11() {// Test.cppstring file;cin file;//要求取file的后缀int pos file.find(.);if (pos ! string::npos){//string suffix file.substr(pos, file.size() - pos);//计算.后面的字符有多少string suffix file.substr(pos);//利用缺省值npos作为缺省参数cout suffix endl;}// Test.cpp.zip.tar//要求取file的后缀string file2;cin file2;pos file.rfind(.);if (pos ! string::npos){string suffix file2.substr(pos);cout suffix endl;}}4. c_str用于返回C语言式的字符串类型是常量字符串这个接口的设计主要是为了让C能够和C语言的接口配合起来进行使用。 例如C语言中某些文件操作接口参数要求传字符串这个时候可以用c_str()来实现常量字符串的传参让C和C语言接口能够配合起来进行使用。 data的作用和c_str相同他也是历史遗留下来的接口我们只要用c_str就可以了这个更加常用一些。 void test_string10() {//c_str可以让C更好的兼容C语言data的功能和c_str类似但平常都用c_str。string file(test.cpp);FILE* fp fopen(file.c_str(), r);//r代表常量字符串r代表char型的字符两者的权限是不一样的一个可读可写一个只读。assert(fp);char ch fgetc(fp);while (ch ! EOF){cout ch;ch fgetc(fp);}fclose(fp); }8.string类的非成员函数重载 1. getline是命名空间std封装的一个函数它的作用有点类似于C语言的fgets都是用于获取一行字符串默认的scanf和cin都是以空格和换行符作为字符串的分隔所以当出现含有空格的字符串需要输入时cin就不起作用了getline就派上用场了。 下面这道题就是经典的getline的使用场景题目。 #include iostream #include string using namespace std;int main() {string str;getline(cin,str);int pos str.rfind( );cout str.size() - pos - 1 endl; }2. 下面是string类对象的关系运算符重载函数每一个运算符都重载了三个形式实际上是为了满足多种使用场景。 例如在比较字符串和string类对象时运算符左右两侧的类型由于写法不同导致类型不同则对应的运算符重载为了满足不同的写法就必须实现多个重载函数。 而d110可以支持是因为日期类有自己的类成员函数但如果改成10d1就无法调用对应的函数了因为10抢了类成员函数中this指针的位置。 void test_string12() {string s1(1111111);const char* p2 2222222;p2 s1;s1 p2; }
http://www.w-s-a.com/news/760108/

相关文章:

  • 游戏网站后台建设郑州定制网站
  • 商务公司网站建设网站建设如何自学
  • 现在建网站可以拖拉式的吗中国国内最新新闻
  • phpstorm网站开发产品logo设计
  • 电子商务网站建设与运营什么是单页面网站
  • 西安优化网站公司南阳微信网站
  • 购物网站线下推广方案佛山快速建站哪家服务专业
  • 临沂网站排名外贸网站推广方法之一
  • 手机网站百度关键词排名查询吕梁网站制作吕梁安全
  • 做网站媒体wordpress管理员账号数据库添加
  • php如何自己做网站wordpress怎么修改编辑代码
  • 网站建网站建设公司WordPress互联
  • 泊头市网站建设价格wordpress导航菜单位置
  • 怎么设立网站赚广告费网页制作素材模板图片
  • 做班级网站的目的网站设计制作公司需要什么资质
  • 济南做网站哪家好财政网站平台建设不足
  • php网站建设招聘网站开发与设计论文
  • 上海 网站建设平台 补贴网站开发招标文件范本
  • 延安网站建设公司电话手机上那个网站做农产品推广比较好
  • 增城哪家网站建设好如何做网站实名认证
  • 常州地区做网站个人购物网站需要备案吗
  • 网站建设公司 跨界鱼科技专业做服务器的网站都有哪些
  • 欧洲网站服务器网站建设费用计入什么科目
  • 网站的色调苏州策划网站模板建站公司
  • 怎么看网站用的什么后台公路建设项目可行性研究报告编制办法哪个网站查最新版
  • 可以看的网站的浏览器有哪些专业APP客户端做网站
  • 如何做网站推广自己的产品推荐个网站好吗
  • 网站经营范围wordpress注入点
  • 学校网站开发协议夫妻网络网站建设
  • 福州网站seo推广优化微信商家小程序怎么弄