C++STL之string类的使用

目录
  • 1.STL简介
    • (1)什么是STL
    • (2)STL的版本
    • (3)如何学习STL
    • (4)STL的六大组件
  • 2.string类的基本概念
    • (1)含义
    • (2)使用方法
    • (3)原理
  • 3.string类中常见构造函数
  • 4.string类中析构函数
  • 5.string类对象的容量操作
    • (1)显示容量
    • (2)扩容
  • 6.string类中operator[]重载
    • (1)举例
    • (2)底层实现
  • 7.string类与迭代器
    • (1)举例
    • (2)反向迭代器
    • (3)使用迭代的意义
    • (4)补充:语法糖实现遍历
  • 8.string类对象的增删操作
    • (1)增删
    • (2)查与匹配
  • 9.string类中自定义插入与删除(效率低,不建议使用)
  • 10.string类字符串的比较
  • 11.string类字符串的转换
  • 12.总结

1.STL简介

(1)什么是STL

STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。
可以理解为就是一个类似stdio.h的库,包含了这个库,里面的语法或者函数可以直接使用。

(2)STL的版本

最原始的版本是由Alexander Stepanov和Meng Lee开发的,并且他们要求对其进行开源处理。之后又经历了PJ.版本,RW版本,SGI版本等,目前SGI版本最应用最广泛的版本,我们后面学习STL要阅读部分源代码,主要参考这一版本。

总结一下目前开源与闭源的操作系统或者软件:

开源:STL,linux,git,Vue
闭源:IOS,Windows

(3)如何学习STL

第一境界:熟练使用STL。

第二境界:了解STL的源代码,即了解底层。

第三境界:会自己扩充STL库。

废话不多说,正式进入主题:

(4)STL的六大组件

STL有六大组成部分,我们会来逐一学习:

首先我们来学习容器中的string类。

2.string类的基本概念

(1)含义

string类,顾名思义是进行字符串操作的一个,操作方式即使用其中的成员函数来进行操作。

(2)使用方法

#include<string>
using namespace std;

string也是在类域std中的,我们在练习时也可以将类域std打开。

(3)原理

通过查阅文献,我们发现string类原来是typedef出来的,是对basic_string这一模板传入char类型时起的别名。这一模板的定义方式大概是这样的:

template<class T>
class basic_string
{
private:
T* _str;
//....
}

有人会问为什么要使用模板呢?字符串类型除了char还有别的嘛?

其实字符类型除了char之外还有别的类型,比如wchar_t就占两个字节。我们存储汉字一般会使用两个字节来进行存储。所以对于两字节存储的字符再使用basic_string传入wchar_t起别名的话就方便的多了。

注意:string类中传入的是char,上面只作了解即可。

3.string类中常见构造函数

构造函数即用于初始化。

1.string():构造空的string类对象str,即空字符串。

2.string (const char* s):向对象中传入字符串来构造string对象。

3.string(size_t n,char c):string类对象中包含n个字符c。

4.string(const string&s):拷贝构造函数。

    string s1;//空字符串s1。
	string s2("hello world");//向s2中传入hello world。
	string s3(s2, 2, 6);//向s3中传入s2中从第二个开始(不包括第二个)后六个字符。当最后不加数值时(即不加6),则会取后面的全部字符。
	string s4(s2);//用s2对s4进行初始化。
	cout << s1 << endl;//重载运算符,可以直接打印s1对象的字符串内容。
	cout << s2 << endl;
	cout << s3 << endl;
	cout << s4 << endl;

4.string类中析构函数

自动调用,不用管。

5.string类对象的容量操作

1.size:返回有效字符长度。

2.length:返回字符串的有效字符长度。是一个历史残留问题。

3.capacity:返回空间总大小。

4.empty:检测字符串是否为空,是返回true,不是返回false

5.clear:清空有效字符。

6.reserve:为字符串预留空间。

7.resize:将有效字符改成n个,多出的用字符C填充。

(1)显示容量

    string s1("hello world");
	cout << s1.size() << endl;//输出字符串大小,不包括'\0'
	cout << s1.length() << endl;//输出字符串大小,不包括'\0'
	cout << s1.capacity() << endl;//输出空间总大小
	s1.clear();//清空有效字符串
	cout << s1 << endl;

(2)扩容

扩容一般使用两种函数,reserve与resize。reserve主要为开空间,而resize在开空间的同时还会进行初始化。

string s1("hello world");
cout << s1.capacity() << endl;
s1.reserve(100);
cout << s1.capacity() << endl;

打印的结果是:

通过打印我们发现,reserve扩展的空间是在原有字符串大小基础上扩展的,而不是在原有容量的基础上。

string s1("hello world");
s1.resize(100,'x');

我们可以通过调试来观察这段代码的效果:

我们发现hello world并没有被覆盖,最大空间变成了111和reserve一样。但是,x只有89个,一共增加了100-11个x,但是在hello world后面增加了100个空间。

如果我们开辟的空间小于字符串本身呢?s1.resize(5)表示的是只保留前五个字符大小。

6.string类中operator[]重载

(1)举例

我们可以使用s1[i]来进行字符的读或者写的操作。

     string s1("hello world");
	for (size_t i = 0; i < s1.size(); i++)
	{
		cout << s1[i] << " ";//s1[i]进行读操作
		s1[i] += 1;
	}
	cout << endl;
	for (size_t i = 0; i < s1.size(); i++)
	{
		cout << s1[i] << " ";//s1[i]进行写操作
	}

(2)底层实现

char& operator[](size_t pos)
{
      return _str[pos];//返回pos位置所在的字符
}

注意,这里使用引用返回不是为了减少拷贝,这里是为了修改返回对象。

at也是和operator[]一样,但是检测越界的方法不同,operator[]使用断言,at直接抛异常。

7.string类与迭代器

(1)举例

在刚开始使用迭代器时,我们可以把它想象成一个指针类型。

    string s1("hello world");
	string::iterator it = s1.begin();
	while (it != s1.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

其中it就是一个迭代器类型的变量,由于函数iterator在类内,因此在使用时需要首先指明类域。

我们仍然使用解引用操作符来进行类似解引用的操作。我们同样也可以通过*来对字符串的内容进行修改,对这段代码打印的结果是:

(2)反向迭代器

反向迭代器使用函数reverse_iterator

    string s1("hello world");
	string::reverse_iterator rit = s1.rbegin();
	while (rit != s1.rend())
	{
		cout << *rit;
		++rit;
	}

打印的结果是刚好反过来的:

注意:我们定义反向迭代器rit之后,在进行遍历时虽然是从后向前遍历,但是仍需要对rit进行++操作。

(3)使用迭代的意义

迭代的意义主要体现在和[]进行对比,有人可能认为既然可以用下标直接引用,为什么还要使用迭代器呢?

这是因为对于string来说,下标和[]就足够好用,可以不使用迭代器,但是对于其他容器,比如list map/set等不支持下标加[]遍历,比如对于链表来说,由于物理内存不连续所以不能使用下标来进行遍历。

除了普通迭代器之外,还有const修饰的迭代器等等。后面会详细说明的。

(4)补充:语法糖实现遍历

除了使用迭代器遍历之外,我们还可以使用语法糖来进行遍历操作:

    string s1("hello world");
	for (auto& e : s1)
	{
		cout << e << " ";
	}

范围for会把s1中的每一个字符取出来赋值给e(使用引用则为它本身),自动往后迭代,自动判断结束。

8.string类对象的增删操作

push back:在字符串后尾插字符c

append:在字符串后追加一个字符串

operator+=:在字符串后追加字符串str

c str:返回C格式字符串

find+nops:从字符串pos位置开始往后找字符c,返回该字符再字符串中的位置。

rfind:从字符串中pos位置开始往前找字符c,返回该字符再字符串中的位置。

substr:在str中从pos位置开始,截取n个字符,然后将其返回。

(1)增删

    string s1("hello world");
	s1.push_back('a');//在末尾插入字符a
	cout << s1 << endl;
	s1.append("bcd");//在末尾插入字符串bcd
	cout << s1 << endl;
	s1 += 'e';//在末尾插入字符e
	cout << s1 << endl;
	s1 += "hello linux";//在末尾插入字符串hello linux
	cout << s1 << endl;

注意:推荐直接使用操作符重载进行增删操作。

(2)查与匹配

下面是一段字符串截取的代码,截取后缀.txt:

    string file("test.txt");
	size_t pos = file.find('.');//返回第一次匹配'.'的位置
	if (pos != string::npos)
	{
		string suffix = file.substr(pos, file.size() - pos);//将.之后的内容赋值给suffix
		cout << suffix << endl;
	}

find会返回第一次出现匹配的位置,如果匹配失败会返回nops(无符号-1,表示一个极大的数)。

substr是字符串截取函数,意思是截取pos位置与file.size()-pos位置的字符串。

同上,我们也可以使用rfind进行倒着查找。

这里再举一个截取网址的例子:

我们都知道网址分为三部分:协议,域名与网络路径。下面使用find与substr来进行截取操作。

    string url("http://www.cplusplus.com/reference/string/string/find/");
	size_t pos1 = url.find(':');
	string protocol = url.substr(0, pos1 - 0);
	cout << protocol << endl;
	size_t pos2 = url.find('/', pos1 + 3);//从pos+3的位置开始找
	string domain = url.substr(pos1 + 3, pos2 - (pos1 + 3));
	cout << domain << endl;
	string uri = url.substr(pos2 + 1);//没指定结尾位置,默认为整个后面内容
	cout << uri << endl;

打印的结果为:

9.string类中自定义插入与删除(效率低,不建议使用)

使用insert与erase两函数进行操作:

    string s("hello world");
	s.insert(0, 1, 'x');//在0位置插入一个1
	s.insert(s.begin(), 'y');//在头处插入一个y
	s.insert(0, "test");//在头处插入test
	s.insert(4, "&&");//在第四个位置插入特殊符号
	s.erase(0, 1);//删除头处第一个字符
	s.erase(s.size() - 1, 1);//尾删一个字符
	cout << s << endl;

打印的结果为:

在使用erase时,如果不给值的话,会继续删完。

尽量少使用头部和中间的删除,因为要挪动数据,效率较低。

10.string类字符串的比较

和C语言中strcmp一样,string类也有对字符串的比较,不过是通过运算符重载。

    string s1("hello world");
	string s2("string");
	cout << (s1 < s2) << endl;
	cout << ("hhh" > s2) << endl;

注意我们可以使用两种方式来说进行字符串比较,一种是s1<s2,另一种是直接进行比较。

与strcmp原理一样,会从两个字符串起始位置开始比较,如果为真则返回1,如果为假返回0。

11.string类字符串的转换

我们使用stoi(string to int)来将字符串转为整型,使用to_string来将其他类型转换为字符串。

    int val = stoi("1234");
	string str = to_string(3.14);

我们可以通过调试来观察转换是否成功:

可见,转换很成功。

12.总结

string类是表示字符串的字符串类,在使用string类时必须包含头文件,并开放std空间,在OJ中有关字符串的题目基本以string类的形式出现,而且在常规工作中,为了简单、方便、快捷,基本都会使用string类,很少有人去使用C库中的字符串操作函数。

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • 关于C++STL string类的介绍及模拟实现

    目录 一.标准库中的string类 1.string类 2.string类中的常用接口说明+模拟实现 2.1 string类对象的常见构造+模拟实现 2.2 string类对象的容量操作+模拟实现 2.3 string类对象的访问及遍历操作+模拟实现 2.4 string类对象的修改操作+模拟实现 2.5 string类非成员函数+模拟实现 一.标准库中的string类 1.string类 字符串的表示字符序列的类 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专

  • 一起来看看C++STL容器之string类

    目录 前言 1.标准库中的string类 2.string类的常用接口说明 2.1string对象的常见构造 2.2string类对象的容量操作 2.2.1reserve是如何开辟空间的 2.2.2clear和empty 2.2.3resize的用法 2.3string类对象的访问以及遍历操作 范围for的使用 2.4string类对象的修改操作 2.4.1push_back和append以及operator+= 2.4.2 find和rfind以及substr 2.5string非成员函数重载

  • zlib库压缩和解压字符串STL string的实例详解

    zlib库压缩和解压字符串STL string的实例详解 场景 1.一般在使用文本json传输数据, 数据量特别大时,传输的过程就特别耗时, 因为带宽或者socket的缓存是有限制的, 数据量越大, 传输时间就越长. 网站一般使用gzip来压缩成二进制. 说明 1.zlib库可以实现gzip和zip方式的压缩, 这里只介绍zip方式的二进制压缩, 压缩比还是比较可观的, 一般写客户端程序已足够. 2.修改了一下zpipe.c的实现, 其实就是把读文件改为读字符串, 写文件改为写字符串即可. 例子

  • STL 的string类怎么啦

    STL 的string类怎么啦?陈皓 前言 上个周末在和我的同学爬香山闲聊时,同学说到STL中的string类曾经让他备受折磨,几年前他开发一个系统前对string类还比较清楚,然后随着程序的复杂度的加深,到了后期,他几乎对string类失去了信心和信任,他觉得他对string类一头雾水.老实说,我几年前也有同样的痛苦(就是当我写下<标准C++类string的Copy-On-Write技术>之前的一段时间).那时,我不得不研究那根本不是给人看的SGI出品的string类的源码,代码的可读性几乎

  • STL中的string你了解吗

    目录 模拟实现一个string类 成员变量 构造函数 遍历 与容量相关的成员函数 运算符的重载 修改器 常用的几个字符串函数 总结 STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架. STL的六大组件:容器.迭代器.适配器.空间配置器.仿函数.算法. string的行为与普通容器类似,但是并不能说它是个容器,因为无法接受所有类型的数据. string是表示字符串的字符串类. s

  • C++STL之string类的使用

    目录 1.STL简介 (1)什么是STL (2)STL的版本 (3)如何学习STL (4)STL的六大组件 2.string类的基本概念 (1)含义 (2)使用方法 (3)原理 3.string类中常见构造函数 4.string类中析构函数 5.string类对象的容量操作 (1)显示容量 (2)扩容 6.string类中operator[]重载 (1)举例 (2)底层实现 7.string类与迭代器 (1)举例 (2)反向迭代器 (3)使用迭代的意义 (4)补充:语法糖实现遍历 8.strin

  • 分享C++面试中string类的一种正确写法

    具体来说: 能像 int 类型那样定义变量,并且支持赋值.复制. 能用作函数的参数类型及返回类型. 能用作标准库容器的元素类型,即 vector/list/deque 的 value_type.(用作 std::map 的 key_type 是更进一步的要求,本文从略). 换言之,你的 String 能让以下代码编译运行通过,并且没有内存方面的错误. 复制代码 代码如下: void foo(String x)  {  } void bar(const String& x)  {  } Strin

  • 探究C++中string类的实现原理以及扩展使用

    C++程序员编码过程中经常会使用string(wstring)类,你是否思考过它的内部实现细节.比如这个类的迭代器是如何实现的?对象占多少字节的内存空间?内部有没有虚函数?内存是如何分配的?构造和析构的成本有多大?笔者综合这两天阅读的源代码及个人理解简要介绍之,错误的地方望读者指出. 首先看看string和wstring类的定义: typedef basic_string<char, char_traits<char>, allocator<char> > string

  • 代码分析c++中string类

    一:回顾 (1)c++中的string类是在面试中和笔试中经常考的题目: 工程代码免费下载 string类的自行实现 (2)c++中的string类和fstream类合起来是处理外部数据的利器: (3)string类经常用到find find_first_of find_first_not_of find_last_of find_last_not_of substr replace等,以及联合使用来达到java中的split和trim (4) 使用friend 仅仅是在类中进行声明的非内部 却

  • C++中的string类(C++字符串)入门完全攻略

    前言 string 类是 STL 中 basic_string 模板实例化得到的模板类.其定义如下: typedef basic_string <char> string; basic_string 此处可以不必深究. string 类的成员函数有很多,同一个名字的函数也常会有五六个重载的版本.篇幅所限,不能将这些原型一一列出并加以解释.这里仅对常用成员函数按功能进行分类,并直接给出应用的例子,通过例子,读者可以基本掌握这些成员函数的用法. 要想更深入地了解 string 类,还要阅读 C++

  • C++ STL之string的模拟实现实例代码

    目录 前言 构造函数 析构函数 拷贝构造函数 operator=赋值运算符重载 c_str operator[] size() capacity() empty() operator+= 扩容函数(reserve) resize() push_back() append() insert() erase() find() 1.查找一个字符 2.查找一个字符串 substr() 比较大小函数 总结 前言 上一章我们对string的常见接口及使用进行了讲解,接下来我们将对一些常见的接口,包括构造函数

  • C++中的string类的用法小结

    相信使用过MFC编程的朋友对CString这个类的印象应该非常深刻吧?的确,MFC中的CString类使用起来真的非常的方便好用.但是如果离开了MFC框架,还有没有这样使用起来非常方便的类呢?答案是肯定的.也许有人会说,即使不用MFC框架,也可以想办法使用MFC中的API,具体的操作方法在本文最后给出操作方法.其实,可能很多人很可能会忽略掉标准C++中string类的使用.标准C++中提供的string类得功能也是非常强大的,一般都能满足我们开发项目时使用.现将具体用法的一部分罗列如下,只起一个

随机推荐