0 简介
在C语言中,字符串和数组有很多相似之处,且官方提供了很多的库函数可供调用。那么字符串和数组这对姐妹花,究竟有着什么样的亲密关系,而作为我们本期的重点角色,字符串又有何独特之处呢?
C语言并没有显式的字符串数据类型,因为字符串以字符串常量的形式出现或者存储于字符数组中。字符串常量很适用于那些程序不会对它们进行修改的字符串。所有其他字符串都必须存储于字符数组或动态分配的内存中。
本篇着重介绍了一些字符串常用的库函数,使大家在不同的情况下去选择最适合的库函数。下面是本文的内容概览
1 字符串基础
字符串就是一串0个
或多个
字符,并且以一个位模式全为0
的NUL
字节结尾。
例如:
char message[] = "hello word";
2 字符串长度
字符串的长度就是字符串所包含的字符个数,并不包括最后一个终止符。这个在面试中会经常考查。
可以通过库函数strlen()来自动计算字符串的长度。
例如:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char message[] = "hello word"; printf("字符串的长度为:%d\n",strlen(message)); system("pause"); return 0; }
打印输出:
需要注意的是,该函数返回的是无符号数,因此通过该函数比较两个字符串的长度的时候需要格外注意:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char message1[] = "hello word"; char message2[] = "hello Shanghai"; //比较方式1 if(strlen(message1) >= strlen(message2)) printf("字符串1更长\n"); else printf("字符串2更长\n"); //比较方式2 if (strlen(message1) - strlen(message2) >= 0) printf("字符串1更长\n"); else printf("字符串2更长\n"); system("pause"); return 0; }
打印输出:
因为返回的是无符号数,所以比较方式2中,条件判断的结果永远为真,导致判断结果出现错误。
3 不受限制的字符串函数
所谓的不受限制的字符串函数,是指在使用的时候,不需要指定字符串(实参)的长度,函数即可顺利运行。
3.1 复制字符串
复制字符串在开发中经常会用到,但是在复制到新的字符串中时,会覆盖掉原来的部分,所以需要格外注意。
例如:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char message1[] = "hello word"; char message2[] = "hello Shanghai"; int message2_len = strlen(message2); printf("字符串2的长度为:%d\n", strlen(message2)); strcpy(message2,message1); printf("字符串2的长度为:%d\n",strlen(message2)); for(int i = 0; i < message2_len; i++) printf("%c",message2[i]); system("pause"); return 0; }
打印输出:
可以看到,在将字符串message1
复制到message2
之后,message2
的长度居然都不一样了,这是为什么呢?
这是因为,在复制字符串的时候,顺便也将终止符复制了过来,在strlen()
函数进行处理的时候,肯定就会返回10
,从打印结果来看,message2
的其余部分仍然被保留了下来。
而将较长字符串复制到较短的字符串中时,常常会报错,这是因为没有足够的空间去容纳需要复制的字符。
3.2 连接字符串
连接字符串的时候,可以使用strcat()函数。它的原型如下:
char *strcat(char *dst, char const *src);
举个例子:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char message1[] = "hello word"; char message2[] = "hello Shanghai"; strcat(message1,message2); printf("%s\n", message1); system("pause"); return 0; }
打印输出:
可以看到,直接将两个字符串进行了拼接。新字符串的长度值是原来两个字符串的长度之和。
3.3 函数的返回值
这些函数的返回值有时候是第一个参数的一份拷贝,因此可以嵌套使用,因为当字符串做实参的时候,传递的也是第一个元素的地址。所以这些函数经常可以嵌套地调用。
例如:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char message1[] = "hello "; char message2[] = "word "; char message3[] = "Shanghai"; strcat(strcat(message1, message2), message3); printf("%s\n", message1); system("pause"); return 0; }
打印输出:
但是为了程序的可读性,不嵌套也可以。
3.4 字符串比较
字符串比较,常用的库函数只有一个,就是strcmp
。它的原型如下:
int strcmp(char const *s1, char const *s2);
这个函数的比较规则比较 有意思,该函数对两个字符串的字符逐个进行比较,直到发现不匹配为止,这里有两种情况:
- 最先不匹配的字符中在ASCII中排名靠前的那个字符所在的字符串被认为是较小的字符串;
- 如果开始部分的两个字符串都相等,那么较短的字符串被认为是较小的字符串。
字符串发现有不匹配的某个字符,即可得到对比结果,而无须比较剩余部分。
如下图所示:
看看实际的代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char temp1[] = "hello"; char temp2[] = "hello world"; char temp3[] = "hello worLd"; //字符串temp1和temp2作比较 if(strcmp(temp1,temp2) == 0) { printf("temp1 = temp2\n"); } else if (strcmp(temp1, temp2) > 0) { printf("temp1 > temp2\n"); } else if (strcmp(temp1, temp2) < 0) { printf("temp1 < temp2\n"); } printf("------------------\n"); //字符串temp2和temp3作比较 if (strcmp(temp2, temp3) == 0) { printf("temp2 = temp3\n"); } else if (strcmp(temp2, temp3) > 0) { printf("temp2 > temp3\n"); } else if (strcmp(temp2, temp3) < 0) { printf("temp2 < temp3\n"); } printf("\n"); system("pause"); return 0; }
打印输出: