【我与string的第一次见面】

【我与string的第一次见面】_第1张图片

文章目录

  • 前提:STL是啥
  • string类
    • 编码
    • string常用接口
      • string类对象的常用构造
      • 迭代器(iterator)通用的访问方式
        • 正向迭代器
        • 反向迭代器
        • const 迭代器
      • string类对象的相关操作
        • string类对象的容量操作
          • resize的功能
          • empty的功能
          • shrink_to_fit的功能
        • string类对象的修改操作
          • push_back、append、operator+=的功能
          • reserve的功能
          • insert,erase的常见功能
          • assign和replace的差别
          • **c_str作为指针的用法**
          • rfind和substr
        • 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 Systems,Inc公司开发,继承自HP版 本。被GCC(Linux)采用,可移植性好,可公开、修改甚至贩卖,从命名风格和编程 风格上看,阅读性非常高。**我们后面学习STL要阅读部分源代码,主要参考的就是这个版本。

三、STL的六大组件

【我与string的第一次见面】_第2张图片

四、stl的缺陷

  1. STL库更新慢。上一版靠谱是C++98,中间的C++03基本一些修订。C++11出来已经相隔了13年,STL才进一步更新。

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

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

  4. **STL的使用会有代码膨胀的问题。**比如使用vector/vector/vector这样会生成多份代码,当然这是模板语法本身导致的。

string类

C语言中,字符串是以’\0’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。

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

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

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

  4. 不能操作多字节或者变长字符的序列。在使用string类时,必须包含#include头文件以及 using namespace std;

编码

ASCALL-美国信息交换标准编码

编码:计算机存值(01)–对应关系–文字符号

然而ascall码的一个字符只占用1个字节【2^8-256】种对应关系,仅仅能满足美国(英文)的需求。

【我与string的第一次见面】_第3张图片

所以ascall码并不能满足我们博大精深的汉字。随之运营而生的出现了万国码(又称统一码)

万国码

其中有UTF-8(兼容ascall码)-最常用,UTF-16,UTF32

咱们中国也编了一套计算机编码-GBK字库-专门针对中文的编码(双字符编码)

GBK

string常用接口

string类对象的常用构造

函数名称 功能
string()【括号省略则为无参字符串】 空字符串
string(const char*s) 用字符串来构造string对象
string(size_t,char c) 用size_t个字符c来构造string对象
string(const string&s) 拷贝构造函数

演示如下图

【我与string的第一次见面】_第4张图片

【我与string的第一次见面】_第5张图片

迭代器(iterator)通用的访问方式

【我与string的第一次见面】_第6张图片

正向迭代器

注意:正向迭代器用的bigin()和end()要搭配出现!【我与string的第一次见面】_第7张图片

反向迭代器

注意:反向迭代器用的rbigin()和rend()要搭配出现!

【我与string的第一次见面】_第8张图片

到这里会有人吐槽道这一串代码也太长了,迭代器真不好用…;这里有接收到s1.begin( )的返回值,那就可以用auto通过返回值推导类型拉!

【我与string的第一次见面】_第9张图片

const 迭代器

【我与string的第一次见面】_第10张图片

综上我们可以作出迭代器表格总结

迭代器(都可以用auto推导) 非const const
正向 (正向)可遍历可读可写begin(),end() (正向)可遍历可读不可写cbegin(),cend()
反向 (反向)可遍历可读可写rbegin(),rend() (反向)可遍历可读不可写crbegin(),crend()

通过这里我们还可以总结一个规律:

需要的功能 实现
可读可写 实现可读(cosnt) 和可写两个版本
只可读不需要可写 *实现*可读(const)一个版本
只需要可写不需要可读 实现可写版本

string类对象的相关操作

string类对象的容量操作

【我与string的第一次见面】_第11张图片

函数名称 功能(单位:字节)
size 返回字符串有效长度
length 返回字符串有效长度
capacity 返回空间(容量)总大小
max_size 返回可用最大空间大小(42亿9千万)
clear 清除有效字符
reverse(n) 为字符串预留n个空间
resize(n,初始化的内容) 把有效字符个数改为n个,若有初始化的内容则在有效字符之后的空间用其填充;初始化的内容省略时,则用/0(/0不显示)填充,。
empty 检查字符串是否为空,若为空则返回true,不为空则返回false
shrink_to_fit 把字符串的capacity减少或增加为满足size大小的容量

【我与string的第一次见面】_第12张图片

resize的功能

【我与string的第一次见面】_第13张图片

因此我们做出resize功能的表格

resize(n)
n 从后往前只保留n个当前有效字符
size size
n>capacity 对字符串扩容,size和capacity增大
empty的功能

【我与string的第一次见面】_第14张图片

【我与string的第一次见面】_第15张图片

shrink_to_fit的功能

【我与string的第一次见面】_第16张图片

string类对象的修改操作

这里可以对照各个接口查看文档

【我与string的第一次见面】_第17张图片

在这里我们也列一个表格

push back 在字符串尾插字符
append 在字符串后追加一个字符串
operator+= 在字符串后追加字符、字符串str或者已有字符串(即同时具备push_back和append的功能)因此是最常用的
insert(size_t pos,const string& str) 在pos位置插入字符串或者字符(较为常用)
assign 给字符串赋值
replace 替换字符串
c_str 返回c格式字符串(或者返回指向c格式字符串的指针)
find(pos,‘c’)+npos 从字符串pos位置开始往后找字符c,找到返回该字符c下标,没有则返回npos
rfind(pos,‘c’)+npos 从字符串pos位置开始往前找字符c,找到返回该字符c下标,没有则返回npos
substr(pos,n) 从pos位置开始,往后截取n个字符,作为字符串返回,不给n则以缺省值输出到结尾
push_back、append、operator+=的功能

【我与string的第一次见面】_第18张图片

我们对psuh_back的功能进行刨析:

【我与string的第一次见面】_第19张图片

在这里我们可以做个实验,初始化一个字符串s,然后一直往字符串里尾插字符c,尾插1000次,然后检测字符串容量;我们可以看到右边显示每次字符串容量扩容是大概按照1.5倍capacity开辟的(vs编译器底下开辟容量只考虑有效字符串大小,不考虑/0)。

我们知道push_back会在插入字符之前先检查空间够不够大小,不够会去扩容,而这里会造成多次开辟空间,会造成很大的损失。如果我们提前知道了要存入字符串大小呢?是不是可以预先在push_back之前先开辟一块空间,然后再往这块空间尾插呢?
这里就要用到上面提到的reserve;这样就不用多次开辟空间,减少损害。

reserve的功能

【我与string的第一次见面】_第20张图片

insert,erase的常见功能

【我与string的第一次见面】_第21张图片

assign和replace的差别

【我与string的第一次见面】_第22张图片

assign是清空字符串所有内容,然后再将新内容填充;replace是替换文本,可以不清空所有内容。

leetcode上面有一题:把空格换成%20;当时用c写非常难受,现在咱用c++写一下。

find的常用接口:find(要找的内容,找的起始位置(没写则默认从第一个位置开始找)):在字符串里面找相应内容,找到了返回下标,没找到返回npos

【我与string的第一次见面】_第23张图片

是不是舒服了很多呀!

c_str作为指针的用法
void test_string11()
{
	//c_str作为指针用-可以打印该test.c文件的内容
	{
		string file("test.cpp");
		FILE* fout = fopen(file.c_str(), "r");
		assert(fout);
		char ch = fgetc(fout);
		while (ch != EOF)
		{
			cout << ch;
			ch = fgetc(fout);
		}
		fclose(fout);
	}
}
rfind和substr

【我与string的第一次见面】_第24张图片

string类非成员函数

【我与string的第一次见面】_第25张图片

getline 以/n为结尾获取一行字符

【我与string的第一次见面】_第26张图片

对于string类的第一次见面到这里为止了;这次鸽了半个月没有更新博客,现在回来继续更新优质内容!(坚决不当,从我做起!)

你可能感兴趣的:(c++,c++,开发语言)