本章学习字符相关内容。
让我们从介绍字符型(char)开始。
字符型
字符型,顾名思义,就是可以保存字符的数据类型,与int、double等保存数字的略有区别。什么区别呢?
表示上的区别
比如我们要表示数字1,则int a=1;即可。
而若要表示字符1,则需要
char a='1';
注意到字符1被单引号所围住。这就是表示字符的方法。
若写char a=1;则会令a被赋值为一个与字符1毫无关系的符号。
使用上的区别
首先声明三个概念:数字、数值、字符。
毋庸置疑的是,在计算机内部,不论是数字还是字符,都是转化为数值进行处理的。
显然,数字1的数值也是1,以此类推。
但是字符1的数值就不是1了,而是49。
为什么呢?可以查询一下ASCII码,此处不多解释。
常见的字符与其数值:
‘0’=48,’1’=49,以此类推
‘A’=65,’B’=66,以此类推
‘a’=97,’b’=98,以此类推
但有时候我们还会经常看到’\n’,’\0’之类的。这些是什么呢?这些叫转义字符。其中,’\0’表示空字符,’\n’表示换行符。
*
printf(“\n”);
与cout<<endl;
一致。数值匹配如下:
‘\0’=0
‘\n’=10
查看数值匹配的方法:
- cout<<int(‘0’);可以查看字符0的ascii码(数值)
- printf(“%d”,’0’);也可以实现1的效果
- cout<<char(48);可以查看数值48对应的字符
- printf(“%c”,48);也可以
以上,就是字符型的简单表示。
接下来是字符数组。
字符数组
在前几章中,我们已经学习了数组的相关知识。那么很显然,字符数组的声明应该满足下述格式:
char str[100];
本语句声明了一个名为str的char类型数组,有100个单位可供使用。
我们知道,对于数组,其内部存储的时候是一个个值连续存储的。那么对于字符数组,因为字符型的值是字符,所以字符数组内部就是一个个字符连续存储的。如将“helloworld”保存在上述字符数组str内,则内部表示为’h’,’e’,’l’,’l’,’o’,’w’,’o’,’r’,’l’,’d’,如同一连串的字符,此时便可称之为字符串。
对于字符数组的初始化,除了前述的对于数组的通用初始化方法,还可以使用双引号,也就是用字符串常量直接初始化。如:
- 采用通用方法:
char str[100]={'h','e','l','l','o','w','o','r','l','d'};
- 采用双引号:
char str[100]="helloworld";
注意到采用通用方法时,需要大括号,而采用字符串常量时不需要大括号。
上面我们为str数组开设了100个单位,并且注意到”helloworld”只有10个字符。那么我们可不可以只开10个单位呢?问题可以转化成,以下两种写法可不可行?
- 采用通用方法:
char str[10]={'h','e','l','l','o','w','o','r','l','d'};
- 采用双引号:
char str[10]="helloworld";
答案是,两种都不可行。
在第一种中,虽然我们显式指定了str数组各个位上的值,但编译时其会在结尾补一个空字符’\0’,导致其最终有11个元素,超出了str数组10个元素的限制,引起访问错误。所以,在使用通用方法进行对字符数组的初始化时,应该预留足够的位置,至少应该是显示指定的字符数+1。
在第二种中,我们直接使用字符串常量来对字符数组进行初始化,依然会有第一种的问题,所以仍然需要多留一位。但要注意的是,第一种引发的是运行时的紊乱,而第二种引发的是编译错误,相比第一种更加容易发现。
特殊的,可以采用这样的写法来对字符数组进行初始化:char str[]="helloworld";
这样的写法可以不指定数组的长度,其内部会自动适配长度。但仅仅在对字符数组使用字符串常量进行初始化时可以不指定数组长度,其它类型/写法均不可以。
*仅在定义的时候可以用字符串常量对其进行赋值,在之后便不再可行,会引发编译错误。后续要操作的话只能按普通数组的方法。
对于二维数组,可以采用下述方法进行初始化:
char a[][10]={"hello","hi"};
第一维可以放空,若填写则不得少于字符串数量。
第二维必填,不得少于最长的字符串长度+1。
一般不需要使用更多维的char数组。
在cstring头文件中,提供了下列函数来对字符数组进行操作。
基本假设:设有char a[20]="hello",b[20]="hi";
strcpy(目标,来源);
此函数为复制函数,能将来源的字符串复制给目标。
示例:
strcpy(a,b);
运行后a数组和b数组都将等于”hi”。
strcat(目标,来源);
此函数为拼接函数,能将来源的字符串拼接到目标字符串后面。
示例:
strcat(a,b);
运行后a数组将等于”hellohi”,b数组不变。
strlen(数组名称);
此函数可以求出字符串长度(直到’\0’)。
示例:
strlen(a);
求出来的值是”hello”的长度5。因为a数组内部有赋值的部分是’h’,’e’,’l’,’l’,’o’,’\0’,strlen会从下标0开始往后计算直到第一个’\0’之前。
*若令
a[2]='\0'
,则a数组内部有赋值的部分变为’h’,’e’,’\0’,’l’,’o’,’\0’,将导致strlen所求得的值变为2。*若令
a[0]='\0'
,则a数组内部有赋值的部分变为’\0’,’e’,’l’,’l’,’o’,’\0’,将导致strlen所求得的值变为0。strcmp(数组1名称,数组2名称);
此函数可以按字典序比较数组1中的字符串1与数组2中的字符串2的大小。若字符串1大则返回正数,小则返回负数,一样大则返回0。
*字典序的比较方法:
设有
char a[]="13",b[]="120";
字典序是逐位比较的。先比较下标0的位置,发现字符串1和2的该位置都是’1’,则继续比较下标1的位置,发现字符串1的该位置是’3’而字符串2的该位置是’2’,因为’3’>’2’,所以字符串1比字符串2大。
再设有
char a[]="12",b[]="120";
先比较下标0的位置,发现字符串1和2的该位置都是’1’,则继续比较下标1的位置,发现字符串1和2的该位置都是’2’,则继续比较下标2的位置,发现字符串1的该位置是’\0’而字符串2的该位置是’0’,因为’\0’<’0’,所以字符串1比字符串2小。
以上就是对于字符数组的相关描述。对字符串的了解有没有清晰一些呢?现在开始介绍string类型,也即字符串类型。
字符串类型
使用string类型需要包含string头文件。
上面说到,一个一维字符数组可以表示一个字符串。那么对于string类型,该如何表示一个字符串呢?答案是一个变量即可。string在有string头文件的情况下可以如int等类型一般使用。
示例:string str="helloworld";
对于string类型,无需指定字符串长度,其内部会自动适配。且string类型可以在任意时候更改其赋值。如,可以在上述已有定义的情况下,令str=”hi”,则str会变成字符串”hi”。
尽管我们上述声明的str仅仅是一个变量,不是数组,但因为它是string类型,所以我们也可以使用下标来访问它内部的字符。如在string str=”helloworld”的基础上,我们可以访问str[4]得到其第五个字符’o’,也可以令str[4]=’r’使得str变为”hellrworld”。
同样的,对于string类型,我们也可以使用数组。如string str[2]={"hi","helloworld"};
可以通过str[i]来访问在str数组中下标为i的字符串,也可以通过str[i][j]来访问在str数组中下标为i的字符串的下标为j的位置。更多维数组同理。
在string头文件中,提供了下列成员函数来对string类型变量进行操作。
基本假设:设有string a="hello",b="hi";
(以下基于与上文中适用于字符数组的函数的对比)
a=b;
可以直接令a的值等于b的值,使用赋值符号即可。
a=a+b;
可以直接令字符串a和字符串b拼接在一起产生一个新的字符串,然后再把这个新的字符串赋值给a。
length();
可以求得字符串a的长度(求值方法与strlen一致)。
直接使用运算符进行比较。比较方法仍然是根据字典序(详见上文)。
以上,我们可以显而易见地发现,使用string类型比使用char数组更为方便。故实际使用时,若无特殊要求,一般建议使用string类型。
第五章到此结束。
本章练习: