第六章 数组(三)

2023-12-22 16:40:13

三、字符数组

前面讲解一维和二维数组时,所遇到的多以整型数组为主,也就是数组元素多为整型数据。如int a[10];int a[3][4];

字符数组表示每一个数组元素中保存的是字符,这里要先提醒一下,因为字符数组中不但能保存字符,还能保存字符串,因此,字符数组这节中有一些陷阱,在讲解时会提醒。

1、字符数组的定义

用来存放字符数据的数组就是字符数组,字符数组的一个元素存放一个字符,可以看到字符数组其实也是一维数组。

例:

2、字符数组的初始化

字符数组的初始化如下:

(1)逐个字符赋给数组中的元素,这种初始化方式是好理解。

(2)如果提供的初值个数和预定的数组长度相同,定义时可以省略数组长度,系统会自动根据初值个数确定数组长度。

(3)如果初值个数大于数组长度,则做语法错误处理:

(4)如果初值个数小于数组长度,则只将这些字符赋给数组中前面的元素,其余的元素值可能会给 '\0',也可能无法确定 ,所以强烈不建议使用这些无法确定的元素值。

转义字符 \0等于数字0。

后续讲解字符串时会看到,系统会自动给字符串末尾增加一个 '\0'字符作为整个字符串的结束标记。当然,如果手工给字符串末尾增加一个 '\0'也是完全没有语法错误的,或者如躲给任何一个合法的字符数组中的元素赋值成 '\0'都是可以的,也同样不会报错。如c[0] ='\0'。

打印结果:

实际应用中二维字符数组用的并不多,而一维字符数组用得比较多 ,所以重点掌握一维字符数组,等讲解后续的字符串知识时就知道了。

再看一个例子:

3、字符串和字符串结束标记

非常重要的一节,必须掌握。

如果提供的初值个数和预定的数组长度相同,定义时可以省略数组长度,系统会自动根据初值个数确定数组长度。

补充一个对字符数组初始化的方法,就是用字符串常量来初始化字符数组。

如果设置断点跟踪调试,会发现,上面这种初始化居然是定义了一个"char c[11];" 的数组,也就是该数组的长度是11,意味着能够引用的元素是 c[0]-c[10],并且c[10]里面被系统自动填充进去一个 "\0'字符,前面讲过,在计算机内存中保存的是字符的 ASCIl 码,查询一下 ASCIl 码表就可以知道 '\0'的 ASClI 码是 0。

'\0'称为字符串结束标志,用来标记一个字符串的结束。为了测定字符串的实际长度,C 语言规定了一个字符串结束标记,用 '\0'代表。如果一个字符串的第 10 个字符为 '\0' ,则该字符串中的有效字符为 9 个。也就是说,在遇到字符 '\0'时,代表字符串结束,由 '\0'前面的字符构成整个字符串。

第二章提过字符串常量,例如"I love you"就是字符串常量。实际上,C语言对字符串常量也会自动在其末尾增加一个 '\0'作为字符串结束标记,例如 "I love you"一共有10 个可见字符(空格也算可见字符) ,每个可见字符占 1字节内存,但实际上这个字符串在内存中是占 11 字节,最后1字节存放的是 '\0',这个 '\0'是由系统自动加上去的。

有了字符串结束标记 '\0'之后,字符数组的长度就很容易确定了,在程序中往往依靠检测'\0'来判断字符串(也就是字符数组中保存的内容)是否结束,当然,在定义字符数组时,必须要估计实际要保存的字符串长度,定义字符数组时指定的长度必须要不小于字符串的长度。

例:

因为数组c大小是 10,无法保存下 "I love you”这个字符串, C 语言对字符串常量会自动在字符串末尾加一个 '\0'作为字符串结束标记,所以至少要把字符数组 c 的大小设置为 11才可以。

例:

例:下面两行代码的区别

上面两行代码是不等价的,因为后一种写法系统会自动在字符串末尾增加个 '\0’,第一行字符数组长度是10,第二行字符串数组长度是11。

例:下面两行代码是等价的,因为第一行加了'\0'。它们的长度相等 ,内容也相同。

注意:

(1)对于字符串(双引号包含起来),系统会自动往末尾增加一个'\0',也可以自己手动在末尾增加'\0',字符数组并不要求它最后一个字符为'\0',甚至整个字符数组可以没有'\0'。?

(2)是否加个 '\0'取决于需要,但是,只要用字符串来初始化字符数组,系统就会自动在字符串末尾加一个 '\0'。

(3)如果要使用字符数组并对它进行初始化 ,建议和字符串保持一致 ,也就是人为地增加一个 '\0' ,这样做主要是为了确定字符串的实际长度(因为字符串实际长度是靠找到末尾的'\0’来确定的。

(4)一般不会给字符数组中每个元素分别赋值。

(5)下面这种写法更常用,建议重点掌握下面这种写法即可。

例:加深对字符串结束标记的记忆

向屏幕输出字符串内容,一直遇到 '\0'才会停止输出,而因为内存中一直没有遇到'\0'。就会一直向屏幕输出内容,所以看到了垃圾信息, 偶然之间(无意中)遇到了 个 '\0',于是停止了输出,这种写法的程序代码肯定是有问题的。

下面的这种方法,因为系统自动给字符串末尾增加丁一个 '\0',所以向屏幕输出字符串内容时,遇到'\0'刚好停止输出,所以结果非常正确。

本节重点是理解好字符串结束标记。

4、字符数组的输入/输出

在 printf里,输出一个字符串,用%s格式符。

例:

说明:

(1)printf输出的字符串中并不包含 '\0' ,而且'\0'也不是个可显示字符。

(2)?printf("%s\n",c);这里用%s输出时,输出项是字符数组名,不可以是数组元素,如c[0],c[1]等,输出字符要用printf的%c格式字符来输出。如printf(“%c\n”,c[0]);

(3)即便数组定义时的长度大于字符串实际长度,也只输出到 '\0’结束。

例:

虽然字符数组 c的长度是 100(定义时的长度),输出依旧是”I love you",字符串结束标记的用处正在于标记一个字符串内容的结束。

(4)如果一个字符数组里包含多个 '\0',那么 printf遇到第一个'\0'时就停止输出。

5、字符串处理函数

1) puts(字符数组);

将一个字符串输出到屏幕,注意只能输出一个字符串。

例:

上面这段代码等价于下面的代码:

2)strcat(字符数组1,字符数组2) ;

连接两个字符数组中的字符串,把字符数组 2 的内容连接到字符数组 1 后边 ,结果存放在字符数组1中,记住是把右边字符数组2中的内容连接到左边字符数组1中内容的末尾,这是一个常用函数。

例:

如果上面的代码报错,请在自己的源码文件顶部增加# include <string.h> 代码行来包含系统头文件, 也可以借助搜索引擎解决报错的问题。

字符串连接前后的示意图如下,注意最终只在 str1被连接后生成的新字符末尾才带字符串结束标记 '\0'。

说明:

(1)字符数组1必须足够大,能够容纳连接后的新字符串。本例中连接后的新字符串中,字符是 7 个,加上连接后字符串末尾的 '\0',所以 str1长度至少为 7。

(2)连接之前两个字符串后而都有一个 '\0',连接时将字符串1末尾的 '\0'删除并开始连接字符串2的内容,连接后只在新字符串的末尾保留一个 '\0'。

(3)连接后str2内容不发生任何变化,strcal函数对str2没有任何影响。

3)strcpy(字符数组1,字符串2)

将字符串2复制到字符数组1中,字符数组1中的内容将被覆盖,这里不要搞反,是把右边的内容往左边复制,一个很常用的函数,要仔细掌握。

字符串复制前后的示意图如下:

说明:

(1)字符数组1必须足够大 ,以便能容纳下被复制的字符串,也就是说,字符数组1的容量不能小于字符串2的长度(不要忘记字符串2末尾还有个 '\0'也要占一个位置)。?

(2)字符数组1必须是一个数组名,而字符串2可以是一个数组名 ,也可以是一个字符串常量。

例:strcpy(str1,"two");

(3)复制的时候连同字符串末尾的 '\0'也一起复制到字符数组中。

(4)不能用赋值语句将一个字符串常量或者字符数组名直接赋给一个字符数组(字符数组名)。

例:以下代码不合法,必须得用strcpy函数。

char str1="one";

char str2="two";

str1=str2;

严格区分"定义的时候初始化" 与 "赋值"这两个概念。

char str1[10]="one";? ? //这是定义的时候初始化,合法

str1="one";? ? ? ? ? ? //这是赋值,非法

(5)赋值语句只能将一个字符赋给一个字符型变量或数组元素。

(6)复制后str2内容不发生任何变化,str1中虽然有两个'\0',但是当输出该字符串内容时,只输出到第一个'\0'之前,所以,str1中的有效内容其实还是"two"。

4)strcmp(字符串1,字符串2);

比较字符串1和字符串2中的内容,这也是个比较常用的函数。

说明:

(1)如果字符串1=字符串2,则函敛返回0。?

(2)如果字符串1>字符串2,则函数返回一个正整数。

(3)如果字符串1<字符串2,则函数返回一个负整数。

比较规则:对两个字符串自左至右逐个字符比较(按 ASCII 码值大小比较),一直到出现不同的字符或者遇到 '\0'为止,若全部字符相同,认为相等,若出现不相同的字符,则以第一个不相同的字符比较结果为准。

strcmp 常用于比较两个字符串是否相等,而比较大小用的少,因为比较大小一般来说意义不大。

例:

例:

例:

注意, C 语言中比较两个字符串不能写下面这样的代码:

if(str1==str2){

......

}

上面的代码是进行两个地址的比较(地址是一个数字,前面讲过) , str1 代表某段内存的首地址,str2 代表另一段内存的首地址,两者比较,肯定不相等.所以,要比较两个字符串中的内容,只能像下面这样写:

if(strcmp(str1,str2)==0){

......

}

5)strlen (字符数组);

得到字符串长度,这个函数执行的结果值为字符串的实际长度,但不包括字符串结束标记'\0',这同样是一个比较常用的 函数,需要认真掌握。

例:

第二章讲过sizeof运算符,用于计算变量所占的内存大小,那strlen函数和sizeof运算符从功能上有什么区别?

sizeof 中可以直接使用类型名。

例:

例:

C语言中还有很多函数,后面遇到再介绍。上面的存储和操作字符数组的函数很重要,必须理解。

文章来源:https://blog.csdn.net/weixin_30479905/article/details/135154428
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。