
6.3.5 字符串处理函数
(1)puts(字符数组);
将一个字符串输出到屏幕,注意只能输出一个字符串。看看如下范例:

上面这段代码等价于如下这段代码,这意味着puts函数很容易被取代,所以现在puts函数很少使用:

(2)strcat(字符数组1,字符数组2);
连接两个字符数组中的字符串,把字符数组2的内容连接到字符数组1后边,结果存放在字符数组1中。这里不要搞反,是把右边字符数组2中的内容连接到左边字符数组1中内容的末尾。这是一个常用函数,请用心掌握。看看如下范例,在演示过程中,如果这段代码报错,请在自己的源码文件顶部增加#include<string.h>代码行来包含系统头文件,也可以借助搜索引擎解决报错的问题:

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

图6.15 strcat函数示意图
有几点说明:
①字符数组1必须足够大,能够容纳连接后的新字符串。本例中连接后的新字符串中字符是7个(不要忘记连接后字符串末尾的'\0'),所以str1长度至少为7。
②连接之前两个字符串后面都有一个\'0',连接时将字符串1末尾的\'0'删除并开始连接字符串2的内容,连接后只在新字符串的末尾保留一个'\0'。
③连接后str2内容不发生任何变化,换句话说,strcat对str2没有任何影响。
(3)strcpy(字符数组1,字符串2);
将字符串2复制到字符数组1中。字符数组1中的内容将被覆盖。这里不要搞反,是把右边的内容往左边复制。这是一个很常用的函数,要仔细掌握。看看如下范例:

字符串复制前后的示意图如图6.16所示。

图6.16 strcpy函数示意图
有几点说明:
①字符数组1必须足够大,以便能容纳下被复制的字符串,也就是说,字符数组1的容量不能小于字符串2的长度(不要忘记字符串2末尾还有个'\0'也要占一个位置)。
②字符数组1必须是一个数组名,而字符串2可以是一个数组名,也可以是一个字符串常量。例如:

③复制的时候连同字符串末尾的'\0'也一起复制到字符数组中。
④不能用赋值语句将一个字符串常量或者字符数组名直接赋给一个字符数组(字符数组名)。如下代码不合法:

必须得用strcpy函数。
请严格区分“定义的时候初始化”与“赋值”这两个概念:

⑤赋值语句只能将一个字符赋给一个字符型变量或数组元素:

⑥复制后str2内容不发生任何变化,str1中虽然有两个\'0',但是当输出该字符串内容时,只输出到第一个'\0'之前,所以,str1中的有效内容其实还是“two”。
(4)strcmp(字符串1,字符串2);
比较字符串1和字符串2中的内容,这也是一个比较常用的函数:
①如果字符串1=字符串2,则函数返回0。
②如果字符串1>字符串2,则函数返回一个正整数。
③如果字符串1<字符串2,则函数返回一个负整数。
比较规则:对两个字符串自左至右逐个字符比较(按ASCII码值大小比较),一直到出现不同的字符或者遇到'\0'为止,若全部字符相同,认为相等,若出现不相同的字符,则以第一个不相同的字符比较结果为准。
一般来说,strcmp常用于比较两个字符串是否相等,而比较大小则用的比较少,因为比较大小一般来说意思不大。看看如下范例:

再看一例:

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

上面的代码是进行两个地址的比较(地址是一个数字,前面讲过),str1代表某段内存的首地址,str2代表另一段内存的首地址,两者比较,肯定不相等,读者可以尝试加断点跟踪调试一下代码来帮助自己理解。所以,要比较两个字符串中的内容,只能像下面这样写:

(5)strlen(字符数组);
得到字符串长度,本函数执行的结果值为字符串的实际长度,但不包括字符串结束标记'\0'。这同样是一个比较常用的函数,而且也容易在考试以及面试中出现,需要认真掌握。看看如下范例,建议设置断点调试和观察结果:

第2章曾经讲过sizeof运算符,用于计算变量所占的内存大小,那么,strlen函数和sizeof运算符从功能上有什么区别呢?这也是一个考点,回忆一下下面这段代码:

当然sizeof中可以直接使用类型名。看如下代码:

再看看下面几行代码:

当然还有很多其他函数,以后遇到时再继续介绍。本节的主要任务是理解好怎样用字符数组来存储和操作字符串,这是非常重要的一节,如果一时无法理解,请反复阅读,不断在计算机上进行编程实践,一直到完全学会完全理解为止!