【C++】C++标准模板库STL (一) string类的使用详解(1)

简介: 【C++】C++标准模板库STL (一) 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的六大组件

二、string类的介绍

string类是STL中的容器,也是我们学习STL的开始。

1. 为什么学习string类

  • C语言中的字符串
    C语言中基本类型有char类型没有字符串类型,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数(如:strlen, strcmp,strcat,strcpy 等),但是这些库函数与字符串是分离开的,不太符合OOP(面向对象)的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。

因此为了更加高效的使用和管理字符串,C++提出了string类的概念,关于string类的学习我们先学习string类的使用,后面我们进一步深入时我们再去动手模拟实现string类,在这里我们首先知道string类的底层其实就是char类型的顺序表就行了。

2. 标准库中的string类

string类的文档介绍

从文档中我们能看到:

  1. string类basic_string模板类的一个实例,它使用char来实例化basic_string模板类。
  2. string在底层实际是:basic_string模板类的别名,typedef basic_string<char>string;
  3. 不能操作多字节或者变长字符的序列。(如英文使用ASCII编码使用一个字节表示一个字母,汉字如果采用GBK编码占用两个字节表示一个汉字)
  4. 处理多字节或者变长字符的序列要用到以下三个类:
  5. 在使用string类时,必须包含 #include<string>以及using namespace std;

三、string类的常用接口说明

在上面的string类的文档介绍中我们可以看到string类接近有140个不同的接口函数,在这么多的成员函数中,很多都是冗余不必要的,因此下面我只讲解最常用的接口。

在讲解这些函数接口之前,我们先来介绍nposnposstring类里面的一个静态成员变量,因此用string类创建的所有对象访问的都是同一个npos,其次我们来看pos的定义:

首先npos的值是被const修饰了,其值不能更改,然后size_t是无符号整形unsignedtypedef,定义将-1的值赋值给了npos,但npos是无符号整形,因此此时nops的值就是无符号整形的最大值65535。

1. string类对象的常见构造函数

  1. 缺省构造函数,用空字符串初始化string对象
  2. 拷贝构造函数,用string类的对象另一个对象
  3. string类的对象中的字符串的子串初始化一个对象,子串的起始位置是pos,结束位置是pos向后的len个字符,如果len没有给缺省值,默认为npos即从pos位置后面有多少拿多少。
  4. 用C风格的字符串初始化string类的对象
  5. 用C风格的字符串前n个字符初始化string类的对象
  6. 用n个字符初始化string类的对象
#include<iostream>
#include<string>
using namespace std;
int main()
{
  string s0("hello world!");
  string s1;          //default (1)   缺省构造函数   
                //用空字符串初始化s1对象  
  string s2(s0);        //copy (2)      拷贝构造函数   
                //用string类的对象s0初始化s2对象
  string s3(s0, 6, 5);    //substring (3)   用string类的对象s0的字符串的子串"world"初始化s3  
                //这里pos参数表示位置,len表示的是个数
  string s4("hello string");  //from c-string (4) 
                //C风格的字符串初始化string类的对象s4
  string s5("hello world",5); //from sequence(5)  
                //用C风格的字符串前五个字符"hello"初始化string类的对象s5
  string s6(5, 'x');      //fill (6)  
                //用5个'x'初始化string类的对象s6
  cout << s0 << endl;
  cout << s1 << endl;
  cout << s2 << endl;
  cout << s3 << endl;
  cout << s4 << endl;
  cout << s5 << endl;
  cout << s6 << endl;
}


2. string类对象的容量操作

  • 我们先来看看不涉及扩容的函数
#include<iostream>
#include<string>
using namespace std;
int main()
{
  string s1("hello world");
  cout << s1.size() << endl;
  cout << s1.length() << endl;
  cout << s1.capacity() << endl;
  cout << s1.max_size() << endl;
  s1.clear();
  cout << s1.empty() << endl;
  return 0;
}

  • 我们再来看看涉及扩容的函数
  1. std::string::reserve()函数与std::string::shrink_to_fit()函数
//std::string::reserve()函数
#include<iostream>
#include<string>
using namespace std;
int main()
{
  string s1("hello world");
  cout << s1.size() << endl;
  cout << s1.capacity() << endl;
  s1.reserve(200);  //提前把空间扩容到200字节,但不初始化
            //由于string类内部的一些原因(如:对齐等原因),虽然向系统申请的的200字节,
            //但不一定就是200字节,总之系统申请的空间会 >= 你给的指定值
  cout << s1.size() << endl;
  cout << s1.capacity() << endl;
  s1.shrink_to_fit(); //缩减容量让 size == capacity
  cout << s1.size() << endl;
  cout << s1.capacity() << endl;
  return 0;
}

观察会发现,经过reserve()函数的处理后size(字符个数)没有变,但是capacity(容量)改变了。

经过shrink_to_fit()函数处理后size(字符个数)没有变,但是capacity(容量)改变了。(虽然,shrink_to_fit()函数能够减少空间的浪费,但是我们还是一般不缩容,因为缩容的消耗是很大的)

相关文章
|
2天前
|
域名解析 网络协议 程序员
程序员必知:【转】adns解析库——域名解析实例(C++、linux)
程序员必知:【转】adns解析库——域名解析实例(C++、linux)
11 0
|
2天前
|
C++ 容器
C++ STL标准库 《map容器详解》
C++ STL标准库 《map容器详解》
7 0
|
2天前
|
存储 C++ 容器
C++ STL标准库 《map容器详解》
C++ STL标准库 《map容器详解》
7 0
|
2天前
|
缓存 C++
详细解读C++常用库函数C函数库cstdio
详细解读C++常用库函数C函数库cstdio
|
2天前
|
域名解析 网络协议 程序员
程序员必知:【转】adns解析库——域名解析实例(C++、linux)
程序员必知:【转】adns解析库——域名解析实例(C++、linux)
|
2天前
|
C语言 C++
【c++】string模拟实现(2)
【c++】string模拟实现(2)
6 0
|
2天前
|
算法 C++
【c++】string模拟实现(1)
【c++】string模拟实现(1)
6 0
|
5天前
|
Java UED
Java中String强转int:一种常见的错误和解决方法
在Java中将非数字字符串转换为整数会导致`NumberFormatException`。要解决这个问题,可以使用`try-catch`捕获异常,正则表达式验证数字格式,或利用异常信息提供错误提示。例如,`Integer.parseInt()`会因遇到非数字字符如`&quot;123abc&quot;`而抛出异常,但通过异常处理或正则`\\d+`可确保安全转换。记得在编程时避免直接强转,以防止程序异常中断。
|
1天前
|
安全 Java
Java基础之StringBuffer
Java中的`StringBuffer`是线程安全的可变字符串,适用于多线程环境,其方法同步导致较慢。`StringBuilder`在Java 5引入,非线程安全但更快,适合单线程操作。两者均提供append、insert、delete等方法。在不需要线程安全时,选择`StringBuilder`以提升效率。
8 1
|
4天前
|
Java 数据处理 Apache
探讨Java中判断String类型为空和null的方法
探讨Java中判断String类型为空和null的方法
11 1