目录
前言
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>
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"中的两个字符内容,括号内只有两个形参,一个是字符串内容,一个是获取的字符数,那么下标位置默认是从字符串首部开始取!
结果:
(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.迭代器遍历:
使用迭代器,需要明白其格式:
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.迭代器的对象是类似于指针形式的,通过迭代器进行的遍历需要其对象进行解引用才能实现遍历!