c++|STL简介+string类的使用(常用接口)

目录

一、STL简介

1.1STL的版本

 1.2STL六大组件

1.3STL的重要性及缺陷 

二、string类简介

2.1string类了解

2.2为什么学习string类

三、string类使用(常用接口)

3.1string类的成员函数

3.1.1构造函数

3.1.2析构函数

3.1.3“=”运算符重载函数 

3.2迭代器(iterator)+string类对象的访问及遍历

3.2.1 iterator

3.2.2 operator[]

3.2.3 at()

3.2.4 back() && front()

3.2.5 范围for

3.3string类对象的容量操作

3.3.1 size() && length()

3.3.2 capacity() && reserve && resize

3.3.3  empty() && clear()

3.4string类对象的修改操作

3.4.1 push_back  && append && assign && insert

3.4.2 operator+=

3.4.3 c_str()

3.4.4 find+ npos && substr()

3.4.5 erase


一、STL简介

STL(standard template libaray-标准模板库):从表面意思来说,他是c++标准库的重要组成成分,他的组件(接口)是可复用的,管理着数据结构和算法。

1.1STL的版本

  • 原始版本--HP版本(所有STL实现版本的始祖),开源版本,允许任何人使用,但后人如对其修改,也需开源。
  • P.J.版本--继承自HP版本,在 HP 版本的基础上进行了大量的独立创作和投入,形成了新的商业价值,那么他可以根据自己的意愿选择是否收费,并制定自己的授权协议。被Windows Visual C++采用,不能公开或修改,那么必然有一定的缺陷不容易发现,可读性较低。
  • RW版本--继承HP版本,被C++ Builder采用,同样不能修改,可读性较低
  • SGI版本--继承HP版本,被GCC(Linux)采用,开源版本,可移植性好,阅读性非常高。在学习过程中,就可以参照这个版本的源码进行研究。

 1.2STL六大组件

STL有六大组件,通过一张图来展示,要学的第一个组件就是容器,这些容器接口说白了就是管理数据结构,最重要的基础就是string接口,string产生其实比STL还要早,后来才归类进来,学会这一个,就可以贯通各个接口,因为用法都大差不差。

 

1.3STL的重要性及缺陷 

STL在笔试中、面试中占了很重要的一部分,在工作中也会经常使用,在学习STL的过程中,也不能急于求成,先学会怎么用,再去深入了解底层,再扩展。当然在学习过程中也可能遇到以下问题,当然这应该也是STL的缺陷。

1.STL更新慢。

2.STL现在没有只差线程安全。并发环境下需要我们自己加锁。且锁的粒度是比较大的

3.STL极度的追求效率,导致内部比较复杂。比如类型萃取,迭代器萃取

4.STL的使用会有代码膨胀的问题,当然这是模板语法本身导致的。

接下来我们进行学习第一个容器接口string类,并结合所学理解STL的缺陷。

二、string类简介

2.1string类了解

1.string类其实就是一个模板类,typedef过来的,是basic_string模板类的一个实例,用的char来实例化basic_string模板类。

2.管理字符序列的一个类

3.string类有许多接口,这些接口都是用来操作操作字符串

4.这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。

2.2为什么学习string类

其实还是一个原则,string类可以更好的面向对象,string类的接口都是拿来使用就行,不需要过分管理底层如何实现,而C语言就不同了,轮子需要自己造,空间需要自己管理 ,不能出错。

 那么接下来,就进行学习string类的常用接口有哪些,以及如何使用。

三、string类使用(常用接口)

在介绍string类接口前先说明一下接口会出现的npos,他是成员常量,在接口中扮演缺省值成分,size_t为unsigned int,无符号整形的-1,即整形最大值。也就是不传参,默认就是缺省值。其次在使用string类的接口时包含一下头文件#include <string>

static const size_t npos = -1;

3.1string类的成员函数

3.1.1构造函数

default (1)
                             string();
                        默认构造函数,构造空的string类对象,即空字符串
copy (2)
                     string (const string& str);
                                                   拷贝构造函数
substring (3)
    string (const string& str, size_t pos, size_t len = npos);
                   从字符串的 pos 位置取len个字符串来构造string类对象
from c-string (4)
                        string (const char* s);
                                        用c-string来构造string类对象
from sequence (5)
                 string (const char* s, size_t n);
                              从字符串中拷贝前n个字符构造string类对象
fill (6)
                     string (size_t n, char c);
                                        string类对象中包含n个字符c

#include <iostream>
#include <string>
using namespace std;
int main()
{string str;//构造空对象,调用默认构造函数string s("hello world");//用c-string来构造string类对象string s1(5, 'x');//创建5个字符xstring s2(s1);//s1拷贝给s2string s3(s, 5, 3);//从第五个位置,拷贝3个字符给s3string s4(s, 2);//从第2个位置,npos为整形最大值,默认拷贝后面所有字符给s4,包括'/0'string s5("hello world", 5);//拷贝前5个字符给s5cout << s << endl;cout << s1 << endl;cout << s2 << endl;cout << s3 << endl;cout << s4 << endl;cout << s5 << endl;return 0;
}

 运行结果:

3.1.2析构函数

~string():这个基本上不用,编译器会自动调用析构函数,释放对象

3.1.3“=”运算符重载函数 

string (1)
string& operator= (const string& str);
c-string (2)
string& operator= (const char* s);
character (3)
string& operator= (char c);
#include <iostream>
#include <string>
using namespace std;
int main()
{string s("hello world");string s1 = s;string s2 = "hello world";//string s3 = 'x';这个不支持,这种构造形式只能是字符串,不能是单个字符string s3;s3 = 'x';cout << s << endl;cout << s1 << endl;cout << s2 << endl;cout << s3 << endl;return 0;
}

运行结果:

3.2迭代器(iterator)+string类对象的访问及遍历

迭代器本质上可以是内置类型,如typedef过的指针(例如:typedef char* iterator; typedef const char*  const_iterator),也可以是其他类型(自定义类型),虽然迭代器底层实现方式不同,但在表面上其功能是一样的,当作指针来理解使用。其次,迭代器可以适用所有容器,例如:string、vector、list、stack、queue等

3.2.1 iterator

迭代器的范围对于对象而言是左闭右开:[  ),在字符串当中代表最后一个'/0'位置,并不算是有效字符

迭代器是属于string的类域,所以调用迭代器时,要指明类域,即string::iterator

迭代器作用于的成员函数有8个: begin(),end(),rbegin(),rend(),cbegin(),cend(),crbegin(),crend()。

他作用于的成员函数有各自的重载函数。

①begin + end(作用:正向遍历字符串)

iterator begin():返回指向第一个字符串的迭代器

iterator end():返回指向最后一个字符串下一个位置的迭代器,可以认为指向'/0'
const_iterator begin() const:返回指向第一个字符串的迭代器,但迭代器所指向的内容不能修改
 
const_iterator end() const;返回指向最后一个字符串的迭代器,但迭代器所指向的内容不能修改 

#include <iostream>
#include <string>
using namespace std;
int main()
{string s("hello world");const string s1("excuse me");string::iterator it = s.begin();//指向字符串的第一个位置,返回对象为迭代器string::const_iterator it1 = s1.begin(); //返回指向第一个字符串的迭代器,但迭代器所指向的内容不能修改while (it != s.end())//遍历{cout << *it;//迭代器当作指针,进行解引用//*it = 'x';可以修改++it;}cout << endl;while (it1 != s1.end())//遍历{cout << *it1;//迭代器当作指针,进行解引用//*it = 'x';不能修改++it1;}cout << endl;return 0;
}

 

 ②rbegin + rend(作用:反向遍历字符串)

reverse_iterator rbegin():反向迭代器,其功能跟begin相反,返回指向最后一个字符的迭代器

reverse_iterator rend():其功能与end相反,返回指向第一个字符的迭代器

const_reverse_iterator begin() const:返回指向最后一个字符串的迭代器,但迭代器所指向的内容不能修改 
const_reverse_iterator end() const返回指向第一个字符的迭代器,但迭代器所指向的内容不能修改 

#include <iostream>
#include <string>
using namespace std;
int main()
{string s("hello world");const string s1("excuse me");string::reverse_iterator it = s.rbegin();//指向字符串的最后一个位置,返回对象为迭代器string::const_reverse_iterator it1 = s1.rbegin(); //返回指向最后一个字符串的迭代器,但迭代器所指向的内容不能修改while (it != s.rend())//反向遍历{cout << *it;//迭代器当作指针,进行解引用//*it = 'x';可修改++it;}cout << endl;while (it1 != s1.rend()){cout << *it1;//迭代器当作指针,进行解引用//*it1 = 'x';不能修改++it1;}return 0;
}

 

③cbegin + cend  ④crbegin + crend

这两个组合就是说明调用的是const对象的迭代器,当调用的是const对象迭代器时,前缀有符号c和不加c都是一样的。

例如:const s1("hello world"); 定义一个const对象,调用const的迭代器。

string::const_iterator it = s1.cbegin();或者string::const_iterator it1 = s1.begin();

同理另外几个也是一样的,所以这两个组合也没啥特别大的作用。

3.2.2 operator[]

属于string类,运算符[ ]的重载函数,直接由string对象调用访问对象元素。

重载版本:

char& operator[](size_t pos):返回pos位置的字符,由const string类对象调用

const char& operator[](size_t pos) const:返回pos位置的字符,是一个常量引用 ,不能对其修改,且在函数内部不能修改对象的成员变量。


#include <iostream>
#include <string>
using namespace std;
int main()
{string s("hello world");const string s1("excuse me");for (size_t i = 0; i < s.size(); i++){cout << s[i];}cout << endl;for (size_t i = 0; i < s1.size(); i++){cout << s1[i];//s[i] = 'x';不能修改常量引用}return 0;
}

3.2.3 at()

功能跟operatro[]一样,调用方式不同罢了

重载版本:

char& at(size_t pos);

const char& at(size_t pos) const;

using namespace std;
int main()
{string s("hello world");const string s1("excuse me");for (size_t i = 0; i < s.size(); i++){cout << s.at(i);}cout << endl;for (size_t i = 0; i < s1.size(); i++){cout << s1.at(i);//s[i] = 'x';不能修改常量引用}return 0;
}

 

3.2.4 back() && front()

分别返回最后一个字符和第一个字符 

重载版本: 

char& back();     const char& back();

char& front();      const char& front();

#include <iostream>
#include <string>
using namespace std;
int main()
{string s("hello world");const string s1(s);cout << s.back() << endl;s.back() = '!';//修改最后一个字符cout << s.back() << endl;cout << s.front() << endl;s.front() = '!';//修改第一个字符cout << s.front() << endl;cout << s1.back() << endl;cout << s1.front() << endl;return 0;
}

 

3.2.5 范围for

 他的底层其实就是用迭代器来实现的,调用的就是迭代器,只不过在表面上的用法不同而已

形式:

for(auto e :  对象) {}; 或者for(auto& e : 对象) {};

e对象的名称可以随便取,一般用e,auto在类和对像章节讲过,根据赋值对象的类型来推演被赋值对象的类型。如何使用范围for的形式,具体也要看对象中的成员赋值给e时,是否要调用拷贝构造,而造成没必要的浪费。

#include <iostream>
#include <string>
using namespace std;
int main()
{string s("hello world");const string s1 = "string is easy to learn";for (auto e : s)//依次取s中的元素到e中,底层调用的就是迭代器。依次打印e中的内容{cout << e;}cout << endl;for (auto d : s1){cout << d;}
}

 

3.3string类对象的容量操作

3.3.1 size() && length()

函数原型:

 size_t size() const;    size_t length() const;

他们两的作用是一样的,都是获取字符串的长度,至于为什么有两个,这是因为历史上的原因,早期是先出来的length函数,但后来如果用length来表示树的大小就不合适,所以又造了个size函数,就是为了更符合表面意义,本质上没区别。

#include <iostream>
#include <string>
using namespace std;
int main()
{string s("hello world");cout << s.size() << endl;cout << s.length() << endl;return 0;
}

3.3.2 capacity() && reserve && resize

函数原型:

size_t capacity() const;返回string对象容量的大小。

void reserve(size_t n);对容量进行操作,vs下只能扩容,不能缩容

 void resize(size_t);  void resize(size_t, char c);对_size 和容量和数据的操作,vs下对容量的操作只能扩容

#include <iostream>
#include <string>
using namespace std;
int main()
{string s("hello world");cout << s.size() << endl;cout << s.capacity() << endl;//返回空间总大小,可能比字符串的长度大,可能采用了对齐规则s.reserve(30);//扩容cout << s.capacity() << endl;//n是相对字符串的大小//n<resize<capacity,进行尾插数据,若未指定尾插数据默认为0s.reserve(20);//vs下reserve不支持缩容,所以还是和前面的容量一样s.resize(16, 'y');//剩余的空间都尾插'y'cout << s.capacity() << endl;cout << s << endl;//n>capacity,进行扩容,然后尾插数据s.resize(46, 'x');//扩容后多余的空间都尾插'x'cout << s.capacity() << endl;cout << s << endl;//resize<n,删除数据,只取前面resize个数据,此时resize不会缩容,但size大小变了s.reserve(30);s.resize(5);cout << s.capacity() << endl;cout << s << endl;return 0;
}

3.3.3  empty() && clear()

 函数原型:

bool empty() const;判断字符串是否为空

void char();清空字符串中的内容,变为空串

#include <iostream>
#include <string>
using namespace std;
int main()
{string s("hello world");cout << s << endl;cout << s.empty() << endl;//s不为空while (!s.empty())//判断s对象是否为空,不是就清空{s.clear();}cout << s.empty() << endl;//s为空s = 'w';//插入一个字符cout << s << endl;return 0;
}

3.4string类对象的修改操作

3.4.1 push_back  && append && assign && insert

函数原型:

void push_back(char c);尾插一个字符

 append(部分重载):

string& append (const string& str);追加字符串的拷贝

string& append (const char* s);追加字符串的拷贝

string& append (const char* s, size_t n);追加字符串的前n个字符

string& append (size_t n, char c);追加n个字符c

assign的原型跟append的一样,但它的功能是赋值,而不是追加

insert(部分重载):

string& insert (size_t pos, const string& str); pos位置插入字符串

string& insert (size_t pos, const char* s); pos位置插入字符串

string& insert (size_t pos, const char* s, size_t n);pos位置插入字符串的前n个字符

string& insert (size_t pos, size_t n, char c);pos位置插入n个字符c

void insert (iterator p, size_t n, char c);迭代器位置插入n个字符c

iterator insert (iterator p, char c);迭代器位置插入字符c

#include <iostream>
#include <string>
using namespace std;
int main()
{string s;s.push_back('h');//尾插字符s.push_back('e');cout << s << endl;s.append("llo");//尾插字符串s.append("world", 5);cout << s << endl;s.assign("excuse me");//赋值cout << s << endl;string s2;string s3 = "world";s2.insert(0, "hello");//在0位置插入字符串cout << s2 << endl;s2.insert(s3.size(), s3);cout << s2 << endl;s3.insert(0, 1, 'h');//0位置插入1个字符hs3.insert(s3.begin() + 1, 1, 'e');//迭代器+1位置插入1个字符es3.insert(s3.begin() + 2, 2, 'l');//迭代器+2位置插入2个字符ls3.insert(s3.begin() + 4, 'o');//迭代器+4位置插入字符ocout << s3 << endl;return 0;
}

3.4.2 operator+=

函数原型(重载):

string& operator+= (const string& str);尾插字符串

string& operator+= (const char* s);尾插字符串

string& operator+= (char c);尾插字符

#include <iostream>
#include <string>
using namespace std;
int main()
{string s;string s1 = "hello";s += s1;//尾插字符串s += ' ';//尾插字符空格s += "world";cout << s << endl;return 0;
}

 

3.4.3 c_str()

函数原型:

const char* c_str() const;返回指向数组的指针,该数组包含以空结尾的字符序列(即C字符串),数组中的值跟对象中的值一样。就是获取字符串,以c字符形式返回

#include <iostream>
#include <string>
using namespace std;
int main()
{string s1 = "hello";//const char* str=s1;×const char* str = s1.c_str();//✓cout << str << endl;return 0;
}

 

3.4.4 find+ npos && substr()

函数原型:

find:

size_t find (const string& str, size_t pos = 0) const;在pos位置查询字符串,默认从0开始

size_t find (const char* s, size_t pos = 0) const;在pos位置查询字符串,默认从0开始

size_t find (const char* s, size_t pos, size_t n) const;在pos位置查询字符串的前n个字符

size_t find (char c, size_t pos = 0) const;在pos位置查询字符,默认从0开始

若查询到字符串,则返回字符串的起始位置的下标,否则返回npos;

substr: 

string substr (size_t pos = 0, size_t len = npos) const;pos位置往后取len个字符返回给新对象,默认从0位置开始取。

#include <iostream>
#include <string>
using namespace std;
int main()
{string s("test1.cpp hello world");string s1("https://leetcode.cn/problems/ba-zi-fu-chuan-zhuan-huan-cheng-zheng-shu-lcof/description/");size_t pos1 = s1.find(':');//默认从0位置查询字符cout << s1.substr(0, pos1) << endl;;size_t pos2 = s1.find("/",pos1+3);//从Pos+3的位置查询字符串cout << s1.substr(pos1 + 3, pos2-pos1-3) << endl;//从POS+1位置取POS-POS1+3个字符cout << s1.substr(pos2 + 1)<<endl;//默认从0开始取POS2+1个字符cout << s.c_str() << endl;cout << s.substr(2)<<endl;size_t pos3 = s1.find("/");while (pos3 != string::npos){s1.replace(pos3, 1, "*");//pos3位置,替换一个字符pos3 = s1.find("/", pos3 + 1);}cout << s1 << endl;return 0;
}

 运行结果:

3.4.5 erase

string& erase (size_t pos = 0, size_t len = npos);从Pos位置删除len个字符,默认从0开始,默认删除所有字符

iterator erase (iterator p);删除迭代器位置的字符

iterator erase (iterator first, iterator last);删除迭代器区间的字符

#include <iostream>
#include <string>
using namespace std;
int main()
{string s("test1.cpp   hello world");cout << s << endl;s.erase(0,5);//从0位置删除5个字符cout << s << endl;s.erase(0, 4);//从0位置删除4个字符cout << s << endl;s.erase(s.begin());//删除迭代器位置cout << s << endl;s.erase(s.begin(), s.begin() + 2);//删除迭代器区间的字符cout << s << endl;s.erase();cout << s << endl;//s为空return 0;
}

 

end~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/573226.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

http认证

1.Digest认证 各字段含义&#xff1a; Nonce 服务器直接返回的数据 H1MD5(user”:”realmpassword) H2MD5(method”:”url) method为请求类型、url不包括域名 Nc 指当前的第几次请求&#xff0c;使用8位16进制显示 Cnonce 8位随机字符串 ResponseMD5(H1”:”nonce”:”…

机器学习 | 期望最大化(EM)算法介绍和实现

在现实世界的机器学习应用中&#xff0c;通常有许多相关的特征&#xff0c;但只有其中的一个子集是可观察的。当处理有时可观察而有时不可观察的变量时&#xff0c;确实可以利用该变量可见或可观察的实例&#xff0c;以便学习和预测不可观察的实例。这种方法通常被称为处理缺失…

[串联] MySQL 存储原理 B+树

InnoDB 是一种兼顾高可靠性和高性能的通用存储引擎&#xff0c;在 MySQL 5.5 之后&#xff0c;InnoDB 是默认的 MySQL 存储引擎。 InnoDB 对每张表在磁盘中的存储以 xxx.ibd 后缀结尾&#xff0c;innoDB 引擎的每张表都会对应这样一个表空间文件&#xff0c;用来存储该表的表结…

【Postman如何进行接口测试简单详细操作实例】

1、下载Postman postman下载地址&#xff1a;Download Postman | Get Started for Free 2、安装Postman (1)双击下载好的postman-setup.exe文件&#xff0c;进行安装postman工具 (2)安装完成后&#xff0c;在桌面找到并打开postman软件&#xff0c;输入邮箱和密码进行登录&a…

(七)图像的均值滤波

环境&#xff1a;Windows10专业版 IDEA2021.2.3 jdk11.0.1 OpenCV-460.jar 系列文章&#xff1a; &#xff08;一&#xff09;PythonGDAL实现BSQ&#xff0c;BIP&#xff0c;BIL格式的相互转换 &#xff08;二&#xff09;BSQ,BIL,BIP存储格式的相互转换算法 &#xff08;三…

WIFI驱动移植实验:将 rtl8188EUS驱动添加到 Linux 内核中

一. 简介 正点原子的 I.MX6U-ALPHA 开发板目前支持两种接口的 WIFI &#xff1a; USB 和 SDIO &#xff0c;其中 USB接口的WIFI 使用使用的芯片为 RTL8188EUS 或 RTL8188CUS &#xff0c; SDIO 接口的 WIFI 使用芯片为 RTL8189FS &#xff0c;也叫做 RTL8189FT…

【保姆级讲解如何Chrome安装Vue-devtools的操作】

&#x1f308;个人主页:程序员不想敲代码啊&#x1f308; &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家&#x1f3c6; &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提…

下拉选中搜索angularjs-dropdown-multiselect.js

需要引入angularjs-dropdown-multiselect.js 页面 <div ng-dropdown-multiselect"" options"supplierList_data" selected-model"supplierList_select" events"changSelValue_supplierList" extra-settings"mucommonsetti…

鸿蒙HarmonyOS应用开发之Node-API常见问题

ArkTS/JS侧import xxx from libxxx.so后&#xff0c;使用xxx报错显示undefined/not callable 排查.cpp文件在注册模块时的模块名称与so的名称匹配一致。 如模块名为entry&#xff0c;则so的名字为libentry.so&#xff0c;napi_module中nm_modname字段应为entry&#xff0c;大小…

【Linux】网络基础1

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;题目解析 目录 &#x1f449;&#x1f3fb;一些常见网络设备&#x1f449;&#x1f3fb;网络协议(栈)&#x1f449;&#x1f3fb;协议分层OSI参考模型每个层…

线程局部存储(TLS)

线程局部存储&#xff08;Thread Local Storage&#xff0c;TLS&#xff09;&#xff0c;是一种变量的存储方法&#xff0c;这个变量在它所在的线程内是全局可访问的&#xff0c;但是不能被其他线程访问到&#xff0c;这样就保持了数据的线程独立性。而熟知的全局变量&#xff…

【jmeter+ant+jenkins】之搭建 接口自动化测试平台

平台搭建 (1). 录制jmeter脚本 (2). 将jmeter的安装目录下的G:\jmeter\apache-jmeter-5.1.1\extras中&#xff0c;将 ”ant-jmeter-1.1.1.jar”文件放到 ant的lib目录下 (3). 配置jmeter的xml配置文件&#xff0c;并放在ant目录的bin目录下&#xff0c;使用ant编译验证jmeter的…