C++ STL:string类的概述及常用接口说明

news/2025/3/15 3:33:02/

目录

一. 什么是STL

二. string类的概述

三. string类的常用接口说明

3.1 字符串对象创建相关接口(构造函数)

3.2 字符串长度和容量相关接口

3.3 字符访问相关接口函数

3.4 字符串删改相关接口函数

3.5 字符查找和子串相关接口函数

3.6 迭代器相关接口函数

3.7 常用的关于string类对象的全局函数


一. 什么是STL

STL,即标准库模板(standard template library),是C++标准库的重要组成部位,是一个包含了很多经常使用的数据结构和算法的软件框架。

C++标准规定的STL有六大组件:容器、迭代器、算法、仿函数、空间配置器和配接器,其中容器就是我们常说的数据结构。

图1.1 STL六大组件

二. string类的概述

string类,是专为用于存储和操作字符串的类,使用STL string容器的接口,可以实现对字符串进行增删查改、计算长度、循环遍历等操作。string类是模板类basic_string以char为模板参数类型的一个实例,其定义为:typedef basic_string<char> string。

那么或许会有人问:字符串的每个字符不都是char类型吗,那么直接将basic_string的参数类型定义为char不就行了吗,为什么还要定义模板再实例化?

其实,我们通常认为的char类型仅仅可以表示英文字母或字符,每个char类型数据的值,通过编码表(通常为ASCII码表)与特定字符对应,由于英文字母仅有26个,加上各种可打印字符不过128个,char类型数据完全足够对英文进行编码。

但是,其他语言就不一样了,中文汉字有几万几十万,char类型数据是无法表示的。因此,为了对汉字进行编码,就引入wchar_t型数据,一个wchar_t型数据占2byte,可以表示60000多个汉字,基本可以涵盖所有常见汉字。

因此,basic_string之所以不直接将成员变量类型设为char而是采用模板,就是为了能够实例化出不同类型的模板参数,以对应不同的编码规则,从而使其适用于全世界的语言。

常见的编码规则

编码:通过值与符号表建立映射关系,从而使值可以转换为各种字符。

  • ASCII码 -- 适用于英文。
  • unicode -- 全世界文字的通用编码表,又称万国码。它为世界各国语言的每个字符设置了统一且唯一的二进制编码。unicode下面有包括utf-8、utf-16、utf-32这几种细化的编码规则,他们分别表示以无符号的8、16、32个二进制位的数据进行编码。
  • gkb -- 为中文量身定制的编码表。

在Windows下,中文采用gkb编码规则,长字节w_char类型数据可用于中文编码。

三. string类的常用接口说明

3.1 字符串对象创建相关接口(构造函数)

  • string() -- 创建空字符串对象(仅包含字符串结束标识\0)。
  • string(const string& s) -- 拷贝构造,通过一个string类对象创建一个新的string类对象。注意string类的拷贝构造函数完成的是深拷贝,他会为新创建的对象再开辟一块内存空间,用于存储与s对象相同的字符,即:两者表示的字符串内容相同,但并不是存储在同一块空间的字符串。
  • string(const char* s) -- 通过一个现有的字符串构造string类对象。
  • string(const string& s, size_t pos, size_t len = npos) -- 通过一个string类对象的子字符串构建新的对象,子串的为:从下标pos开始为第一个字符,向后len个字符。缺省参数npos为string类的静态成员变量,值为size_t类型的-1(一个极大的数)。如果pos往后的字符数不足len,那么就用从pos往后的所有字符创建对象。
  • string(const char* s, size_t n) -- 用字符串s的前n个字符构建字符串。

演示代码3.1:

int main()
{string s1;   //空字符串构建string s2("abcdef");  //通过字符串创建对象string s3(s2);   //通过拷贝构造创建新对象string s4(s2, 1, 3);  //通过已有类对象的子串创建新对象 -- "bcd"string s5("abcdef", 3);   //通过字符串的前n个字符创建新对象 -- "abc"cout << "s1 = " << s1 << endl;cout << "s2 = " << s2 << endl;cout << "s3 = " << s3 << endl;cout << "s4 = " << s4 << endl;cout << "s5 = " << s5 << endl;return 0;
}
图3.1 演示代码3.1的运行结果

3.2 字符串长度和容量相关接口

  • size -- 获取字符串长度(不包括末尾\0),函数原型为:size_t size() const。
  • length -- 获取字符串长度(不包括末尾\0),函数原型为:size_t length() const。

在string类中,size和length没有任何区别。但是,size可以用在树、链表等其他数据结构中计算数据量,而length不行。为了保证STL中各种数据结构的接口名称统一,一般建议使用size。

  • capacity -- 获取当前string类对象能够存储的有效字符量,函数原型为:size_t capacity() const。
  • reserve -- 将字符串空间扩容到至少一定的值,函数原型为:void reserve(size_t n)。用reserve进行扩容,并一定恰好扩容到n,而是扩容到不小于n。同时,reserve不影响字符串中原来的内容,且不对扩大的那部分空间进行初始化,如果n小于原来的capacity,那么reverse函数不进行任何工作。
  • resize -- 使字符串的长度(size\length)变到n,函数原型为:void resize(size_t n)、void resize(size_t n, char ch),这两个函数构成重载。resize函数的工作为:将函数长度扩大到n,在将扩大的部分的内容改为ch,如果不给定ch值,则默认为'\0'。如果n小于原来的长度size,那么就截取前n个内容。
  • clear -- 清空字符串的内容,使字符串的长度(size\length)变为0。
  • empty -- 判断字符串是否为空。

演示代码3.2:

int main()
{string s1("abc");cout << "size = " << s1.size() << endl;cout << "length = " << s1.length() << endl;  //获取s1的长度cout << "capacity = " << s1.capacity() << endl;  //获取s1的容量cout << endl;s1.resize(10, 'x');cout << "s1 = " << s1 << endl;  //abcxxxxxxxcout << "size = " << s1.size() << endl;   //10cout << endl;s1.reserve(20);   //将s1的容量扩大到至少20cout << "capacity = " << s1.capacity() << endl;  // >=20cout << "size = " << s1.size() << endl;  //3cout << endl;cout << s1.empty() << endl;  //非0s1.clear();  //清空数据cout << s1.empty() << endl;  //0cout << "size = " << s1.size() << endl;  //0cout << "capacity = " << s1.capacity() << endl;  //31return 0;
}
图3.2  演示代码3.2的运行结果

3.3 字符访问相关接口函数

  • [] -- 下标引用操作符重载:char& operator[](size_t pos)、const char& operator[](size_t pos) const,两个函数构成重载,分别用于访问普通类对象和const类对象。
  • at -- 访问指定下标位置处的字符:char& at(size_t pos)、const char& at(size_t pos) const。

重载[]和at都可以达到访问某个下标位置处字符的目的,但是,当出现越界访问时,[]会assert断言出错,at会抛异常,且[]更符合一般的编码习惯,这里推荐使用[]而不是ar。

演示代码3.3:

int main()
{string s1("abcdef");const string s2("abcdef");//使用[],将s1的每个值+1for (size_t i = 0; i < s1.size(); ++i){s1[i] += 1;}cout << s1 << endl;  //bcdefg//[]访问const对象s2的每个字符,只能读不能写for (size_t i = 0; i < s2.size(); ++i){//s2[i] += 1;  //报错cout << s2[i];}cout << endl;//通过at函数,遍历打印s2的每个字符for (size_t i = 0; i < s2.size(); ++i){cout << s2.at(i);}cout << endl;return 0;
}
图3.3 演示代码3.3

3.4 字符串删改相关接口函数

  • operator+= -- 尾插字符或字符串
  1. string& operator+=(const string& s)  -- 通过类对象获取尾插字符串
  2. string& operator+=(const char* s) -- 直接尾插字符串s
  3. string& operator+=(char c) -- 尾插字符c
  • push_back -- 尾插字符。函数原型为:void push_back(char c)
  • append -- 尾插字符串或字符
  1. string& append(const string& s) -- 通过string类对象获取字符串尾插
  2. string& append(const char* s) -- 直接尾插字符串
  3. string& append(const string& s, size_t pos, size_t len = npos) -- 通过获取子字符串尾插
  4. string& append(const char* s, size_t n) -- 尾插字符串s的前n个字符
  • insert -- 在指定位置插入字符或字符串
  1. string& insert(size_t pos, const string& s) -- 在pos下标处通过string类对象插入字符串
  2. string& insert(size_t pos, const string& s, size_t subpos, size_t len = npos) -- 在pos位置处插入string对象的一个子字符串
  3. string& insert(size_t pos, const char* s) -- 在pos下标处插入字符串s
  4. string& insert(size_t pos, const char* s, size_t n) -- 在pos下标处插入s的前n个字符
  5. string& insert(size_t pos, size_t n, char c) -- 在pos位置处插入n个c字符
  • erase -- 从指定位置开始删除n个字符,函数原型:string& erase(size_t pos = 0, size_t len = npos)

演示代码3.4:

int main()
{string s1;s1 += "aaa";  //+=尾插字符串cout << s1 << endl;s1 += 'b';  //+=尾插单个字符cout << s1 << endl;s1.push_back('c');  //push_back尾插单个字符cout << s1 << endl;s1.append("ddd");  //append尾插字符串cout << s1 << endl;cout << endl;string s2("aaaaaaa");s2.insert(2, "bbbb");  //在下标2的位置插入字符串"bbbb"cout << s2 << endl;s2.erase(2, 4);   //从下标为2的位置开始删除4个字符cout << s2 << endl;return 0;
}
图3.4 演示代码3.4的运行结果

3.5 字符查找和子串相关接口函数

  • c_str -- 获取string类对象中的字符串成员(字符串首字符地址)。函数原型为:const char* c_str() const。
  • find -- 以指定下标位置pos为起点,从前向后查找特定字符或子字符串,找到了返回字符或子串第一次出现的下标,找不到就返回npos。
  1. size_t find(const string& s, size_t pos = 0) const -- 查找sting对象s的字符串。
  2. size_t find(const char* s, size_t pos = 0) const -- 查找字符串s。
  3. size_t find(const char* s, size_t pos, size_t len) const -- 查找字符串s的一个子串。
  4. size_t find(char c, size_t pos = 0) const -- 查找字符c。
  • refind -- 与find类似,从尾部开始,查找子字符串或字符第一次出现的下标位置。
  • substr -- string substr(size_t pos = 0, size_t len = npos) -- 从当前string对象中获取子串,构建一个新的string对象。

演示代码3.5:

int main()
{string s1("abcdefgh");cout << s1.c_str() << endl;  //获取字符串成员cout << s1.find("bcd") << endl;   //查找子串"bcd" -- 输出1cout << s1.find("cdeg", 2, 3) << endl;   //从下标2处开始查找"cdef"前3个字符构成的子串"cde" -- 输出2cout << s1.find('e') << endl;  //查找字符e -- 输出4cout << endl;string s2("abcdefabcdef");cout << s2.rfind("abc", 9) << endl;  //查找下标位置9之前pos最后一次出现的位置 -- 输出6cout << s2.rfind('e') << endl;  //查找字符'e'最后一次出现的位置 -- 输出10string s3("abcdef");string s4 = s3.substr(1, 4);cout << "s4 = " << s4 << endl;   //bcdereturn 0;
}
图3.5 演示代码3.5运行结果

3.6 迭代器相关接口函数

迭代器的类型为iterator,是char*的类型重定义名称,其定义语句为:typedef char* iterator -- 对于普通对象的迭代器,typedef const char* const_iterator -- 对于const属性对象的迭代器。除了一般的iterator以外,还有反向迭代器reverse_iterator和const_reverse_iterator。

对iterator类型的变量执行++操作,其指向的位置后移一位、对reverse_iterator类型的成员变量执行++操作,其指向的位置前移一位。

  • begin -- 获取指向字符串首元素的指针,函数原型为:iterator begin()和const_iterator begin() const,这两个函数构成重载,分别应用于普通对象和const属性对象。
  • end -- 获取指向字符串最后一个元素后面那个位置('\0')的指针,函数原型为:iterator end()和const_iterator end() const。
图3.6 begin和end函数返回值的指向位置示意图
  • rbegin -- 返回指向字符串最后一个字符的指针,函数原型为:reverse_iterator rbegin() 和 const_reverse_iterator rbegin() const。
  • rend -- 返回指向字符串第一个字符前一个位置的指针,函数原型为:reverse_iterator rend() 和 const_reverse_iterator rend() const。
图3.7 rbegin和rend返回值指向的位置示意图

演示代码3.6:

int main()
{string s1("abcde");//使用正向迭代器遍历s1的每个字符,+1后输出string::iterator it1 = s1.begin();while (it1 != s1.end()){++(*it1);cout << *it1;  //输出bcdef++it1;}cout << endl;string s2("abcde");//使用反向迭代器,反向遍历s2的每个字符并输出string::reverse_iterator it2 = s2.rbegin();while (it2 != s2.rend()){cout << *it2;  //输出edcba++it2;}cout << endl;return 0;
}
图3.8  演示代码3,6的运行结果  

3.7 常用的关于string类对象的全局函数

在C语言阶段,学过函数atoi,功能是将字符串转化为整数。但是,C/C++标准库函数中并没有atoi函数,虽然大部分编译器都已支持atoi函数,但是,依然建议不要使用,这样会降低程序的可移植性,很多老式编译器依然不支持atoi。

  • stoi -- 将string类对象转换为int型数据。
  • stol -- 将string类对象转换为long int型数据。
  • stoul -- 将string类对象转换为unsigned long int型数据。
  • stoll -- 将string类对象转换为long ong型数据。
  • stoull -- 将string类对象转换为转换为unsigned long long型数据。
  • stof -- 将string类对象转换为float型数据。
  • stod -- 将string类对象转换为double型数据。

上述函数,会自动排除字符串前部的空格,会通过'+'、'-'字符判断返回值的正负,当遇到非数字字符时,函数会终止执行,返回当前值。

注意:如果string无法转换为数字(首个非空字符不是'+'、'-'或数字字符),以及超出数据类型表示范围的情况下,上述函数均会抛异常,引发程序崩溃。

演示代码3.7:

int main()
{string s1(" -123ab1");string s2(" 1234");string s3("+1234abc");string s4("aa");string s5("-123.12");string s6("100.111abc");string s7("110.ab");string s8("001234.5");string s9("123456789987654321");cout << "s1 = " << stoi(s1) << endl;  //-123cout << "s2 = " << stoi(s2) << endl;  //1234cout << "s3 = " << stoi(s3) << endl;  //1234//cout << "s4 = " << stoi(s4) << endl;  //无法转换为int会抛异常cout << "s5 = " << stod(s5) << endl;  //-123.12cout << "s6 = " << stod(s6) << endl;  //110.111cout << "s7 = " << stod(s7) << endl;  //110cout << "s8 = " << stod(s8) << endl;  //1234.5//cout << "s9 = " << stoi(s9) << endl;  //超出int范围会抛异常return 0;
}


http://www.ppmy.cn/news/31420.html

相关文章

【JavaSE】数组的定义与使用详解

目录 1.数组的基本概念 1.1数组的好处 1.2什么是数组 1.3数组的定义及初始化 1.3.1数组的创建 1.3.2数组的初始化 1.4数组的使用 1.4.1访问数组中的元素 1.4.2遍历数组 2.数组的类型 2.1认识JVM的内存分布 2.2基本类型变量与引用类型变量 2.3认识null 3.数组的应…

基于Qt WebEngine 的Web仪器面板GUI程控技术

随着IIoT的发展&#xff0c;很多工业仪器也具备了远程管理的GUI。与早期使用串口进行命令交互不同&#xff0c;这些GUI可以直接在远程呈现数据。 作为希望对仪器、软件进行二次开发的小公司来说&#xff0c;会遇到GUI人工操作转自动化的需求。在无法通过串口等传统接口进行自动…

Vue 3.0 单文件组件 【Vue3 从零开始】

#介绍 在很多 Vue 项目中&#xff0c;我们使用 app.component 来定义全局组件&#xff0c;紧接着用 app.mount(#app) 在每个页面内指定一个容器元素。 这种方式在很多中小规模的项目中运作的很好&#xff0c;在这些项目里 JavaScript 只被用来加强特定的视图。但当在更复杂的…

2023年全国最新机动车签字授权人精选真题及答案17

百分百题库提供机动车签字授权人考试试题、机动车签字授权人考试预测题、机动车签字授权人考试真题、机动车签字授权人证考试题库等&#xff0c;提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助你考试轻松过关。 三、多选题 1.注册登记安全检验时&#xff0c;送检乘用…

硬件语言 Verilog HDL 学习 day02 数据流建模,行为级建模,结构化建模

1.数据流建模 1.含义&#xff1a;在电路规校较小的清况下&#xff0c;由于包含的门数比较少&#xff0c;设计者可以逐个地引用逻辑门实例把它 们互相连接起来&#xff0c; 因此使用门级建换进行设计是很合适的。对于具有数字逻辑电路设计基本知识的用户来讲&#xff0c;门级建模…

ArcGIS:栅格计算器的运算符和函数详解

01 栅格计算器在哪&#xff1f;02 运算符说明栅格计算器的表达式书写与Python语法一致&#xff08;由于其为解释型语言并且语言简洁优美&#xff0c;因此简单上手&#xff09;&#xff0c;这里主要简单说明各个运算符即可使用栅格计算器构建地图代数表达式以输出要求的栅格图像…

项目管理工具DHTMLX Gantt灯箱元素配置教程:如何验证

DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的大部分开发需求&#xff0c;具备完善的甘特图图表库&#xff0c;功能强大&#xff0c;价格便宜&#xff0c;提供丰富而灵活的JavaScript API接口&#xff0c;与各种服务器端技术&am…

(蓝桥真题)剪格子(搜索+剪枝)

样例1输入&#xff1a; 3 3 10 1 52 20 30 1 1 2 3 样例1输出&#xff1a; 3 样例2输入&#xff1a; 4 3 1 1 1 1 1 30 80 2 1 1 1 100 样例2输出&#xff1a; 10 分析&#xff1a;这道题目我们直接从(1,1)点开始进行dfs搜索即可&#xff0c;但是需要注意一点的是我们搜…