前言

   学习C语言或者初阶数据结构的时候我们就会发现,C语言虽然简单易懂,但是很多的东西,比如栈、队列、树没有基本的模板进行套用,每次写题还得自己把东西写好才能做题,这太麻烦了!!!

   所以在C语言的基础上,C++诞生了,如果说C语言是造零件在组装成车子,那么C++就是造好了零件,等待我们组装,C++的大佬写出了STL库,我们可以在库中找零件去组装自己的车子啦!!!

   STL我们只需要熟练掌握、会使用即可,相信有了STL的陪伴,站在巨人的肩膀上,我们一定可以变得更强!!!

   所以对于学习c++而言,学好STL是很有必要的。STL统称为:“Standard TemplateLibrary 标准模板库”,STL提供了有六大组件,包括了容器,算法,迭代器,仿函数,适配器以及空间适配器。这篇文章主要是讲解STL容器中的string。

   我们先了解STL标准库的string,然后再用自己的方式去实现string。

目录

  • 前言
  • 一、STL简介(了解即可)
    • 1.什么是STL
    • 2. STL的版本
    • 3. STL的六大组件
    • 4.STL的重要性
    • 5.STL的缺陷
  • 二、标准库中的string类
    • 1.了解string类
    • 2.string类的常用接口说明
    • 3.string类对象的容量操作
    • 4.string类对象的访问及遍历操作
    • 5.string类对象的修改操作
    • 6.string类非成员函数
  • 三、string的模拟实现
    • 1.经典的string类问题
    • 2.浅拷贝/深拷贝
    • 3.string类的模拟实现
  • 四、总结

一、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的六大组件

4.STL的重要性

  网上有句话说:“不懂STL,不要说你会C++”。STL是C++中的优秀作品,有了它的陪伴,许多底层的数据结构以及算法都不需要自己重新造轮子,站在前人的肩膀上,健步如飞的快速开发。

5.STL的缺陷

  1.  STL库的更新太慢了。这个得严重吐槽,上一版靠谱是C++98,中间的C++03基本一些修订。C++11出来已经相隔了13年,STL才进一步更新。
  2.  STL现在都没有支持线程安全。并发环境下需要我们自己加锁。且锁的粒度是比较大的。
  3.  STL极度的追求效率,导致内部比较复杂。比如类型萃取,迭代器萃取。
  4.  STL的使用会有代码膨胀的问题,比如使用vector/vector/vector这样会生成多份代码,当然这是模板语法本身导致的。

二、标准库中的string类

1.了解string类

  1. string是表示字符串的字符串类

  2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。

  3. string在底层实际是:basic_string模板类的别名,typedef basic_string string;

  4. 不能操作多字节或者变长字符的序列。

因为string类在iostream中,所以一般情况下都需要声明,
#include < iostream>;
using namespace std;

2.string类的常用接口说明

在标准库中string有7个接口,这里我们主要讲解和使用4个,后面模拟实现也是模拟我们常用的。

string()

Constructs an empty string, with a length of zero characters

----构造一个长度为零个字符的空字符串。

#include<iostream>
#include <string>
using namespace std;int main()
{string str;//构造空的string类对象s1cout << str << endl;   //输出为空return 0;
}

string(const char* s)

Copies the null-terminated character sequence (C-string) pointed by s.

----复制s指向的以空字符结尾的字符序列(C字符串)

#include<iostream>
#include <string>
using namespace std;int main()
{string str("hello!myfriends!"); cout << str << endl;   //输出为hello!myfriends!return 0;
}

string(size_t n, char c)

Fills the string with n consecutive copies of character c

----用字符c的n个连续副本填充字符串

#include<iostream>
#include <string>
using namespace std;int main()
{string str(6,'y'); cout << str << endl;  //输出为yyyyyyreturn 0;
}

string(const string&s)

Constructs a copy of str.

----构造str的副本。(本质就是拷贝构造,模具构造)

#include<iostream>
#include <string>
using namespace std;int main()
{string str("hello world");string str1(str);  //根据str构造了一个str1cout << str1 << endl;   //输出为hello worldreturn 0;
}

3.string类对象的容量操作

size

size_t size() const;

Return length of string–返回字符串有效字符长度

我们都是熟知ASCLL表,我们打印的字符,或者符号都是被数字所表示的。因为计算机是只认识二进制,所以这些字符或者符号都会变成二进制让计算机识别。世界上有各种语言,所以对应的就有不同的电脑编码。英文对应的电脑编码是ASCLL,中文对应的电脑编码很多时候就是统一码
统一码(Unicode),也叫万国码、单一码,由统一码联盟开发,是计算机科学领域里的一项业界标准,包括字符集、编码方案等。统一码是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。

统一码是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。统一码用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个码位。码位就是可以分配给字符的数字。UTF-8、UTF-16、UTF-32都是将数字转换到程序数据的编码方案。分别映射为8位,16位,32位长的整数。

#include<iostream>
#include <string>
using namespace std;int main()
{string str("hello world");size_t n=str.size();cout << n << endl;    //utf-8  输出为11return 0;
}

length

size_t length() const;

Return length of string ----返回字符串的长度

#include <iostream>
#include <string>int main ()
{std::string str ("Test string");std::cout <<  str.length() << std::endl; //输出为11return 0;
}

注意

size和length的功能相同,用size()函数较多,size用的范围更广,包括后面的各种容器

capacity

size_t capacity() const;

Return size of allocated storage----返回空间总大小

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;int main() {string s1("hello world");cout << s1.capacity() << endl;   //输出为15,大小取决于编译器
}

empty

bool empty() const;

Test if string is empty----检测字符串释放为空串,是返回true,否则返回false

#include<iostream>
#include <string>
using namespace std;int main()
{string str("hello world");if (!str.empty()){cout << "hello everyone!" << endl; //不为空打印}return 0;
}

clear

void clear();

Clear string----清空有效字符

#include<iostream>
#include <string>
using namespace std;int main()
{string str("hello world");str.clear();   //清空strcout << str << endl; //输出空return 0;
}

注意
clear是清空有效字符但是不清除内存,因为一般情况是下是内存足够,缺时间。一般会选择增容不会减少内存,增加内存会重新开辟一块内存,因为内存中存在这内存碎片。减少内存之后,重新写入就会增加空间,那么就更加耗时,所以一般情况下是不减少内存的。

reserve

void reserve (size_t n = 0);

Request a change in capacity-----请求更改容量

简单来说就是修改容量,不够就申请,往小了改动就在不影响字符串的情况下不变

void Test()
{string s1("hello world");string s2("hello world");cout <<"s1修改前:" << s1 << "  " << s1.capacity() << "  " << s1.size() << endl;s1.reserve(500);cout << "s1修改后:" << s1 << "  " << s1.capacity() << "  " << s1.size() << endl;cout << endl;cout << endl;cout << "s2修改前:" << s2 << "  " << s2.capacity() << "  " << s2.size() << endl;s2.reserve(5);cout << "s2:" << s2 << "  " << s2.capacity() << "  " << s2.size() << endl;}int main()
{Test();return 0;
}

对照实验,清晰易懂,扩容的大小根据编译器的不同而不同,一般vs是1.5倍,linux两倍。

resize

void resize (size_t n);

void resize (size_t n, char c);(常用)

Resize string----调整字符串大小

简单来说就是,往大了调整就是申请内存,补充字符,往小了申请就是erase删除字符(尾删)

int main() {string s1("hello world");string s2("hello world");cout <<"s1修改前: " << s1 << endl;cout<<"s2修改前: " << s2 << endl;s1.resize(15);s2.resize(15, 'x');cout <<"s1变大修改后: " << s1 << endl;cout <<"s2变大修改后: " << s2 << endl;s1 = "hello world";s2 = "hello world";s1.resize(5);s2.resize(5, 'x');cout << "s1变小修改后: " << s1 << endl;cout << "s2变小修改后: " << s2 << endl;}

4.string类对象的访问及遍历操作

operator[ ] (运算符重载)

char& operator[] (size_t pos);

const char& operator[] (size_t pos) const;

Returns a reference to the character at position pos in the string.

----返回pos位置的字符,const string类对象调用

#include <iostream>
#include <string>int main()
{std::string str("Test string");for (int i = 0; i<str.size(); ++i){std::cout << str[i];}return 0;
}

begin /end

iterator begin();

const_iterator begin() const;

Returns an iterator pointing to the first character of the string

----返回指向字符串第一个字符的迭代器

iterator end();

const_iterator end() const;

Returns an iterator pointing to the past-the-end character of the string.

----返回一个迭代器,该迭代器指向字符串的结束字符。

这里的迭代器看作指针即可

int  main() {string s1("hello world");cout << s1 << endl;string::iterator it1 = s1.begin();cout << *it1 << endl;string::iterator it2 = s1.end()-1;cout << *it2 << endl;cout << endl;std::string s2("myfriends");cout << s2 << endl;string::reverse_iterator it3 = s2.rbegin();cout << *it3 << endl;string::reverse_iterator it4 = s2.rend() - 1;cout << *it4 << endl;}

rend/rbegin

reverse_iterator rbegin();

const_reverse_iterator rbegin() const;

Return reverse iterator to reverse beginning

----返回反向迭代器以反向开始

reverse_iterator rend();

const_reverse_iterator rend() const;

Return reverse iterator to reverse end

----将反向迭代器返回到反向端


  C++中,迭代器就是一个类似于指针的对象,它能够用来遍历C++标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址。

  这里需要注意的是,,对于string类来说,无论是正向遍历,还是反向遍历,下标+[]都足够好用,但是对于其他容器,对于那些以链表形式连接的数据结构,如list,map/set等,就不能使用下标+[]的方式去访问容器里的元素,所以就需要采用迭代器来访问这些容器里的元素。

5.string类对象的修改操作

push_back

void push_back (char c);

ppends character c to the end of the string, increasing its length by one.

----将字符c追加到字符串的末尾,将其长度增加1

#include <iostream>
#include <fstream>
#include <string>
using namespace std;int main()
{string str;str.push_back('h');str.push_back('e');str.push_back('l');str.push_back('l');str.push_back('o');std::cout << str << endl;  //hello return 0;
}

append

(1) string

Appends a copy of str.----追加str的副本

(2) substring

Appends a copy of a substring of str. The substring is the portion of
str that begins at the character position subpos and spans sublen
characters (or until the end of str, if either str is too short or if
sublen is string::npos).

----追加str的子字符串的副本。该子字符串是str的一部分,从字符位置子字符串开始,跨越子字符串字符(或直到str结尾,如果str太短或子字符串为string::npos)

(3) c-string

Appends a copy of the string formed by the null-terminated character
sequence (C-string) pointed by s.

----追加由s指向的以空结尾的字符序列(C字符串)形成的字符串的副本

(4) buffer

Appends a copy of the first n characters in the array of characters
pointed by s.

----追加由s指向的字符数组中前n个字符的副本

(5) fill

Appends n consecutive copies of character c.

----追加n个字符c的连续副本。

(6) range

Appends a copy of the sequence of characters in the range
[first,last), in the same order.

#include <iostream>
#include <string>int main()
{std::string str;std::string str2 = "hello my girl ";std::string str3 = "printf you c++,I believe you";str.append(str2);                       // 情况1std::cout << str << '\n';str.append(str3, 6, 3);                   // 情况2std::cout << str << '\n';str.append("believe you", 5);          // 情况3std::cout << str << '\n';str.append("aaaaa ");                   // 情况4std::cout << str << '\n';str.append(10u, '.');                    // 情况5std::cout << str << '\n';str.append(str3.begin() + 8, str3.end());  // 情况6std::cout << str << '\n';return 0;
}


operator+=

Append to string----附加到字符串

#include <iostream>
#include <string>int main()
{std::string name("John");std::string family("Smith");name += " K. ";         // c-stringname += family;         // stringname += '\n';           // characterstd::cout << name;    //John K. Smithreturn 0;
}

c_str

const char* c_str() const;

Get C string equivalent----获取等效的C字符串

返回指向数组的指针,该数组包含表示字符串对象当前值的以空结尾的字符序列(即C字符串)。此数组包含构成字符串对象值的相同字符序列,加上末尾的附加终止空字符(“\0”)。

find

Find content in string----在字符串中查找内容
npos

static const size_t npos = -1;

npos:Maximum value for size_t----size_t的最大值

int main() {string s1("hello");string s2("aa");cout << s1.find('o')<<endl;cout << s1.find("he") << endl;cout << s2.find('b') << endl;
}

找不到要找的字符或者字符串返回npos,就是一串很大的数字

rfind

Find last occurrence of content in string----查找字符串中内容的最后一次出现

就是倒着查找,返回下标

substr

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

Returns a newly constructed string object with its value initialized to a copy of a substring of this object-----返回一个新构造的字符串对象,其值初始化为此对象的子字符串的副本。

就是根据传入的下标构造一个新的字符串

注意

  1. 在string尾部追加字符时,s.push_back© / s.append(1, c) / s += 'c’三种的实现方式差不多,一般 情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。

  2. 对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好

6.string类非成员函数

operator+ (string)

Concatenate strings ----连接字符串


operator>> (string)

istream& operator>> (istream& is, string& str);

Extract string from stream----从流中提取字符串

operator<< (string)

ostream& operator<< (ostream& os, const string& str);

Insert string into stream----将字符串插入流

getline (string)

Get line from stream into string----从流获取线到字符串

#include <iostream>
#include <string>int main()
{std::string name;std::cout << "Please, enter your full name: ";std::getline(std::cin, name);std::cout << "Hello, " << name << "!\n";return 0;
}

relational operators (string)

Relational operators for string----字符串的关系运算符(各种比较)

int main() {string s1("lsdasd");string s2("abcd");string s3("abcd");if (s1 == s2) cout << "s1==s2" << endl;if (s1 >= s2) cout << "s1>=s2" << endl;if (s1 <= s2) cout << "s1<=s2" << endl;if (s2 == s3) cout << "s2==s3" << endl;}

三、string的模拟实现

1.经典的string类问题

我们在模拟实现string的时候,可以先看看string类的经典问题。在实现string类的构造、拷贝构造、赋值运算符重载以及析构函数时,经常会出现深浅拷贝的问题。

构造String类对象的错误:

String(const char* str = “\0”) ----错误示范,"\0"是需要内存存放的

String(const char* str = nullptr) ----错误示范,String是类,地址是不会指向nullptr
Sring(const char* str = “”)----正确示范
构造String类对象时,如果传递nullptr指针,可以认为程序非法。

顺便说一下 ""  '\0'    "\0"的区别吧""     是字符串,不过是空  表示 \0'\0'       是字符0,表示ASCII码为0"\0"        是字符串    表示为 \0\0

2.浅拷贝/深拷贝

浅拷贝:也称位拷贝,编译器只是将对象中的值拷贝过来。如果对象中管理资源,最后就会导致多个对象共享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该资源已经被释放,以为还有效,所以当继续对资源进项操作时,就会发生发生了访问违规。

可以采用深拷贝解决浅拷贝问题,即:每个对象都有一份独立的资源,不要和其他对象共享。

#include <iostream>
#include <assert.h>
using namespace std;
class String
{public:
String(const char* str = "")
{if (nullptr == str){assert(false);return;}_str = new char[strlen(str) + 1];strcpy(_str, str);
}~String()
{if (_str){delete[] _str;_str = nullptr;}
}private:char* _str;
};
// 测试
void TestString()
{String s1("hello bit!!!");String s2(s1);
}int main()
{TestString();return 0;
}

s1传入字符串是没有问题的,但是将s1的地址传入s2时,就会出现错误。因为在s2调用构造函数的时候,s2中的_str存放的地址也是s1的地址。那么在调用析构函数的时候,我们就会发现调用了两次析构函数,第一将_str清除后,s2再调用析构函数的时候,此时_str已经是随机值,再对_str进行删除的时候就会报错。

深拷贝
如果一个类中涉及到资源的管理,其拷贝构造函数、赋值运算符重载以及析构函数必须要显式给出。一般情况都是按照深拷贝方式提供。

3.string类的模拟实现

string.cpp

#define _CRT_SECURE_NO_WARNINGS
#include"String.h"
#include<iostream>
using namespace std;int main() {//zzg::test_string1();//zzg::test_string2();//zzg::test_string3();//zzg::test_string4();//zzg::test_string5();zzg::test_string6();return 0;
}

string.h(我把声明全放在zzg类域中了,包括我的测试)

#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace zzg {class string{public:typedef char* iterator;iterator begin() {return _str;}iterator end() {return _str + _size;}//string() {//   _str = new char[1];//  _str[0] = '\0';//    _capacity = _size = 0;//}// '\0'    0// "\0"    \0\0// ""       \0// string s3;//string  s2("dasdasd");//构造函数  包括无参初始化和有参初始化,运用缺省参数string(const char* str = ""){_size = strlen(str);_capacity = _size;_str = new char[_capacity + 1];strcpy(_str, str);}//s2(s1)//拷贝构造(传统写法)string(const string& s) {   _str = new char[s._capacity + 1]; _capacity = s._capacity;   _size = s._size;// strcpy(_str, s._str);}void swap(string&s) //合理运用c++中的swap,将拷贝构造(深拷贝)转化成交换地址{//c语言中一次swap要深拷贝3次,过于复杂,转换成交换地址std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}//拷贝构造现代写法//s2(s1)//string(const string& s)//  :_str(nullptr)//    , _size(0)//    ,_capacity(0)//{//  string tmp(s);//    swap(_str, tmp._str);// swap(_size, tmp._size);//   swap(_capacity, tmp._capacity);//}//拷贝构造现代写法优化版string(const string& s):_str(nullptr), _size(0), _capacity(0){string tmp(s._str);//this->swap(tmp);swap(tmp);}//析构函数~string() {delete[]_str;_str = nullptr;_size = _capacity = 0;}//=的运算符重载的传统写法//s1=s2//string& operator=(const string& s)//{//    if (this != &s) //避免s1=s1的特殊情况,遇到这种直接跳过//  {//     //开辟新空间=s的_str,并拷贝过去//     char* tmp = new char[s._capacity + 1];//      strcpy(tmp, s._str);//      //释放原空间,让_str指向新的空间//        delete[]_str;//     _str = tmp;//      //修改元素个数和空间大小//     _size = s._size;//     _capacity = s._capacity;// }// return *this;//}//=运算符重载的现代写法//s1=s2//string& operator=(const string& s)//{//    if (this != &s) //避免s1=s1的特殊情况,遇到这种直接跳过//  {//     //string tmp(s._str);//     string tmp(s);//        swap(tmp);//    }// return *this;//}string& operator=(string s){swap(s);return *this;}const char* c_str() const   //只读函数加const{                            //只写函数不加const           return _str;            //可读可写的函数要写两个版本的函数}size_t size() const{return _size;}size_t capacity()const{return _capacity;}//普通对象:可读可写char& operator[](size_t pos){assert(pos < _size);return _str[pos];}//const对象:只读const char& operator[](size_t pos)const{assert(pos < _size);return _str[pos];}//扩容void reserve(size_t n) {if (n > _capacity){char* tmp = new char[n + 1];strcpy(tmp, _str);delete[]_str;_str = tmp;_capacity = n;}}void resize(size_t n, char ch = '\0'){//3种情况 n<_size   _capacity>n>_size   n>_capacityif (n > _size) {reserve(n);for (size_t i = _size; i < n; ++i){_str[i] = ch;}_size = n;_str[_size] = '\0';}else{_str[n] = '\0';_size = n;}}//尾插字符void push_back(char ch) {/*if (_capacity == _size) {reserve(_capacity * 2);}*///当string s1,_capacity=0;reserve(0);无法开辟空间 if (_size == _capacity) {size_t newCapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newCapacity);}_str[_size] = ch;++_size;_str[_size] = '\0';}//尾插字符串void append(const char* str) {size_t len = strlen(str);if (_size + len > _capacity) {reserve(_size + len);}strcpy(_str + _size, str);_size += len;}string& operator+=(char ch) {push_back(ch);return *this;}string& operator+=(const char* str) {append(str);return *this;}//插入数据string& insert(size_t pos, char ch) {assert(pos <= _size);//断言//是否需要扩容if (_size == _capacity) {size_t newCapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newCapacity);}//挪动数据/*int end = _size;    //size_t的end在end--过程中会越界,end=-1变成很大的数while (end >= (int)pos)//防止隐式类型提升,进入死循环,所以必须强转pos{_str[end + 1] = _str[end];--end;}*/size_t end = _size + 1;while (end > pos) {_str[end] = _str[end - 1];--end;}_str[pos] = ch;_size++;return *this;}string& insert(size_t pos, const char*str){assert(pos <= _size);//断言size_t len = strlen(str);if (_size + len > _capacity){reserve(_size + len);}size_t end = _size + len;while (end > pos + len-1) {_str[end] = _str[end - len];--end;}strncpy(_str + pos, str, len);//不用strcpy防止拷贝\0,固定拷贝个数_size += len;return *this;}string& erase(size_t pos, size_t len = npos) {assert(pos <= _size);if (len == npos || len >= _size-pos) {_str[pos] = '\0';_size = pos;}else {strcpy(_str + pos, _str + pos + len);_size -= len;}return *this;}size_t find(char ch, size_t pos = 0) const{assert(pos < _size);while (pos < _size){if (_str[pos] == ch) {return pos;}++pos;   //找到了}return npos; //没找到返回-1}size_t find(const char* str, size_t pos= 0) const{assert(pos < _size);const char* ptr = strstr(_str + pos, str);if (ptr == nullptr) {return npos;}else{return ptr - _str;}}void clear(){_size = 0;_str[0] = '\0';}private:char* _str;size_t _size;size_t _capacity;const static size_t npos = -1;};//流插入和流提取的重载ostream& operator<<(ostream& out, const string& s){for (size_t i = 0; i < s.size(); ++i){out << s[i];}return out;}istream& operator>>(istream& in, string& s){char buff[128] = { '\0' };size_t i = 0;char ch = in.get();while (ch != ' ' && ch != '\n'){if (i == 127) {//满了s += buff;i = 0;}buff[i++] = ch;ch = in.get();}if (i > 0){buff[i] = '\0';s += buff;}return in;}//void test_string1() {//    string s("abcdef");// cout << s.begin() << endl;//    cout << s.end() << endl;//  cout << s.end() - s.begin() << endl;//  string s1;//    string s2("aabb");//  string s3(s2);//    string s4 = s3;//  string s5 = "aa   aa";// cout << s5.size() << endl;//    cout << s5.capacity() << endl;//    cout << s5.c_str() << endl;//   string s8("hello world");//   cout << s8.size() << "  " << s8.capacity() << endl;// cout << s8.c_str() << endl;//   s8.reserve(80);//   s8.resize(5,'x');//   s8.resize(15, 'x');// s8.resize(100, 'x');//    cout << s8.size() << "  " << s8.capacity() << endl;// cout << s8.c_str() << endl;//}
//  void test_string2(){//  string s1 = "hello";
//  cout << s1.c_str() << endl;
//  for (size_t i = 0; i < s1.size(); ++i) {//      s1[i]++;
//  }
//  cout << s1.c_str() << endl;
//
//  string::iterator it1 = s1.begin();
//  while (it1 != s1.end()) {//      (*it1)--;
//      ++it1;
//  }
//  cout << s1.c_str() << endl;
//  for (auto ch : s1) {//      cout << ch << " ";
//  }
//  string s2("world");
//  s2.push_back(' ');
//  s2.push_back('a');
//  s2.push_back('p');
//  cout << s2.c_str() << endl;
//  s2.append("aksdmkwidw");
//  cout << s2.c_str() << endl;
//}//void test_string3() {//    string s1;//    s1.push_back('x');//  s1.push_back('a');//  s1.append("ccccc");// cout << s1.c_str() << endl;//   s1.insert(0,' ');//   cout << s1.c_str() << endl;//   s1.insert(0, "zzgYYDS");//    cout << s1.c_str() << endl;//}//void test_string4()//{//    string s1("hello hello world zzg");// //cout << s1.c_str() << endl;// //cout << s1.size() << "  " << s1.capacity() << endl;//   //s1.erase(5,7);//  //cout << s1.c_str() << endl;// //cout<<s1.find('o')<<endl;// //cout << s1.find('5') << endl;// //cout << s1.find("wor",2) << endl;// cout << s1 << endl;//   string s2;//    cin >> s2;//  cout << s2 << endl;//   //s1.clear();// //cout << s1.c_str() << endl;// //string str("This is an example sentence.");//   //cout << str.c_str() << '\n';//   "This is an example sentence."// //str.erase(10, 8);                        //            ^^^^^^^^// //cout << str.c_str() << '\n';//  //string s1("hello hello world");//   //s1.erase(5, 5);// //std::cout << s1.c_str() << std::endl;//   //s1.erase(5);//    //cout << s1.c_str() << endl;//}//void test_string5() {//   //string s1;//  //string s2("hello world");// //s1 = s2;//   string s3("zzgyyds");//   string s4(s3);//}void test_string6() {string s1("zzgyyds");s1.erase(1,2);cout << s1 << endl;}
}

四、总结

OK!我的伙伴们,到这里就基本结束了,其实string只需要会使用并了解原理即可,大家多多尝试,看在乌龟这么努力的份上,能不能给个三连。
我们下期见!!!

[C++] STL介绍及string的模拟实现相关推荐

  1. 【C++篇】STL常见容器String的模拟实现

    准备 博主:大大怪先森(记得关注哦!) 编程环境:vs2013 所示代码:码源 文章目录 准备 前言 一.标准库中的tring类 1.了解类 2.string类的常见接口 2.1 string类对象的 ...

  2. STL库:string

    STL库:string 文章目录 STL库:string 1.STL库对于string类的介绍 2.string常用接口的掌握 2.1 string的构造接口 2.2 string的容量操作接口 2. ...

  3. 学习笔记:C++初阶【C++入门、类和对象、C/C++内存管理、模板初阶、STL简介、string、vector、list、stack、queueu、模板进阶、C++的IO流】

    文章目录 前言 一.C++入门 1. C++关键字 2.命名空间 2.1 C语言缺点之一,没办法很好地解决命名冲突问题 2.2 C++提出了一个新语法--命名空间 2.2.1 命名空间概念 2.2.2 ...

  4. c++STL容器的string

    STL容器的string String概念 string是一个类, char*是一个指向字符的指针. string不用考虑内存释放和越界. string提供了一系列的字符串操作函数 string的构造 ...

  5. c++——string的模拟实现

    标准库中的string类 string是表示字符串的字符串类 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作. string在底层实际是:basic_string模 ...

  6. 多种期权知识点介绍与损益结构模拟

    多种期权知识点介绍与损益结构模拟 前言 一:期权基础知识介绍 二:期权定价理论简介期权定价要素 三:普通香草期权的payoff组合 四:障碍奇异期权的payoff 五:总结 前言 期权是人们为了规避市 ...

  7. 介绍简易制作飞行模拟游戏的方法(转)

    介绍简易制作飞行模拟游戏的方法(转)[@more@] 对许多网友而言,玩游戏是件令人愉快的事情,但是能因此而想到要去亲手制作一个游戏-----甚至是大型游戏的朋友可能就不是很多了,其中原因,说来也简单 ...

  8. C++STL库:String介绍

    C++STL库 学习方法:使用STL的三个境界:能用,明理,能扩展. 今天我们开启一个新主题:C++数据结构之STL库,我们将介绍STL库里常用库的用法与实现过程. 常用库 库名称 所需头文件 数据结 ...

  9. C++ STL : 模拟实现STL中的string类

    string的文档介绍 string是表示字符序列的类 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作 单字节字符字符串的设计特性. string类是使用c ...

最新文章

  1. 别再和面试官说不懂信号量Semaphore了!
  2. 查询v$lock缓慢和direct path write temp等待
  3. Unity3D学习笔记(一) 模型和贴图导入学习
  4. [C++] 转义序列
  5. 协鑫集成为泰国Enmax建立10MW光伏电站
  6. js数字比较【牢记】
  7. (10)Redis------必须知道的基础内容
  8. 卫星星历和历书的区别
  9. 复指数信号正交性的简单证明
  10. Python-OpenCV4中的阈值二值化函数threshold(),要特别注意其返回值有两个
  11. 树莓派开始,玩转Linux21:进程的生与死
  12. Chrome 扩展插件:如何开始一个插件的开发
  13. 计算摄影:相机成像流程 —— ISP
  14. Arduino与FreeRTOS-守护任务(Gatekeeper Task)
  15. Educational Codeforces Round 117 (Rated for Div. 2)题解(A~D)
  16. LAMP平台QQ农场
  17. Elasticsearch面试题(大数据面试)
  18. 引用微信JSSDK与支付宝JSSDK
  19. Vivado下的集成逻辑分析仪ILA 入门
  20. 【超级详细】RabbitMQ安装教程

热门文章

  1. C++推箱子游戏(可以撤回)
  2. 「PAT乙级真题解析」Basic Level 1089 狼人杀-简单版 (问题分析+完整步骤+伪代码描述+提交通过代码)
  3. 如何用mysql创建数据仓库_数据仓库入门(实验1)创建数据源
  4. c odp.net连oracle,oracle odp.net 连接不上oracle
  5. 修改Office 2003安装序列号,获得验证通过。
  6. Office 2016 删除序列号
  7. 无忧全国计算机等级考试超级模拟软件_一级计算机基础及MS Office应用安装教程
  8. windbg小工具umdh查找内存泄露
  9. QQ空间上传图片过大限制怎么解决?打包压缩在线操作的方法
  10. 目标检测实战必会!4种基于YOLO目标检测(Python和C++两种版本实现)