C语言之字符串函数一

导读:本篇文章讲解 C语言之字符串函数一,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在常量字符串或字符数组中,字符串常量适用于那些对它不做修改的字符串函数。

求字符串长度:

1:strlen函数:size_t strlen(const char*str)【size_t=unsigned int】

举例:

#include<stdio.h>
#include<string.h>
int main()
{
	int len = strlen("hello,C");
	printf("%d\n", len);
	return 0;
}

字符串已经’\0’作为结束标志,strlen函数返回的是在字符串中’\0’前面出现的字符个数(不包含‘\0’),因此输出结果为6

6

但如果我们将其换一种写法,输出结果还会是6吗?

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = { 'h','e','l','l','o','C' };
	int len = strlen(arr);
	printf("%d\n", len);
	return 0;
}

**参数指向的字符串必须要以’\0’结束。

74

输出结果为什么是74呢?原因为,此时的hello,C,被我们存放在了字符数组而不是字符串,而字符数组并不包含’\0‘,但strlen函数只有遇到’\0’会停止计算长度,因此这种情况下,strlen函数会在随机值中继续查找,直到碰到’\0’,才会输出长度。

strlen函数返回的类型是size_t(unsigned int)

证明如下:
在这里插入图片描述对上述示例中的stlen函数的返回值类型,我们进行了调整。
左边输出结果为hehe,原因:由于strlen函数的返回值类型是size_t(unsigned int),因此即使字符串”abc”和字符串“abcdef”相减,都不会返回-3,系统会将-3进行,按无符号整数输出。
右边的strlen函数的返回值类型是int,是有符号整数,因此函数返回值为-3.

2:使用指针:

#include<stdio.h>
#include<assert.h>
int my_strlen(const char* str)//const修饰指针char*
//由于要求的字符串是常量字符串,因此指针指向的内容无法被改变
{
	assert(str != NULL);assert(断言):如果出现括号中的情况,则程序会停止运行
	int count = 0;
	while (*str != 0)
	{
		count++;
		str++;
	}
	return count;
}
int main()
{
	char arr[] =("abcdef");
	int my_strlens = my_strlen(arr);
	printf("%d\n", my_strlens);	
}
6

注意:strlen函数的返回值是无符号整数,因此不会出现负数。
证明如下:

#include<stdio.h>
#include<string.h>
int main()
{
	if ((strlen("abc") - strlen("abcdef")) > 0)
		printf("hehe");fan
	else
		printf("haha");
}
hehe

长度不受限制的字符串函数:strcpy/strcat/strcmp

strcpy:char* strcpy(destination,resource)

举例:

#include<stdio.h>
#include<string.h>
#include<assert.h>
char* my_strcpy(char* dest,const  char* res)//做字符串拷贝时,源头字符串不会发生改变变,可以用const修饰
{
	assert(dest != NULL);
	assert(res != NULL);
	char* ret = dest;//定义指针ret,指向dest
	while (*dest++ = *res++)//遇到'\0',循环终止
	{
		;
	}
	return ret;//注意:这里不能直接返回dest,因此此时的dest已经不是目地空间的起始地址了
}
int main()
{
	char arr1[] = "早上好呀";
	char arr2[] = "小懒虫";
	strcpy_s(arr1, arr2);
	my_strcpy(arr1,arr2);
	printf("%s\n", arr1);
	return 0;
}
小懒虫

注意:*dest++ = res++,运算符和++都属于单目运算符,两者的优先级是一样的,结合性的方向是从右到左。
因此,有些小伙伴会认为这个表达式的运算顺序是:dest/res先自身+1,其次进行解引用,其实这种想法是错误的。
正确的运算顺序应该是:首先解引用指针变量dest/res,然后dest/res再自身加1,之所以不按照从右向左的结合性,是因为++自身的特性引起的。

使用strcpy函数时,需要注意的事项:

1:源字符串必须以’\0’结束
举例:

 char arr[] = { 'h','e','l','l','o' };

如果源字符串是上述这种不包含’\0’的,编译器会一直往后找’\0’,因此很有可能b发生越界访问。
2:会将源字符串中的’\0’拷贝到目标空间
举例:

 char arr[] = "bit";

arr其实有四个字符,其中还包含’\0’.
3:目标空间必须足够大,以确保源字符串能够完整放入
举例:

 char arr[] = "bit";
char arr1[] = "hello,world";

如果是将arr1放入arr中,是不能实现的,因为arr只能存放4个字符,而arr1有12个字符
4:目标空间必须可变

 char *p = "hello,world";

如果目标空间是如上所示这种,是无法将其它字符串拷入其中,因为此时p指向的是常量字符串,其无法被改变,如果强制性被改变,会导致程序崩溃。

strcat:

目标空间必须足够大:
举例:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "hello";
	char arr2[] = "world";
	strcat_s(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

如上所示代码:由于arr1的空间不够大,只能存放6个字符,因此将arr2拷贝到arr1的过程,会导致程序崩溃。
在这里插入图片描述通过调试验证源字符串中的”\0‘也被拷贝过去了
在这里插入图片描述

使用strcat函数时,需要注意的事项:

1:源字符串必须以’\0’结束
2:目标空间必须足够大
3:目标空间必须可修改
以上三点,具体证明结果可参考上面的strcpy函数
4:字符串自己追加自己
证明如下:

#include<stdio.h>
#include<assert.h>
char* my_strcat(char* dest,const char* res)
{
	assert(*dest!=NULL);
	assert(res);
	char* ret = dest;
	//先找目标字符串的结束标志
	while (*dest != '\0')
	{
		dest++;
	}
	//字符串自己进行追加
	while (*dest++ = *res++)
	{
		;
	}
	return ret;//不能直接返回dest,因为此时的dest并不是目标空间的首地址
}
int main()
{
	char arr1[30] = "hello";
	char arr2[] = "world";
	my_strcat(arr1, arr2);
	printf("%s ", arr1);
	return 0;
}
helloworld

通如下路径,我们可以查找各种库函数的实现方法:
在这里插入图片描述在这里插入图片描述

strcmp:int strcmp(const charstr1,const charstr2)

举例:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "bbc";
	//如果str1>str2,返回大于零的数字,str1<str2返回小于零的数字,二者相等返回0
	int ret=strcmp(arr1, arr2);
	printf("%d ", ret);
	return 0;
}

为什么输出结果是-1呢?如果strcmp比较的是字符串的长度,输出结果应该为大于0的数字

-1

由此我们可以得到结论:strcmp函数在比较字符串的时候,实际比较的是首元素的ASCII码值,如果首元素ASCII码相等,则依次比较第二个第三个,直到不相等。

标准规定: 如果str1>str2,返回大于零的数,str1<str2返回小于零的数,二者相等返回0
在VS编译器下,如果str1>str2,返回1,str1<str2返回-1,二者相等返回0
而在Linux-gcc系统下,strcmp函数返回的是ASCII的差值

因此在使用strcmp函数的时候,不能将函数的返回值设置为具有局限的:
举例:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "bbc";
	//1,-1,0只是在VS编译器下,strcmpy函数返回的结果,但C语言并为这样定义
	if (strcmp(arr1, arr2) == 1)
	{
		printf("str1>str2");
	}
	else if (strcmp(arr1, arr2) == 0)
	{
		printf("str1=str2");
	}
	else if (strcmp(arr1, arr2) == -1)
	{
		printf("str1<str2");
	}
	return 0;
}

正确写法:

if (strcmp(arr1, arr2)>0)
	{
		printf("str1>str2");
	}
	else if (strcmp(arr1, arr2) == 0)
	{
		printf("str1=str2");
	}
	else if (strcmp(arr1, arr2) <0)
	{
		printf("str1<str2");
	}

用库函数定义的方法进行实现:

#include<stdio.h>
#include<string.h>
#include<assert.h>
int my_strcmp(const char*str1,const char*str2)//字符串只是进行比较,并会改变值,因此可以用const修饰
{
	assert(str1 && str2);
	while (*str1 == *str2)
	{
		if (*str1 && *str2 == '\0')//字符串相等
		{
			return 0;
		}
		str1++;
		str2++;
	}
	return (*str1 - *str2);
}
int main()
{
	char arr1[] = "abcsdf";
	char arr2[] = "nihao";
	int ret=my_strcmp(arr1, arr2);
	printf("%d", ret);
	return 0;
}
-13

上述所讲的strcpy/strcat/strcmp函数,都是不受长度限制的函数,因此特们不太安全,有时会强制性的进行字符串操作。因此我们引出下受长度限制的字符串函数:

长度受限制的字符串函数:strncpy/strncat/strncmp

strncpy:charstrncpy(chardest,onst char*res,size_t count(单位是字节))

拷贝num个字符从源字符串到目标空间,如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加\0,直到num个
举例:

int main()
{
	char arr1[30] = "abcdef";
	char arr2[] = "bit";
	strncpy_s(arr1, arr2, 8);
	printf("%s ", arr1);
	return 0;
}
bit

使用库函数定义的方法实现:

#include<stdio.h>
#include<string.h>
char* my_strncpy(char* dest,const char* source,size_t count)
{
    char* start = dest;
    //进行字符串拷贝
    while (count && (*dest++ = *source++))   
        count--;
    //将目标空间多出来的部分追加\0
    if (count)                             
        while (--count)
            *dest++ = '\0';
    //返回目标空间的首元素地址
    return(start);
}
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "bit";
    char* ret=my_strncpy(arr1, arr2, 6);
    printf("%s ", ret);
	return 0;
}
bit

strncat:charstrncat(chardest,const *strres,size_t count)

指定长度的追加,追加完毕后,给后面加\0

举例:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[30] = "hello";
	char arr2[] = "world";
	strncat_s(arr1, arr2, 3);
	printf("%s\n", arr1);
	return 0;
}
hellowor

使用库函数定义的方法实现:

#include<stdio.h>
#include<string.h>
char* my_strncat(char* front,const char* back,size_t count)
{
    char* start = front;

    while (*front++)
        ;
    front--;//先找到目标空间中字符串的结束标志
    while (count--)
        if (!(*front++ = *back++))//将两个字符串进行连接
            return(start);
    *front = '\0';//给连接后的字符串添加'\0'
    return(start);
}
int main()
{
    char arr1[30] = "hello";
    char arr2[] = "world";
    char* ret = my_strncat(arr1, arr2, 4);
    printf("%s ", ret);
    return 0;
}
helloworl

strncmp:int strcmp(const charstr1,const charstr2,size_t num)

标准规定: 第一个字符串大于第二个字符串,则返回大于零的数字
第一个字符串小于第二个字符串,则返回小于零的数字
两个字符串相等,返回0

举例:

int main()
{
    char arr1[30] = "abblo";
    char arr2[] = "abbld";
    int ret = strncmp(arr1, arr2, 4);//第三个参数为比较的字节数
    printf("%d ", ret);
    return 0;
}

strncmp函数和strcmp函数不同的是,该函数对所比较的字符长度进行了限制,如上述所示arr1(abblo)和str2(abbld),前四个元素的ASCII码是相同的,但由于我们对二者所比较的长度进行了限制,因此,第五个元素并不会进行比较,所以输出结果为0

0

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/81480.html

(0)

相关推荐

半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!