c++中的string类

目录

一、为什么c++引入了string类

1.1简化字符串操作

[1.2 自动内存管理](#1.2 自动内存管理)

[1.3. 安全性更高](#1.3. 安全性更高)

[1.4. 提供丰富的成员函数](#1.4. 提供丰富的成员函数)

[1.5. 支持面向对象编程](#1.5. 支持面向对象编程)

二、标准库中的string类

三、补充:auto与范围for

[3.1 auto关键字---自动识别变量类型](#3.1 auto关键字---自动识别变量类型)

[3.2 范围for](#3.2 范围for)

四、string类的常用接口

[4.1 构造函数](#4.1 构造函数)

[4.2 迭代器(iterator)](#4.2 迭代器(iterator))

[4.3. string类对象的容量操作](#4.3. string类对象的容量操作)

4.4.string类对象的访问及遍历操作

[4.5 string类对象的修改操作](#4.5 string类对象的修改操作)

[4.6. string类非成员函数](#4.6. string类非成员函数)


一、为什么c++引入了string类

C++ 设计string类是为了提供一种更方便、更安全、更强大的字符串处理方式,相比于c风格的字符串,string类的优势在于:

1.1简化字符串操作

C 风格字符串操作复杂 :在 C 语言中,字符串是用字符数组来表示的,以空字符'\0'结尾。对字符串进行操作时,往往需要手动管理内存和处理边界条件,代码较为繁琐。

string类操作简单 :C++ 的string类封装了这些操作,提供了直观的运算符重载和成员函数,使得字符串操作更加简洁。

1.2 自动内存管理

C 风格字符串内存管理困难 :使用 C 风格字符串时,需要手动分配和释放内存。如果分配的内存不足,会导致缓冲区溢出;如果忘记释放内存,会造成内存泄漏。

string类自动管理内存string类会自动处理内存的分配和释放,用户无需手动管理。当string对象的大小发生变化时,它会自动调整内部缓冲区的大小。

1.3. 安全性更高

C 风格字符串容易出现缓冲区溢出 :由于 C 风格字符串不记录自身长度,使用strcpystrcat等函数时,如果目标数组空间不足,会导致缓冲区溢出,从而引发安全问题。

string类避免缓冲区溢出string类会自动处理字符串的长度,不会出现缓冲区溢出的问题。当进行字符串操作时,string类会确保内部缓冲区有足够的空间。

1.4. 提供丰富的成员函数

string类提供了大量实用的成员函数:如查找子串、替换子串、截取子串等,方便进行各种字符串处理。

1.5. 支持面向对象编程

string类符合面向对象编程的思想 :可以将string对象作为类的成员变量,也可以在函数之间传递string对象,方便进行模块化编程和代码复用。

二、标准库中的string类

string的文档介绍:cplusplus.com/reference/string/string/?kw=string

标准string类具有类似于标准字节容器的接口,并且具有专门设计的用于操作单字节字符串的特性

三、补充:auto与范围for

3.1 auto关键字---自动识别变量类型

在早期C/C++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量,后来这个不重要了。C++11中,标准委员会变废为宝赋予了auto全新的含义即:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期

推导而得。

(1)用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&

当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际

只对第一个类型进行推导,然后用推导出来的类型定义其他变量。

(2)auto不能作为函数的参数,可以做返回值,但是建议谨慎使用.

(3)auto不能直接用来声明数组

结合代码加深理解:

cpp 复制代码
#include<iostream>
using namespace std;

int main() {
	int a = 6;
	//auto能够自动识别变量类型,无须具体指出,根据初始化的类型自动进行推导
	auto b = a;
	//auto修饰的变量必须初始化
	//auto c; // error:无法推导"auto"类型
	int* p = &a;
	//推导指针变量时,可以用auto,也可以用auto*
	auto* d = p;
	auto e = p;
	//但是使用auto*时,推导的变量必须是指针变量
	//auto* e = a;// error:无法推导"auto"类型
	long double x = 0;
	//auto常用修饰简化一个很长的类型名
	auto w = x;

	return 0;
}

3.2 范围for

对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此C++11中引入了基于范围的for循环。for循环后的括号由冒号" :"分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围,自动迭代,自动取数据,自动判断结束。

范围for可以作用到数组和容器对象上进行遍历

结合代码加深理解:

cpp 复制代码
#include<iostream>
using namespace std;

int main() {
	int arr[] = { 2,5,1,4,5,99,8,0,5 };
	//使用范围for进行数组的遍历
	for (int e : arr) {
		cout << e << " ";
	}
	cout << endl;
	return 0;
}

四、string类的常用接口

在学习string类时,我们会借助官方文档进行学习,在学习string类的过程中逐步掌握浏览文档的方式。

注意需要包含头文件<string>,同时使用命名空间std;

4.1 构造函数

重点掌握默认构造,拷贝构造,带参构造

cpp 复制代码
#include<iostream>
#include <string>
using namespace std;
int main() {
	string s1;//默认构造
	string s2("hello world");//带参构造
	string s3(s2);//拷贝构造
	cout << s2 << endl << s3 << endl;
	return 0;
}

注意:(3)中的npos代表无符号整数的最大值,是一个很大的数

4.2 迭代器(iterator)

begin:返回起始位置,end:返回字符串末尾\0所在位置。注意在使用begin()与end()时,所指向的范围区间是"左闭右开"的,而rbegin和rend则是反过来的begin和end,代码演示如下:

cpp 复制代码
#include<iostream>
#include<string>
using namespace std;

int main() {
	string s1("hello world");
	string::iterator it1 = s1.begin();
	string::iterator it2 = s1.end();
	cout << *it1 << " "<< *(it2 - 1);
	return 0;
}

4.3. string类对象的容量操作

结合代码:

cpp 复制代码
#include<iostream>
#include<string>
using namespace std;

int main() {
	string s3("this is an apple");
	//s3的最大空间
	cout << s3.capacity() << endl;
	//s3的有效字符个数,不包括\0
	cout << s3.size() << endl;
	//重新设置s3的size大小
	//resize(x):
	//当x < size,删除数据,capacity不变;
    //当x> size 且x < capacity,往字符串中插入数据,默认是\0
	//当x > capacity,扩容
	s3.resize(10);
	cout << s3 << endl;
	//empty判断字符串是否为空串,不是空返回0,为空返回1
	bool em1 = s3.empty();
	cout << em1 << endl;
	s3.clear();
	bool em2 = s3.empty();
	cout << em2 << endl;
	cout << s3.size() << endl;
	//reserve 直接申请所需的空间,不会修改内容,即size不会因此改变
	s3.reserve(65);
	cout << s3.size() << endl;
	cout << s3.capacity() << endl;

	return 0;
}

注意:

  1. size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size()。

  2. clear()只是将string中有效字符清空,不改变底层空间大小。

  3. resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。

  4. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserver不会改变容量大小。

4.4.string类对象的访问及遍历操作

cpp 复制代码
#include<iostream>
#include<string>
using namespace std;

int main() {
	string s5("today is Saturday");
	//使用operator[]来访问
	for (int i = 0; i < s5.size(); i++) {
		cout << s5[i];
	}
	cout << endl;
	//使用iterator begin + end 来访问
	string::iterator it = s5.begin();
	while (it != s5.end()) {
		cout << *it;
		it++;
	}
	cout << endl;
	//使用iterator rbgin + rend 来访问---逆转顺序
	string::reverse_iterator it2 = s5.rbegin();
	while (it2 != s5.rend()) {
		cout << *it2;
		it2++;
	}
	cout << endl;
	return 0;
}

4.5 string类对象的修改操作

注:由于c语言中没有string类,为了兼容c语言,c++的string类中设置了c_str的接口,其返回值是一个指向字符串的指针,这个指针可读不可改,在使用之前需要先转化,一定要使用strcpy()等函数来操作c_str()返回的指针。

cpp 复制代码
#include<iostream>
#include<string>
using namespace std;

int main() {
	string s6("there");
	cout << s6 << endl;
	//追加单个字符
	s6 += '!';
	cout << s6 << endl;
	//追加字符串
	s6 += "is";
	cout << s6 << endl;
	//追加一个string类
	string s7 = " an apple";
	s6 += s7;
	cout << s6 << endl;
	//使用c_str,返回的是一个const char*指针
	/*char* c;
	string s = "1234";
	c = s.c_str();*/
	//error:不能将 "const char *" 类型的值分配到 "char *" 类型的实体	



	return 0;
}

4.6. string类非成员函数

注:在cin与scanf中,都会将空格字符与换行字符作为分隔,无法获取到,而使用getline则可以解决这一问题,还可以指定想要的分隔符

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

int main()
{
	string name;
	string name2;

	cout << "Please, enter your full name: ";
	//此时默认以换行符作为结束
	getline(cin, name);
	cout << "Hello, " << name << "!\n";
	cout << "Please, enter your full name2: ";
	//此时将以给定的字符"!"作为结束
	getline(cin, name2,'!');
	cout << "Hello, " << name2 << "!\n";

	return 0;
}

创作不易,感谢三连支持!

相关推荐
007php007几秒前
企微审批中MySQL字段TEXT类型被截断的排查与修复实践
大数据·开发语言·数据库·后端·mysql·重构·golang
waves浪游4 分钟前
vector详解
c语言·开发语言·数据结构·c++·算法
ヾChen12 分钟前
数据结构——栈
开发语言·数据结构·物联网·学习
溟洵31 分钟前
【C/C++算法】从浅到深学习--- 位操作算法(图文兼备 + 源码详解)
c语言·c++·算法
小志开发34 分钟前
Java 抽象类:深入解析与实践指南
java·开发语言
重生之绝世牛码44 分钟前
Java设计模式 —— 【行为型模式】迭代器模式(Iterator Pattern)详解
java·大数据·开发语言·设计模式·迭代器模式·设计原则·设计方法
enyp801 小时前
c++ 预处理器和iostream 文件
开发语言·c++·算法
m0_748234341 小时前
搭建Golang gRPC环境:protoc、protoc-gen-go 和 protoc-gen-go-grpc 工具安装教程
开发语言·后端·golang
_GR2 小时前
2016年蓝桥杯第七届C&C++大学B组真题及代码
c语言·数据结构·c++·算法·蓝桥杯
AAA客服小高2 小时前
week 2 - Branching - Arrays
c++