C语言中与字符串有关函数讨论以及安全性能问题

一、strlen函数

strlen(const char *s)

strlen函数结果是得到字符串长度的数值,写出一个最基本用法的代码。

    char s1[] = "123456";///假设s1代码长度为6
    printf("strlen = %lu\n",strlen(s1));

C语言中与字符串有关函数讨论以及安全性能问题_第1张图片C语言中与字符串有关函数讨论以及安全性能问题_第2张图片
一般到这里,大部分初学者都认为,存入数组里的是6个字符长度。但是真的是这样吗? 我们再接着加入一条语句用来测试该字符串所得到的空间是多少?

printf("sizeof = %lu\n",sizeof(s1));///用来观察s1分得了多少空间

结果是非常amazing啊!
C语言中与字符串有关函数讨论以及安全性能问题_第3张图片
C语言中与字符串有关函数讨论以及安全性能问题_第4张图片
为什么s1的长度是7???
这里就要引入了字符串数组的一些性质。还是以s1为例,把s1输入数组中,输入结束时,程序会自动给数组的最后一位加上’\0’的符号,用来表示当数组输入结束。
所以’\0’其实也是占了一个位置,于是就有了我们看到sizeof(s1)=7。

以上我们是使用数组来定义的,现在改用指针定义,看看有没有什么不同。

    char* s1 = "123456";
    printf("strlen = %lu\n",strlen(s1));
    printf("sizeof = %lu\n",sizeof(s1));///结果为4,是指针s1大小为4

废话不多说,直接上实验结果图。
结果也是非常amazing啊~
C语言中与字符串有关函数讨论以及安全性能问题_第5张图片
这里我们可以看到,sizeof(s1)的值为4。细心的同学会看到指针部分的代码片段中有一个注释,解释了指针的大小为4。使用指针定义时,s1是指向字符串中的’1’的位置,于是就有了4的出现。

以下函数中的,以指针举例,有不明白的地方再返回看看。

二、strcmp函数

int strcmp ( const char *s1, const char *s2 );

比较两个字符串,返回:

  • 0:s1 == s2
  • 1: s1 > s2
  • -1: s1 < s2

同样,我们看一下他的用法。

	char *s1 = "abc";
   	char *s2 = "bbc";
   	char *s3 = "abc";
   	printf("s1:s2 = %d\n",strcmp(s1,s2));///比较字符串s
   	printf("s1:s3 =  %d\n",strcmp(s1,s3));///字符串s1=s3
   	printf("s2:s3 =  %d\n",strcmp(s2,s3));///字符串s2>s3

1.第一条输出语句,s1和s2相比较,‘a’的ASCII码(十进制,97)在’b’(十进制,98)前面,所以s1 < s2,得到的结果是-1。
2.第二条输出语句,s1和s3相比较,两个字符串是相同的,得到的结果是0。
3.第三条输出语句,s2和s3相比较,‘b’的ASCII码(十进制,98)在’a’(十进制,97)前面,所以s2 > s3,得到的结果是1。
C语言中与字符串有关函数讨论以及安全性能问题_第6张图片

三、strcpy函数

 char* strcpy( char *restrict dst, const char *restrict src );

作用是把src的字符串复制到dst中,并返回dst
简单的用法:

	char *src = "abc";
    char *dst = (char *)malloc(strlen(src)+1);///复制包含结束标志的字符串
    printf("dst = %s",strcpy(dst,src));

上代码运行图
C语言中与字符串有关函数讨论以及安全性能问题_第7张图片
这里说一下为什么使用malloc创建空间时需要加一,在strlen中解释过了,字符串赋值的时候会自动加上一个’\0’作为结束标志,所以需要多创建一个空间。

四、strcat函数

char* strcat( char *restrict s1, const char *restrict s2 );

即把s2拷贝到s1后面,接成一个长的字符串,并返回s1(s1必须要具有足够的空间)

	char src[] = "abc";
    char dst[] = "Hello";
    printf("dst = %s",strcat(src,dst));

这里使用数组表达的更清楚,所以不用指针写。
看看运行结果怎么样。
C语言中与字符串有关函数讨论以及安全性能问题_第8张图片
此处我们看到了程序把dst里的内容放置在了src后面的,组合成了一新的数组。
C语言中与字符串有关函数讨论以及安全性能问题_第9张图片
图示可以看出,src字符串的第一个字符’a’,放到了dst的结束标志符的位置。可以得出一个等价式:dst[strlen(dst)] = src[0]。

五、strchr函数

char * strchr( const char* s, int c );

即查找指针s所指向的字符串(从左往右查找)里,c字符第一次出现的位置,返回指针。

char * strrchr( const char* s, int c );

即查找指针s所指向的字符串(从右往左查找)里,c字符第一次出现的位置,返回指针。

以上指针返回NULL表示没有找到。
口说无凭,上代码:

    char *s = "Hello";
    printf("%s\n",strchr(s,'l'));

上运行结果:
C语言中与字符串有关函数讨论以及安全性能问题_第10张图片
结果也是非常amazing啊,指针p所在的位置刚好是字符串中第一次出现’l’的地方。

举一反三:
如果我要是想查找到第二个’l’咋办?使用strchr是一种办法,使用的条件下比较特殊。接下来介绍一种技巧,从左到右查找第二个相同的字符:

    char *s = "Hello";
    char *p = strchr(s,'l');
    p = strchr(p+1,'l');
    printf("%s\n",p);

第一次查找’l’指针所到的位置是2(0、1、2,共计移动三次),那么接下来找’l’,则从位置3开始找起,对应代码里的p+1。

六、strstr函数

char * strstr( const char *s1, const char *s2 );

在字符串中寻找一个字符串(不忽略大小写)

    char *s1 = "HELLO123hello";
    char *s2 = "hello";
    printf("%s\n",strstr(s1,s2));

C语言中与字符串有关函数讨论以及安全性能问题_第11张图片

char * strcasestr( const char *s1, const char *s2 );

在字符串中寻找一个字符串(忽略大小写)

char *s1 = "HELLO123hello";
char *s2 = "hello";
printf("%s\n",strcasestr(s1,s2));

C语言中与字符串有关函数讨论以及安全性能问题_第12张图片

那么接下来有一个问题来了,如果使用strcpy和strcat函数导致数组越界怎么办?
给大家举个例子:
s1 = {“123456”};

s2 = {“123”};

这种情况下我们使用strcpy和strcat函数,肯定会出现报错的情况,但是又不想大面积更改代码。建议看看下面的内容。

安全版本

反思:使用strcpy和strcat都有可能出现数组内存不够导致越界的情况发生,于是就有了下面的安全版本的诞生。尽可能的使用安全版本

char* strncpy( char* restrict dst, const char* restrict src, size_t n );

char* strncat( char* restrict s1, const char* restrict s2, size_t n );

int strncmp( const char* s1, const char* s2, size_t n );

这里的strncmp函数,表示为比较两个字符串的内容。n:比较字符串前n个字符。

举个栗子:

 *s1 = {"abcde"};
 *s2 = {"abcdef123"}

如果是正常使用strcmp函数,会出现报错的情况。
现在改用strncmp方式,最后多加入一个参数n。(strncmp(s1,s2,n),此时n的数值为min(strlen(s1),strlen(s2)),即此时n取值为s1的字符串长度,max = 5,min = 1。理论上是可以取0,但是没有什么实际的意义,反而占用计算机程序资源)

写在最后:如果你觉得这篇文章写得不错或对你有帮助,就点个赞吧~~

你可能感兴趣的:(C/C++编程)