C++之STL——string字符序列类容器(1)

5 篇文章 0 订阅

目录      

前言

string类

1.该类的由来

2.string类对象的创建

(1)头文件

(2)类对象的创建

其他用法:

(3)string类对象遍历 

1:方括号[ ]重载遍历

2.范围for遍历:

3.迭代器遍历:

总结:


前言

        在学习 C语言的过程中,我们对于字符的表示所使用数据类型用的是char,而字符串是字符的集合,需要用到字符数组或者指针两种方式,如下:

int main(){
char str[10]="123456";
char* std="Hello World";
}

         第一种方式字符数组,字符串数据被放在堆栈空间的,它是可读可写的,对于字符串,我们可以对它进行数据的修改,例如:求长度、拷贝字符串、拼接、比较多个字符串的大小、查找内容......:

# include<stdio.h>
#include<string.h>
int main() {
	char str[40] = "12345678";		//可修改
	//int length = sizeof(str) / sizeof(str[0]);
	//求字符串的长度
	int length = strlen(str);

    //遍历字符串
	for (int i = 0; i < length; i++) {
		printf("%c ", str[i]);
	}
	printf("\n");

	//字符串的拷贝
	char s1[15] = "haha";
	char s2[18] = "xixi";
	strcpy(s2, s1);
	printf("s2:%s\n", s2);

	//字符串的拼接
	char s3[6] = "789";
	strcat(s1, s3);
	printf("%s\n", s1);

	//字符串的查找
	char a[] = "abcdefg";
	char b[] = "bc";
	char* ret = strstr(a, b);	//在数组a中查找数组b的内容
	if (ret == NULL) {
		printf("Can not find!\n");
	}
	else {
		printf("%s\n", ret);  //输出 bcdefg
	}
	return 0;
}

测试结果: 

        通过代码我们可以发现字符串操作很繁琐,且字符数组在修改时还得时时刻刻注意数组是否会造成越界,表明char类型的字符数组无法自动分配内存空间。

        第二种就是指针指向字符串,对于此种方式,我们无法进行修改,因为字符串处在常量区。

        而在C++中,为了弥补C语言字符功能的不足,编程人员专门创建了String类,该类内部封装了与内存容量有关的信息,string对象自己就知道在内存的位置,包含的字符序列与长度;并且当自身存储空间不足时,会自动调整,让内存空间存储到能够容纳下所有字符序列的大小。


string类

1.该类的由来

        该类是根据utf-8编码为核心所制作的字符序列类,在学习C语言过程中,我们唯一熟悉的就是ASCII码,。它是美国标准信息交换代码(American Standard Code for Information Interchange)的缩写, 为美国英语通信所设计。它由128个字符组成,包括大小写字母、数字0-9、标点符号、非打印字符(换行符、制表符等4个)以及控制字符(退格、响铃等)组成。因为计算机最开始是由美国发明创造的,所以有了ASCII码去划分字符,但后来计算机的广泛发展,各国都开始使用,但ASCII码远远不能满足,各国都有他们各自特殊的字符,所以Unicode诞生了。

        统一码(Unicode),也叫万国码、单一码,由统一码联盟开发,是计算机科学领域里的一项业界标准,包括字符集编码方案等。统一码是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。

        而我们在各类语言中经常使用的就是utf-8编码,所以String类也是我们最常用的字符序列类。

2.string类对象的创建

(1)头文件

string类想要使用,就得包含头文件:#include<string>

String是char的优化类型,所以在C++中它是typedef代替而成的:

typedef basic_string<char>  string

(2)类对象的创建

        主要用法:

#include<iostream>
#include<string>
using namespace std;
int main() {
	//生成空字符串
	string str1;
	cout << str1 << endl;

	//生成字符串方法1:
	string str2("1234");
	cout << str2 << endl;

	//生成字符串方法2:
	string str3="5678";
	cout << str3 << endl;

	//生成字符串方法3:
	string str4(str3);
	cout << str4 << endl;

        总结:方法1和方法2虽然创建格式不同,但是等价的,方法1是对象str2拷贝字符串"1234",方法2是将字符串"5678"内容赋值给对象str3;

                  方法3和方法1都是用到类的拷贝构造函数,str4拷贝构造了str3的数据内容,但却是深拷贝,对象str4指向的字符串"5678"地址与str3指向的字符串地址不同!

其他用法:

        针对于拷贝字符串内容生成的方法,还需要注意以下几种情况:

情况1:

string str5("123456", 3, 2);
	cout << str5 << endl;

        str5生成方式:从字符串的某个下标位置开始,共获取n个字符;第一个参数是字符串,第二个参数指字符串的下标位置,第三个参数是需要输入获取的字符数。

        代码解析:在字符串内容的下标3位置开始获取2个字符数。

    string str5_1("123456", 3, 100);
	cout << str5 << endl;

        若是想要获取100个字符,会不会出现异常或者报错?

        答案是:不会,编译器在字符下标位置3处,也就是字符4处一直往后取,直到'\0'就自动结束获取,不会造成越界。

结果: 

情况2:

    string str6("987654", 2);		
	cout << str6 << endl;

	string str7("Hello World",10);	
	cout << str7 << endl;

        代码解析:str6获取从字符串"986754"中的两个字符内容,括号内只有两个形参,一个是字符串内容,一个是获取的字符数,那么下标位置默认是从字符串首部开始取! 

结果:

         以上红框中的内容就是String类对象的构造方法,有多种方式可以构造对象,到时候我们可以具体情况具体分析的进行使用。


(3)string类对象遍历 

        遍历方式有三种:

1:方括号[ ]重载遍历

int main() {
	string s = "123456";
	for (int i = 0; i < s.size(); i++) {
		s[i]++;    //让字符串s中的每个字符都加1,这个加1是编码+1(类似于Ascii+)
		cout << s[i]<<"  ";
	}

       注:string类中之所以能用数组循环的方式遍历,原因就在于[ ]这对方括号,在string类中,方括号被重载。

​ 


2.范围for遍历:

cout<<"遍历方法2:范围for:" << endl;
	for (auto& j :s ) {
		j--;
		cout << j <<"  ";
	}
	cout<<endl;

auto可以自动识别类型,使用引用&符号,可以修改数据。 


3.迭代器遍历:

        如上是迭代器中的接口函数,我们可以把它们看作是指针例如:begin指向String类对象内容的开头,end指向string类对象内容的结尾。在迭代器中,共有四种类型的begin和end,即正向迭代、反向迭代、const正向迭代、const反向迭代。这四种类型的接口都受string类域的限制,所以定义这些begin、end时需要加上类域才行!

 

        使用迭代器,需要明白其格式:

string:: iterator 迭代器对象名=String类对象.函数名(); 

正向迭代器:

​ 

cout << "遍历方式3:用迭代器iterator:" << endl;
string s2 = "20221213";
string::iterator it1 = s2.begin();
while(it1!=s2.end()){
	//写操作
	(*it1) += 1;
	//读操作
		cout << (*it1) << "  ";
		it1++;
		}

        iterator迭代器功能的使用需要 


反向迭代器:逆置遍历

注: rbegin与rend都是搭配reverse_iterator使用,且方向相反,迭代器对象也是++,不可--使用。

//反向迭代器
			string s4 = "WangKai";
			string::reverse_iterator rit1 = s4.rbegin();
			while (rit1 != s4.rend()) {
				cout << (*rit1) << "  ";
				rit1++;
			}
			cout << endl;


 const正向迭代器:不支持数据修改

string::const_iterator cit1 = s4.cbegin();
		while (cit1 != s4.cend()) {
			cout << (*cit1) << "  ";
			//(*cit1)++;	//报错
			cit1++;
			}
	

​ 

​ cbegin与cend也是搭配const使用的。

const反向迭代器:不支持数据修改+逆置遍历

string::const_reverse_iterator rcit1 = s4.rbegin();
			while (rcit1 != s4.rend()) {
				cout << (*rcit1) << "  ";
				rcit1++;
			}
			cout << endl;

总结:

        1.const不可以放在string外面,const放在外面则是:

const string::iterator it=s1.begin();        该语句限制了it不能够移动位置,只能指向s1字符串的首部,无法进行遍历;

而string::const_iterator cit=s1.begin();        该语句则是限制了cit不能修改字符串的内容,cit还是可以继续移动进行遍历的

        2.可以缩写类型:转换成auto,auto具有自动识别数据的类型功能,所以:

 auto it=s1.begin();                auto rit=s1.rbegin();        auto cit=s1.cbegin();......   

        3.迭代器的对象是类似于指针形式的,通过迭代器进行的遍历需要其对象进行解引用才能实现遍历! 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橙予清的zzz~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值