Error[8]: Undefined offset: 31, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

C语言中对字符和字符串的处理很频繁,但是C语言本身的类型中是没有字符串类型,字符串通常放在 常量字符串 中或者 字符数组 中。


常量字符串,顾名思义,就是这个字符串当成一个常量,我们知道常量是不可以被修改的,所以常量字符串适用于那些对它不做修改的字符串函数。




目录


一、求字符串长度

1、库函数strlen


二、字符串函数

1、字符串拷贝函数

1.1  库函数strcpy

2、字符串追加函数

2.1 库函数strcat

3、 字符串比较函数

3.1 看函数strcmp



一、求字符串长度 1、库函数strlen

 库函数strlen是用来求字符串长度的函数,从函数的声明中可以知道,函数的形式参数的一个字符型指针,说明用来接收一个字符型变量的地址,而函数的返回值是无符号类型的整型。


运用这个函数的时候,要注意以下几点(后面会有相应的代码对每一点说明):

第一点:参数指向的字符串必须要以 '\0' 结束,我们知道,字符串的结束标志是 '\0',本身就已经自带了 '\0' ,但是如果求得是一个字符数组的长度了?那么定义这个字符数组的时候,它的内容也必须加上 '\0' 。


第二点:库函数strlen返回的是在字符串(或字符数组)中 '\0' 前面出现的字符个数(不包含 '\0')。


因为strlen函数的结束标志就是 '\0' ,当这个函数内部运行到看见 '\0' 的时候,它就会返回 '\0' 前面的所有字符个数。


第三点:注意函数的返回值是size_t,是无符号整型(易错)。



代码1:

#include
#include//strlen函数的头文件
int main()
{
	char* p = "abcdef";
	char arr[] = { 'h','i','j','k','l','\0' };
	int lenth1 = strlen(p);
	int lenth2 = strlen(arr);
	printf("字符串的长度:%d\n", lenth1);
	printf("字符数组的长度:%d\n", lenth2);
	return 0;
}

 以上代码对应的是上面的

一、二点。


可以看出,字符串自带了 '\0' ,所以结果是6;而定义字符数组的时候,内容的最后放上了 '\0' ,所以打印的结果是5。


而不管是字符串还是字符数组,strlen函数的返回值都是 '\0' 前面的字符个数,并没有加上 '\0' ,这也对应着 '\0' 是函数strlen的结束标志。



代码2:

#include
#include
int main()
{
	char* p = "abcdef";
	if (strlen(p) > -1)
	{
		printf(">\n");
	}
	else
	{
		printf("<\n");
	}
	return 0;
}

 我相信,可能有很多同学会以为打印的是<。


代码对应上面第三点,函数strlen的返回值是一个无符号整型,所以 -1 与其返回值比较的时候,也必须先要转换成无符号整型,如下图所示。



自定义函数模拟实现库函数strlen的功能: 

我们上面所说的,库函数strlen的结束标志是 '\0' ,那么函数的内部是如何实现的?我们可以自己定义一个函数实现相同的功能(特别是当题目中不允许用库函数strlen求长度的时候)。


#include
#include
size_t my_strlen(const char* p)
{
	int count = 0;
	assert(p);
	while (*p) //当循环到指针指向'\0'时,它的ASCII为0,就会跳出循环
	{
		count++;
		p++;
	}
	return count;
}
int main()
{
	char* p = "abcdef";
	char arr[] = { 'h','i','j','k','l','\0' };
	printf("字符串长度:%d\n", my_strlen(p));
	printf("字符数组长度:%d\n", my_strlen(arr));
	return 0;
}

 顺便说一下库函数assert,它的头文件是assert.h,它的功能是当传递过来的指针是空指针的时候,就会报错,这样可以保证指针的时效性,当一个函数接收的是指针的时候,其内部最好用用函数assert。


自定义代码很好的诠释了 ‘\0’ 的重要性,所以用库函数strlen的时候,一定要注意 '\0'。




二、字符串函数 1、字符串拷贝函数 1.1  库函数strcpy

 库函数strcpy是将一个字符串(或字符数组)的内容(这里我们叫源空间)拷贝到另外一个字符串(或字符数组)里面去(这里我们叫目标空间)。


从函数的申明里面可以看到,是将指针source所指向的源空间里面的内容拷贝到指针destination所指向的目标空间里面去;这里函数的返回类型是字符型指针,返回的是目标空间的地址。


使用库函数strcpy要注意的几点:

第一点:源空间里面的内容必须以 '\0' 结束,即如果是字符串,它自带 '\0' ;如果是字符数组,那么自己在定义字符数组的时候,数组的内容必须要有 '\0' ,而目标空间有没有 '\0' 都剋ui可以说 '\0' 也是函数strcpy的结束标志

第二点:拷贝的时候会将源空间里的 '\0' 拷贝到目标空间里面区。


第三点:目标空间足够大,以确保能存放源空间的内容;目标空间必须可变。


所以目标空间只能是字符数组,因为字符数组的内容才可以更改,而不能用指针:例如char* p = “abc”,因为这是常量字符串,里面的内容是不能够被修改的。



代码1:

#include
#include
int main()
{
	//将arr所指向的空间作为目标空间,可变空间
	char arr[20] = { 0 };
	char* p = "abcdef";//第一种
	char arr1[] = "hijklm";//第二种
	char arr2[] = { 'o','p','q','r','s','t','\0' };//第三种
	//将p所指向的空间作为源空间
	char* ret1 = strcpy(arr, p);
    printf("将p所指向的空间作为源空间时:%s\n", ret1);
	//将arr1所指向的空间作为源空间
	char* ret2 = strcpy(arr, arr1);
	printf("将arr1所指向的空间作为源空间时:%s\n", ret2); 
	//将arr2所指向的空间作为源空间
	char* ret3 = strcpy(arr, arr2);
	printf("将arr2所指向的空间作为源空间时:%s\n", ret3);
	return 0;
}

 对应上面的第一点和第三点:可以看到,不管源空间时第一种,第二种还是第三种,源空间的末尾都必须带有 '\0' ,而目标空间里,'\0' 可有可无,且目标空间必须足够大,且目标空间必须可变,才能完全拷贝过去。


对应上面的第二点:并且拷贝的时候源空间里的 '\0' 也拷贝了过去,也必须拷贝过去,因为库函数strcpy内部也是通过 '\0' 结束的,即 '\0' 也是函数strcpy结束的标志,这一点类似函数strlen。



自定义函数模拟实现库函数strcpy的功能: 

我们上面所说的,库函数strcpy的结束标志也是 '\0' ,那么函数的内部是如何实现的?我们可以自己定义一个函数实现相同的功能(特别是当题目中不允许用库函数strcpy拷贝内容的时候)。


#include
char* my_strcpy(char* dest, const char* src)
{
	char* a = dest;
	while (*src)//循环到指针指向'\0'时,跳出循环
	{
		*dest++ = *src++;
	}
	*dest = '\0';//跳出循环的时候,'\0'没有拷贝过去
	return a;
}
int main()
{
		//将arr所指向的空间作为目标空间,可变空间
	char arr[20] = { 0 };
	char* p = "abcdef";//第一种
	char arr1[] = "hijklm";//第二种
	char arr2[] = { 'o','p','q','r','s','t','\0' };//第三种
	//将p所指向的空间作为源空间
	char* ret1 = my_strcpy(arr, p);
    printf("将p所指向的空间作为源空间时:%s\n", ret1);
	//将arr1所指向的空间作为源空间
	char* ret2 = my_strcpy(arr, arr1);
	printf("将arr1所指向的空间作为源空间时:%s\n", ret2); 
	//将arr2所指向的空间作为源空间
	char* ret3 = my_strcpy(arr, arr2);
	printf("将arr2所指向的空间作为源空间时:%s\n", ret3);
	return 0;
}

 结果和用库函数strcpy拷贝的一样,最重要的是要将源空间里的 '\0' 拷贝过去。



2、字符串追加函数 2.1 库函数strcat

 库函数strcat是将一个字符串(或字符数组)的内容(源空间)追加到另外一个字符串(或字符数组)里面去(目标空间)。


从函数的申明里面可以看到,是将指针source所指向的源空间里面的内容追加到指针destination所指向的目标空间里面去;这里函数的返回类型是字符型指针,返回的是目标空间的地址。


使用库函数strcat要注意的几点:

第一点:源空间和目标空间里面的内容必须以 '\0' 结束,即如果是字符串,它自带 '\0' ;如果是字符数组,那么自己在定义字符数组的时候,数组的内容必须要有 '\0' ,目标空间和源空间必须要有 '\0' 也是函数strcat的追加的原理和结束标志。


第二点:追加的时候会将源空间里的第一个字符会覆盖掉目标空间的 '第三点' ,并且把自身的 '\

0' 追加到目标空间里面区。


第一点和第三点::目标空间足够大,以确保能存放源空间的内容;目标空间必须可变。


所以目标空间只能是字符数组,因为字符数组的内容才可以更改,而不能用指针:例如char* p = “abc”,因为这是常量字符串,里面的内容是不能够被修改的。



代码1:

#include
#include
int main()
{
	//将arr0、arr00、arr000所指向的空间作为目标空间,可变空间,必须带有'\0'
	char arr0[20] = "ppppp";
	char arr00[20] = "uuuuu";
	char arr000[20] = "vvvvv";
	char* p = "abcdef";//第一种
	char arr1[] = "hijklm";//第二种
	char arr2[] = { 'o','p','q','r','s','t','\0' };//第三种
	//将p所指向的空间作为源空间
	char* ret1 = strcat(arr0, p);
    printf("将p所指向的空间作为源空间时:%s\n", ret1);
	//将arr1所指向的空间作为源空间
	char* ret2 = strcat(arr00, arr1);
	printf("将arr1所指向的空间作为源空间时:%s\n", ret2); 
	//将arr2所指向的空间作为源空间
	char* ret3 = strcat(arr000, arr2);
	printf("将arr2所指向的空间作为源空间时:%s\n", ret3);
	return 0;
}

 对应上面的第二点:可以看到,源空间和目标空间的末尾都必须带有 '\0' ,且目标空间必须足够大,且目标空间必须可变,才能完全追加过去。


对应上面的覆盖掉目标空间的 '自定义函数模拟实现库函数strcat的功能:' 追加的时候会将源空间里的第一个字符会覆盖掉目标空间的 '比较的原理' ,并且把自身的 '\0' 追加到目标空间里面区。


和函数strcpy不同的是,目标空间和源空间必须都有 '\0' 才是函数strcat结束的标志。



自定义函数模拟实现库函数strcmp的功能: 

我们上面所说的,库函数strcat的结束标志也是 '\0' ,那么函数的内部是如何实现的?我们可以自己定义一个函数实现相同的功能(特别是当题目中不允许用库函数strcat追加内容的时候)。


#include
char* my_strcat(char* dest, const char* src)
{
	char* a = dest;
	while (*dest)//该循环是为了是指针dest指向目标空间的'\0'
	{
		dest++;
	}
	while (*src)
	{
		*dest++ = *src++;
	}
	*dest = '\0'; //跳出循环的时候,源空间里的'\0'没有拷贝过去
	return a;
}
int main()
{
	//将arr0、arr00、arr000所指向的空间作为目标空间,可变空间,必须带有'\0'
	char arr0[20] = "ppppp";
	char arr00[20] = "uuuuu";
	char arr000[20] = "vvvvv";
	char* p = "abcdef";//第一种
	char arr1[] = "hijklm";//第二种
	char arr2[] = { 'o','p','q','r','s','t','\0' };//第三种
	//将p所指向的空间作为源空间
	char* ret1 = my_strcat(arr0, p);
	printf("将p所指向的空间作为源空间时:%s\n", ret1);
	//将arr1所指向的空间作为源空间
	char* ret2 = my_strcat(arr00, arr1);
	printf("将arr1所指向的空间作为源空间时:%s\n", ret2);
	//将arr2所指向的空间作为源空间
	char* ret3 = my_strcat(arr000, arr2);
	printf("将arr2所指向的空间作为源空间时:%s\n", ret3);
	return 0;
}

 结果和用库函数strcat拷贝的一样,最重要的是追加的时候要将源空间里的第一个字符strncnp,并且把自身的 '\0' 追加到目标空间里面区。



3、 字符串比较函数 3.1 看函数strcmp

  库函数strcmp是比较两个字符串的大小的。


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

那么两个字符串strncat是是什么了?

比如 “abc” 和 “abdc”

是对应的字符的ASCII码值进行大小比较的,如果对应字符的ASCII码值相等,就依次比较下一个,'\0' 也要比较,直到比较出不相等的对应字符的ASCII码值为止。


但是如果两个字符串一样,比较到 '\0' 为止,'\0' 也要比较,就不再比较了,所以 '\0' 在函数strcmp里就没有前面的函数那么重要,它在strcmp函数里,只是为了防止两个字符串相等,必须要用 '\0' 来结束这个函数,因为一般来说,如果要比较两个字符串,那么肯定是会不一样的。



代码1:

#include
#include
int main()
{
	char* p = "abc";
	char* p1 = "abcd";
	int ret = strcmp(p, p1);
	if (ret == 0)
		printf("p=p1");
	else if (ret > 0)
		printf("p>p1");
	else
		printf("p

 两个字符串前三个字符a、b、c相等,第一个字符串的第四个字符 '\0' 小于第二个字符串的第四个字符 'd' ,所以代码结果是 p



 strncmp

函数的内部是如何实现的?我们可以自己定义一个函数实现相同的功能(特别是当题目中不允许用库函数strcmp比较大小的时候)。


#include
int my_strcmp(const char* str1, const char* str2)
{
	while (*str1 == *str2)
	{
		if (*str1 == 0)//防止两个字符串一样,用'\0'结束函数
		{
			return 0;
		}
		str1++;
		str2++;
	}
	if (*str1 > *str2)
	{
		return 1;
	}
	else
	{
		return -1;
	}
}
int main()
{
	char arr[] = "abcdef";
	char* p = "abcdhg";
	int ret = my_strcmp(arr, p);
	if (ret > 0)//通过返回值判断
	{
		printf("arr>p");
	}
	else if (ret < 0)
	{
		printf("arr

 

 需要注意的地方就是不要忘记如果两个字符串一样,需要用 '\0' 来结束函数。



上面所说的库函数是长度不受限制的字符串函数,那么长度受限制的库函数[+++]、[+++]和[+++]是如何实现的了?可以看这一篇文章:https://blog.csdn.net/m0_68136339/article/details/123906018 

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 166, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
Error[8]: Undefined offset: 32, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

C语言中对字符和字符串的处理很频繁,但是C语言本身的类型中是没有字符串类型,字符串通常放在 常量字符串 中或者 字符数组 中。


常量字符串,顾名思义,就是这个字符串当成一个常量,我们知道常量是不可以被修改的,所以常量字符串适用于那些对它不做修改的字符串函数。




目录


一、求字符串长度

1、库函数strlen


二、字符串函数

1、字符串拷贝函数

1.1  库函数strcpy

2、字符串追加函数

2.1 库函数strcat

3、 字符串比较函数

3.1 看函数strcmp



一、求字符串长度 1、库函数strlen

 库函数strlen是用来求字符串长度的函数,从函数的声明中可以知道,函数的形式参数的一个字符型指针,说明用来接收一个字符型变量的地址,而函数的返回值是无符号类型的整型。


运用这个函数的时候,要注意以下几点(后面会有相应的代码对每一点说明):

第一点:参数指向的字符串必须要以 '\0' 结束,我们知道,字符串的结束标志是 '\0',本身就已经自带了 '\0' ,但是如果求得是一个字符数组的长度了?那么定义这个字符数组的时候,它的内容也必须加上 '\0' 。


第二点:库函数strlen返回的是在字符串(或字符数组)中 '\0' 前面出现的字符个数(不包含 '\0')。


因为strlen函数的结束标志就是 '\0' ,当这个函数内部运行到看见 '\0' 的时候,它就会返回 '\0' 前面的所有字符个数。


第三点:注意函数的返回值是size_t,是无符号整型(易错)。



代码1:

#include
#include//strlen函数的头文件
int main()
{
	char* p = "abcdef";
	char arr[] = { 'h','i','j','k','l','\0' };
	int lenth1 = strlen(p);
	int lenth2 = strlen(arr);
	printf("字符串的长度:%d\n", lenth1);
	printf("字符数组的长度:%d\n", lenth2);
	return 0;
}

 以上代码对应的是上面的

一、二点。


可以看出,字符串自带了 '\0' ,所以结果是6;而定义字符数组的时候,内容的最后放上了 '\0' ,所以打印的结果是5。


而不管是字符串还是字符数组,strlen函数的返回值都是 '\0' 前面的字符个数,并没有加上 '\0' ,这也对应着 '\0' 是函数strlen的结束标志。



代码2:

#include
#include
int main()
{
	char* p = "abcdef";
	if (strlen(p) > -1)
	{
		printf(">\n");
	}
	else
	{
		printf("<\n");
	}
	return 0;
}

 我相信,可能有很多同学会以为打印的是<。


代码对应上面第三点,函数strlen的返回值是一个无符号整型,所以 -1 与其返回值比较的时候,也必须先要转换成无符号整型,如下图所示。



自定义函数模拟实现库函数strlen的功能: 

我们上面所说的,库函数strlen的结束标志是 '\0' ,那么函数的内部是如何实现的?我们可以自己定义一个函数实现相同的功能(特别是当题目中不允许用库函数strlen求长度的时候)。


#include
#include
size_t my_strlen(const char* p)
{
	int count = 0;
	assert(p);
	while (*p) //当循环到指针指向'\0'时,它的ASCII为0,就会跳出循环
	{
		count++;
		p++;
	}
	return count;
}
int main()
{
	char* p = "abcdef";
	char arr[] = { 'h','i','j','k','l','\0' };
	printf("字符串长度:%d\n", my_strlen(p));
	printf("字符数组长度:%d\n", my_strlen(arr));
	return 0;
}

 顺便说一下库函数assert,它的头文件是assert.h,它的功能是当传递过来的指针是空指针的时候,就会报错,这样可以保证指针的时效性,当一个函数接收的是指针的时候,其内部最好用用函数assert。


自定义代码很好的诠释了 ‘\0’ 的重要性,所以用库函数strlen的时候,一定要注意 '\0'。




二、字符串函数 1、字符串拷贝函数 1.1  库函数strcpy

 库函数strcpy是将一个字符串(或字符数组)的内容(这里我们叫源空间)拷贝到另外一个字符串(或字符数组)里面去(这里我们叫目标空间)。


从函数的申明里面可以看到,是将指针source所指向的源空间里面的内容拷贝到指针destination所指向的目标空间里面去;这里函数的返回类型是字符型指针,返回的是目标空间的地址。


使用库函数strcpy要注意的几点:

第一点:源空间里面的内容必须以 '\0' 结束,即如果是字符串,它自带 '\0' ;如果是字符数组,那么自己在定义字符数组的时候,数组的内容必须要有 '\0' ,而目标空间有没有 '\0' 都剋ui可以说 '\0' 也是函数strcpy的结束标志

第二点:拷贝的时候会将源空间里的 '\0' 拷贝到目标空间里面区。


第三点:目标空间足够大,以确保能存放源空间的内容;目标空间必须可变。


所以目标空间只能是字符数组,因为字符数组的内容才可以更改,而不能用指针:例如char* p = “abc”,因为这是常量字符串,里面的内容是不能够被修改的。



代码1:

#include
#include
int main()
{
	//将arr所指向的空间作为目标空间,可变空间
	char arr[20] = { 0 };
	char* p = "abcdef";//第一种
	char arr1[] = "hijklm";//第二种
	char arr2[] = { 'o','p','q','r','s','t','\0' };//第三种
	//将p所指向的空间作为源空间
	char* ret1 = strcpy(arr, p);
    printf("将p所指向的空间作为源空间时:%s\n", ret1);
	//将arr1所指向的空间作为源空间
	char* ret2 = strcpy(arr, arr1);
	printf("将arr1所指向的空间作为源空间时:%s\n", ret2); 
	//将arr2所指向的空间作为源空间
	char* ret3 = strcpy(arr, arr2);
	printf("将arr2所指向的空间作为源空间时:%s\n", ret3);
	return 0;
}

 对应上面的第一点和第三点:可以看到,不管源空间时第一种,第二种还是第三种,源空间的末尾都必须带有 '\0' ,而目标空间里,'\0' 可有可无,且目标空间必须足够大,且目标空间必须可变,才能完全拷贝过去。


对应上面的第二点:并且拷贝的时候源空间里的 '\0' 也拷贝了过去,也必须拷贝过去,因为库函数strcpy内部也是通过 '\0' 结束的,即 '\0' 也是函数strcpy结束的标志,这一点类似函数strlen。



自定义函数模拟实现库函数strcpy的功能: 

我们上面所说的,库函数strcpy的结束标志也是 '\0' ,那么函数的内部是如何实现的?我们可以自己定义一个函数实现相同的功能(特别是当题目中不允许用库函数strcpy拷贝内容的时候)。


#include
char* my_strcpy(char* dest, const char* src)
{
	char* a = dest;
	while (*src)//循环到指针指向'\0'时,跳出循环
	{
		*dest++ = *src++;
	}
	*dest = '\0';//跳出循环的时候,'\0'没有拷贝过去
	return a;
}
int main()
{
		//将arr所指向的空间作为目标空间,可变空间
	char arr[20] = { 0 };
	char* p = "abcdef";//第一种
	char arr1[] = "hijklm";//第二种
	char arr2[] = { 'o','p','q','r','s','t','\0' };//第三种
	//将p所指向的空间作为源空间
	char* ret1 = my_strcpy(arr, p);
    printf("将p所指向的空间作为源空间时:%s\n", ret1);
	//将arr1所指向的空间作为源空间
	char* ret2 = my_strcpy(arr, arr1);
	printf("将arr1所指向的空间作为源空间时:%s\n", ret2); 
	//将arr2所指向的空间作为源空间
	char* ret3 = my_strcpy(arr, arr2);
	printf("将arr2所指向的空间作为源空间时:%s\n", ret3);
	return 0;
}

 结果和用库函数strcpy拷贝的一样,最重要的是要将源空间里的 '\0' 拷贝过去。



2、字符串追加函数 2.1 库函数strcat

 库函数strcat是将一个字符串(或字符数组)的内容(源空间)追加到另外一个字符串(或字符数组)里面去(目标空间)。


从函数的申明里面可以看到,是将指针source所指向的源空间里面的内容追加到指针destination所指向的目标空间里面去;这里函数的返回类型是字符型指针,返回的是目标空间的地址。


使用库函数strcat要注意的几点:

第一点:源空间和目标空间里面的内容必须以 '\0' 结束,即如果是字符串,它自带 '\0' ;如果是字符数组,那么自己在定义字符数组的时候,数组的内容必须要有 '\0' ,目标空间和源空间必须要有 '\0' 也是函数strcat的追加的原理和结束标志。


第二点:追加的时候会将源空间里的第一个字符会覆盖掉目标空间的 '第三点' ,并且把自身的 '\

0' 追加到目标空间里面区。


第一点和第三点::目标空间足够大,以确保能存放源空间的内容;目标空间必须可变。


所以目标空间只能是字符数组,因为字符数组的内容才可以更改,而不能用指针:例如char* p = “abc”,因为这是常量字符串,里面的内容是不能够被修改的。



代码1:

#include
#include
int main()
{
	//将arr0、arr00、arr000所指向的空间作为目标空间,可变空间,必须带有'\0'
	char arr0[20] = "ppppp";
	char arr00[20] = "uuuuu";
	char arr000[20] = "vvvvv";
	char* p = "abcdef";//第一种
	char arr1[] = "hijklm";//第二种
	char arr2[] = { 'o','p','q','r','s','t','\0' };//第三种
	//将p所指向的空间作为源空间
	char* ret1 = strcat(arr0, p);
    printf("将p所指向的空间作为源空间时:%s\n", ret1);
	//将arr1所指向的空间作为源空间
	char* ret2 = strcat(arr00, arr1);
	printf("将arr1所指向的空间作为源空间时:%s\n", ret2); 
	//将arr2所指向的空间作为源空间
	char* ret3 = strcat(arr000, arr2);
	printf("将arr2所指向的空间作为源空间时:%s\n", ret3);
	return 0;
}

 对应上面的第二点:可以看到,源空间和目标空间的末尾都必须带有 '\0' ,且目标空间必须足够大,且目标空间必须可变,才能完全追加过去。


对应上面的覆盖掉目标空间的 '自定义函数模拟实现库函数strcat的功能:' 追加的时候会将源空间里的第一个字符会覆盖掉目标空间的 '比较的原理' ,并且把自身的 '\0' 追加到目标空间里面区。


和函数strcpy不同的是,目标空间和源空间必须都有 '\0' 才是函数strcat结束的标志。



自定义函数模拟实现库函数strcmp的功能: 

我们上面所说的,库函数strcat的结束标志也是 '\0' ,那么函数的内部是如何实现的?我们可以自己定义一个函数实现相同的功能(特别是当题目中不允许用库函数strcat追加内容的时候)。


#include
char* my_strcat(char* dest, const char* src)
{
	char* a = dest;
	while (*dest)//该循环是为了是指针dest指向目标空间的'\0'
	{
		dest++;
	}
	while (*src)
	{
		*dest++ = *src++;
	}
	*dest = '\0'; //跳出循环的时候,源空间里的'\0'没有拷贝过去
	return a;
}
int main()
{
	//将arr0、arr00、arr000所指向的空间作为目标空间,可变空间,必须带有'\0'
	char arr0[20] = "ppppp";
	char arr00[20] = "uuuuu";
	char arr000[20] = "vvvvv";
	char* p = "abcdef";//第一种
	char arr1[] = "hijklm";//第二种
	char arr2[] = { 'o','p','q','r','s','t','\0' };//第三种
	//将p所指向的空间作为源空间
	char* ret1 = my_strcat(arr0, p);
	printf("将p所指向的空间作为源空间时:%s\n", ret1);
	//将arr1所指向的空间作为源空间
	char* ret2 = my_strcat(arr00, arr1);
	printf("将arr1所指向的空间作为源空间时:%s\n", ret2);
	//将arr2所指向的空间作为源空间
	char* ret3 = my_strcat(arr000, arr2);
	printf("将arr2所指向的空间作为源空间时:%s\n", ret3);
	return 0;
}

 结果和用库函数strcat拷贝的一样,最重要的是追加的时候要将源空间里的第一个字符strncnp,并且把自身的 '\0' 追加到目标空间里面区。



3、 字符串比较函数 3.1 看函数strcmp

  库函数strcmp是比较两个字符串的大小的。


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

那么两个字符串strncat是是什么了?

比如 “abc” 和 “abdc”

是对应的字符的ASCII码值进行大小比较的,如果对应字符的ASCII码值相等,就依次比较下一个,'\0' 也要比较,直到比较出不相等的对应字符的ASCII码值为止。


但是如果两个字符串一样,比较到 '\0' 为止,'\0' 也要比较,就不再比较了,所以 '\0' 在函数strcmp里就没有前面的函数那么重要,它在strcmp函数里,只是为了防止两个字符串相等,必须要用 '\0' 来结束这个函数,因为一般来说,如果要比较两个字符串,那么肯定是会不一样的。



代码1:

#include
#include
int main()
{
	char* p = "abc";
	char* p1 = "abcd";
	int ret = strcmp(p, p1);
	if (ret == 0)
		printf("p=p1");
	else if (ret > 0)
		printf("p>p1");
	else
		printf("p

 两个字符串前三个字符a、b、c相等,第一个字符串的第四个字符 '\0' 小于第二个字符串的第四个字符 'd' ,所以代码结果是 p



 strncmp

函数的内部是如何实现的?我们可以自己定义一个函数实现相同的功能(特别是当题目中不允许用库函数strcmp比较大小的时候)。


#include
int my_strcmp(const char* str1, const char* str2)
{
	while (*str1 == *str2)
	{
		if (*str1 == 0)//防止两个字符串一样,用'\0'结束函数
		{
			return 0;
		}
		str1++;
		str2++;
	}
	if (*str1 > *str2)
	{
		return 1;
	}
	else
	{
		return -1;
	}
}
int main()
{
	char arr[] = "abcdef";
	char* p = "abcdhg";
	int ret = my_strcmp(arr, p);
	if (ret > 0)//通过返回值判断
	{
		printf("arr>p");
	}
	else if (ret < 0)
	{
		printf("arr

 

 需要注意的地方就是不要忘记如果两个字符串一样,需要用 '\0' 来结束函数。



上面所说的库函数是长度不受限制的字符串函数,那么长度受限制的库函数、[+++]和[+++]是如何实现的了?可以看这一篇文章:https://blog.csdn.net/m0_68136339/article/details/123906018 

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 166, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
Error[8]: Undefined offset: 33, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

C语言中对字符和字符串的处理很频繁,但是C语言本身的类型中是没有字符串类型,字符串通常放在 常量字符串 中或者 字符数组 中。


常量字符串,顾名思义,就是这个字符串当成一个常量,我们知道常量是不可以被修改的,所以常量字符串适用于那些对它不做修改的字符串函数。




目录


一、求字符串长度

1、库函数strlen


二、字符串函数

1、字符串拷贝函数

1.1  库函数strcpy

2、字符串追加函数

2.1 库函数strcat

3、 字符串比较函数

3.1 看函数strcmp



一、求字符串长度 1、库函数strlen

 库函数strlen是用来求字符串长度的函数,从函数的声明中可以知道,函数的形式参数的一个字符型指针,说明用来接收一个字符型变量的地址,而函数的返回值是无符号类型的整型。


运用这个函数的时候,要注意以下几点(后面会有相应的代码对每一点说明):

第一点:参数指向的字符串必须要以 '\0' 结束,我们知道,字符串的结束标志是 '\0',本身就已经自带了 '\0' ,但是如果求得是一个字符数组的长度了?那么定义这个字符数组的时候,它的内容也必须加上 '\0' 。


第二点:库函数strlen返回的是在字符串(或字符数组)中 '\0' 前面出现的字符个数(不包含 '\0')。


因为strlen函数的结束标志就是 '\0' ,当这个函数内部运行到看见 '\0' 的时候,它就会返回 '\0' 前面的所有字符个数。


第三点:注意函数的返回值是size_t,是无符号整型(易错)。



代码1:

#include
#include//strlen函数的头文件
int main()
{
	char* p = "abcdef";
	char arr[] = { 'h','i','j','k','l','\0' };
	int lenth1 = strlen(p);
	int lenth2 = strlen(arr);
	printf("字符串的长度:%d\n", lenth1);
	printf("字符数组的长度:%d\n", lenth2);
	return 0;
}

 以上代码对应的是上面的

一、二点。


可以看出,字符串自带了 '\0' ,所以结果是6;而定义字符数组的时候,内容的最后放上了 '\0' ,所以打印的结果是5。


而不管是字符串还是字符数组,strlen函数的返回值都是 '\0' 前面的字符个数,并没有加上 '\0' ,这也对应着 '\0' 是函数strlen的结束标志。



代码2:

#include
#include
int main()
{
	char* p = "abcdef";
	if (strlen(p) > -1)
	{
		printf(">\n");
	}
	else
	{
		printf("<\n");
	}
	return 0;
}

 我相信,可能有很多同学会以为打印的是<。


代码对应上面第三点,函数strlen的返回值是一个无符号整型,所以 -1 与其返回值比较的时候,也必须先要转换成无符号整型,如下图所示。



自定义函数模拟实现库函数strlen的功能: 

我们上面所说的,库函数strlen的结束标志是 '\0' ,那么函数的内部是如何实现的?我们可以自己定义一个函数实现相同的功能(特别是当题目中不允许用库函数strlen求长度的时候)。


#include
#include
size_t my_strlen(const char* p)
{
	int count = 0;
	assert(p);
	while (*p) //当循环到指针指向'\0'时,它的ASCII为0,就会跳出循环
	{
		count++;
		p++;
	}
	return count;
}
int main()
{
	char* p = "abcdef";
	char arr[] = { 'h','i','j','k','l','\0' };
	printf("字符串长度:%d\n", my_strlen(p));
	printf("字符数组长度:%d\n", my_strlen(arr));
	return 0;
}

 顺便说一下库函数assert,它的头文件是assert.h,它的功能是当传递过来的指针是空指针的时候,就会报错,这样可以保证指针的时效性,当一个函数接收的是指针的时候,其内部最好用用函数assert。


自定义代码很好的诠释了 ‘\0’ 的重要性,所以用库函数strlen的时候,一定要注意 '\0'。




二、字符串函数 1、字符串拷贝函数 1.1  库函数strcpy

 库函数strcpy是将一个字符串(或字符数组)的内容(这里我们叫源空间)拷贝到另外一个字符串(或字符数组)里面去(这里我们叫目标空间)。


从函数的申明里面可以看到,是将指针source所指向的源空间里面的内容拷贝到指针destination所指向的目标空间里面去;这里函数的返回类型是字符型指针,返回的是目标空间的地址。


使用库函数strcpy要注意的几点:

第一点:源空间里面的内容必须以 '\0' 结束,即如果是字符串,它自带 '\0' ;如果是字符数组,那么自己在定义字符数组的时候,数组的内容必须要有 '\0' ,而目标空间有没有 '\0' 都剋ui可以说 '\0' 也是函数strcpy的结束标志

第二点:拷贝的时候会将源空间里的 '\0' 拷贝到目标空间里面区。


第三点:目标空间足够大,以确保能存放源空间的内容;目标空间必须可变。


所以目标空间只能是字符数组,因为字符数组的内容才可以更改,而不能用指针:例如char* p = “abc”,因为这是常量字符串,里面的内容是不能够被修改的。



代码1:

#include
#include
int main()
{
	//将arr所指向的空间作为目标空间,可变空间
	char arr[20] = { 0 };
	char* p = "abcdef";//第一种
	char arr1[] = "hijklm";//第二种
	char arr2[] = { 'o','p','q','r','s','t','\0' };//第三种
	//将p所指向的空间作为源空间
	char* ret1 = strcpy(arr, p);
    printf("将p所指向的空间作为源空间时:%s\n", ret1);
	//将arr1所指向的空间作为源空间
	char* ret2 = strcpy(arr, arr1);
	printf("将arr1所指向的空间作为源空间时:%s\n", ret2); 
	//将arr2所指向的空间作为源空间
	char* ret3 = strcpy(arr, arr2);
	printf("将arr2所指向的空间作为源空间时:%s\n", ret3);
	return 0;
}

 对应上面的第一点和第三点:可以看到,不管源空间时第一种,第二种还是第三种,源空间的末尾都必须带有 '\0' ,而目标空间里,'\0' 可有可无,且目标空间必须足够大,且目标空间必须可变,才能完全拷贝过去。


对应上面的第二点:并且拷贝的时候源空间里的 '\0' 也拷贝了过去,也必须拷贝过去,因为库函数strcpy内部也是通过 '\0' 结束的,即 '\0' 也是函数strcpy结束的标志,这一点类似函数strlen。



自定义函数模拟实现库函数strcpy的功能: 

我们上面所说的,库函数strcpy的结束标志也是 '\0' ,那么函数的内部是如何实现的?我们可以自己定义一个函数实现相同的功能(特别是当题目中不允许用库函数strcpy拷贝内容的时候)。


#include
char* my_strcpy(char* dest, const char* src)
{
	char* a = dest;
	while (*src)//循环到指针指向'\0'时,跳出循环
	{
		*dest++ = *src++;
	}
	*dest = '\0';//跳出循环的时候,'\0'没有拷贝过去
	return a;
}
int main()
{
		//将arr所指向的空间作为目标空间,可变空间
	char arr[20] = { 0 };
	char* p = "abcdef";//第一种
	char arr1[] = "hijklm";//第二种
	char arr2[] = { 'o','p','q','r','s','t','\0' };//第三种
	//将p所指向的空间作为源空间
	char* ret1 = my_strcpy(arr, p);
    printf("将p所指向的空间作为源空间时:%s\n", ret1);
	//将arr1所指向的空间作为源空间
	char* ret2 = my_strcpy(arr, arr1);
	printf("将arr1所指向的空间作为源空间时:%s\n", ret2); 
	//将arr2所指向的空间作为源空间
	char* ret3 = my_strcpy(arr, arr2);
	printf("将arr2所指向的空间作为源空间时:%s\n", ret3);
	return 0;
}

 结果和用库函数strcpy拷贝的一样,最重要的是要将源空间里的 '\0' 拷贝过去。



2、字符串追加函数 2.1 库函数strcat

 库函数strcat是将一个字符串(或字符数组)的内容(源空间)追加到另外一个字符串(或字符数组)里面去(目标空间)。


从函数的申明里面可以看到,是将指针source所指向的源空间里面的内容追加到指针destination所指向的目标空间里面去;这里函数的返回类型是字符型指针,返回的是目标空间的地址。


使用库函数strcat要注意的几点:

第一点:源空间和目标空间里面的内容必须以 '\0' 结束,即如果是字符串,它自带 '\0' ;如果是字符数组,那么自己在定义字符数组的时候,数组的内容必须要有 '\0' ,目标空间和源空间必须要有 '\0' 也是函数strcat的追加的原理和结束标志。


第二点:追加的时候会将源空间里的第一个字符会覆盖掉目标空间的 '第三点' ,并且把自身的 '\

0' 追加到目标空间里面区。


第一点和第三点::目标空间足够大,以确保能存放源空间的内容;目标空间必须可变。


所以目标空间只能是字符数组,因为字符数组的内容才可以更改,而不能用指针:例如char* p = “abc”,因为这是常量字符串,里面的内容是不能够被修改的。



代码1:

#include
#include
int main()
{
	//将arr0、arr00、arr000所指向的空间作为目标空间,可变空间,必须带有'\0'
	char arr0[20] = "ppppp";
	char arr00[20] = "uuuuu";
	char arr000[20] = "vvvvv";
	char* p = "abcdef";//第一种
	char arr1[] = "hijklm";//第二种
	char arr2[] = { 'o','p','q','r','s','t','\0' };//第三种
	//将p所指向的空间作为源空间
	char* ret1 = strcat(arr0, p);
    printf("将p所指向的空间作为源空间时:%s\n", ret1);
	//将arr1所指向的空间作为源空间
	char* ret2 = strcat(arr00, arr1);
	printf("将arr1所指向的空间作为源空间时:%s\n", ret2); 
	//将arr2所指向的空间作为源空间
	char* ret3 = strcat(arr000, arr2);
	printf("将arr2所指向的空间作为源空间时:%s\n", ret3);
	return 0;
}

 对应上面的第二点:可以看到,源空间和目标空间的末尾都必须带有 '\0' ,且目标空间必须足够大,且目标空间必须可变,才能完全追加过去。


对应上面的覆盖掉目标空间的 '自定义函数模拟实现库函数strcat的功能:' 追加的时候会将源空间里的第一个字符会覆盖掉目标空间的 '比较的原理' ,并且把自身的 '\0' 追加到目标空间里面区。


和函数strcpy不同的是,目标空间和源空间必须都有 '\0' 才是函数strcat结束的标志。



自定义函数模拟实现库函数strcmp的功能: 

我们上面所说的,库函数strcat的结束标志也是 '\0' ,那么函数的内部是如何实现的?我们可以自己定义一个函数实现相同的功能(特别是当题目中不允许用库函数strcat追加内容的时候)。


#include
char* my_strcat(char* dest, const char* src)
{
	char* a = dest;
	while (*dest)//该循环是为了是指针dest指向目标空间的'\0'
	{
		dest++;
	}
	while (*src)
	{
		*dest++ = *src++;
	}
	*dest = '\0'; //跳出循环的时候,源空间里的'\0'没有拷贝过去
	return a;
}
int main()
{
	//将arr0、arr00、arr000所指向的空间作为目标空间,可变空间,必须带有'\0'
	char arr0[20] = "ppppp";
	char arr00[20] = "uuuuu";
	char arr000[20] = "vvvvv";
	char* p = "abcdef";//第一种
	char arr1[] = "hijklm";//第二种
	char arr2[] = { 'o','p','q','r','s','t','\0' };//第三种
	//将p所指向的空间作为源空间
	char* ret1 = my_strcat(arr0, p);
	printf("将p所指向的空间作为源空间时:%s\n", ret1);
	//将arr1所指向的空间作为源空间
	char* ret2 = my_strcat(arr00, arr1);
	printf("将arr1所指向的空间作为源空间时:%s\n", ret2);
	//将arr2所指向的空间作为源空间
	char* ret3 = my_strcat(arr000, arr2);
	printf("将arr2所指向的空间作为源空间时:%s\n", ret3);
	return 0;
}

 结果和用库函数strcat拷贝的一样,最重要的是追加的时候要将源空间里的第一个字符strncnp,并且把自身的 '\0' 追加到目标空间里面区。



3、 字符串比较函数 3.1 看函数strcmp

  库函数strcmp是比较两个字符串的大小的。


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

那么两个字符串strncat是是什么了?

比如 “abc” 和 “abdc”

是对应的字符的ASCII码值进行大小比较的,如果对应字符的ASCII码值相等,就依次比较下一个,'\0' 也要比较,直到比较出不相等的对应字符的ASCII码值为止。


但是如果两个字符串一样,比较到 '\0' 为止,'\0' 也要比较,就不再比较了,所以 '\0' 在函数strcmp里就没有前面的函数那么重要,它在strcmp函数里,只是为了防止两个字符串相等,必须要用 '\0' 来结束这个函数,因为一般来说,如果要比较两个字符串,那么肯定是会不一样的。



代码1:

#include
#include
int main()
{
	char* p = "abc";
	char* p1 = "abcd";
	int ret = strcmp(p, p1);
	if (ret == 0)
		printf("p=p1");
	else if (ret > 0)
		printf("p>p1");
	else
		printf("p

 两个字符串前三个字符a、b、c相等,第一个字符串的第四个字符 '\0' 小于第二个字符串的第四个字符 'd' ,所以代码结果是 p



 strncmp

函数的内部是如何实现的?我们可以自己定义一个函数实现相同的功能(特别是当题目中不允许用库函数strcmp比较大小的时候)。


#include
int my_strcmp(const char* str1, const char* str2)
{
	while (*str1 == *str2)
	{
		if (*str1 == 0)//防止两个字符串一样,用'\0'结束函数
		{
			return 0;
		}
		str1++;
		str2++;
	}
	if (*str1 > *str2)
	{
		return 1;
	}
	else
	{
		return -1;
	}
}
int main()
{
	char arr[] = "abcdef";
	char* p = "abcdhg";
	int ret = my_strcmp(arr, p);
	if (ret > 0)//通过返回值判断
	{
		printf("arr>p");
	}
	else if (ret < 0)
	{
		printf("arr

 

 需要注意的地方就是不要忘记如果两个字符串一样,需要用 '\0' 来结束函数。



上面所说的库函数是长度不受限制的字符串函数,那么长度受限制的库函数、和[+++]是如何实现的了?可以看这一篇文章:https://blog.csdn.net/m0_68136339/article/details/123906018 

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 166, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
如何让处理C语言的字符和字符串:函数_C_内存溢出

如何让处理C语言的字符和字符串:函数

如何让处理C语言的字符和字符串:函数,第1张

C语言中对字符和字符串的处理很频繁,但是C语言本身的类型中是没有字符串类型,字符串通常放在 常量字符串 中或者 字符数组 中。


常量字符串,顾名思义,就是这个字符串当成一个常量,我们知道常量是不可以被修改的,所以常量字符串适用于那些对它不做修改的字符串函数。




目录


一、求字符串长度

1、库函数strlen


二、字符串函数

1、字符串拷贝函数

1.1  库函数strcpy

2、字符串追加函数

2.1 库函数strcat

3、 字符串比较函数

3.1 看函数strcmp



一、求字符串长度 1、库函数strlen

 库函数strlen是用来求字符串长度的函数,从函数的声明中可以知道,函数的形式参数的一个字符型指针,说明用来接收一个字符型变量的地址,而函数的返回值是无符号类型的整型。


运用这个函数的时候,要注意以下几点(后面会有相应的代码对每一点说明):

第一点:参数指向的字符串必须要以 '\0' 结束,我们知道,字符串的结束标志是 '\0',本身就已经自带了 '\0' ,但是如果求得是一个字符数组的长度了?那么定义这个字符数组的时候,它的内容也必须加上 '\0' 。


第二点:库函数strlen返回的是在字符串(或字符数组)中 '\0' 前面出现的字符个数(不包含 '\0')。


因为strlen函数的结束标志就是 '\0' ,当这个函数内部运行到看见 '\0' 的时候,它就会返回 '\0' 前面的所有字符个数。


第三点:注意函数的返回值是size_t,是无符号整型(易错)。



代码1:

#include
#include//strlen函数的头文件
int main()
{
	char* p = "abcdef";
	char arr[] = { 'h','i','j','k','l','\0' };
	int lenth1 = strlen(p);
	int lenth2 = strlen(arr);
	printf("字符串的长度:%d\n", lenth1);
	printf("字符数组的长度:%d\n", lenth2);
	return 0;
}

 以上代码对应的是上面的

一、二点。


可以看出,字符串自带了 '\0' ,所以结果是6;而定义字符数组的时候,内容的最后放上了 '\0' ,所以打印的结果是5。


而不管是字符串还是字符数组,strlen函数的返回值都是 '\0' 前面的字符个数,并没有加上 '\0' ,这也对应着 '\0' 是函数strlen的结束标志。



代码2:

#include
#include
int main()
{
	char* p = "abcdef";
	if (strlen(p) > -1)
	{
		printf(">\n");
	}
	else
	{
		printf("<\n");
	}
	return 0;
}

 我相信,可能有很多同学会以为打印的是<。


代码对应上面第三点,函数strlen的返回值是一个无符号整型,所以 -1 与其返回值比较的时候,也必须先要转换成无符号整型,如下图所示。



自定义函数模拟实现库函数strlen的功能: 

我们上面所说的,库函数strlen的结束标志是 '\0' ,那么函数的内部是如何实现的?我们可以自己定义一个函数实现相同的功能(特别是当题目中不允许用库函数strlen求长度的时候)。


#include
#include
size_t my_strlen(const char* p)
{
	int count = 0;
	assert(p);
	while (*p) //当循环到指针指向'\0'时,它的ASCII为0,就会跳出循环
	{
		count++;
		p++;
	}
	return count;
}
int main()
{
	char* p = "abcdef";
	char arr[] = { 'h','i','j','k','l','\0' };
	printf("字符串长度:%d\n", my_strlen(p));
	printf("字符数组长度:%d\n", my_strlen(arr));
	return 0;
}

 顺便说一下库函数assert,它的头文件是assert.h,它的功能是当传递过来的指针是空指针的时候,就会报错,这样可以保证指针的时效性,当一个函数接收的是指针的时候,其内部最好用用函数assert。


自定义代码很好的诠释了 ‘\0’ 的重要性,所以用库函数strlen的时候,一定要注意 '\0'。




二、字符串函数 1、字符串拷贝函数 1.1  库函数strcpy

 库函数strcpy是将一个字符串(或字符数组)的内容(这里我们叫源空间)拷贝到另外一个字符串(或字符数组)里面去(这里我们叫目标空间)。


从函数的申明里面可以看到,是将指针source所指向的源空间里面的内容拷贝到指针destination所指向的目标空间里面去;这里函数的返回类型是字符型指针,返回的是目标空间的地址。


使用库函数strcpy要注意的几点:

第一点:源空间里面的内容必须以 '\0' 结束,即如果是字符串,它自带 '\0' ;如果是字符数组,那么自己在定义字符数组的时候,数组的内容必须要有 '\0' ,而目标空间有没有 '\0' 都剋ui可以说 '\0' 也是函数strcpy的结束标志

第二点:拷贝的时候会将源空间里的 '\0' 拷贝到目标空间里面区。


第三点:目标空间足够大,以确保能存放源空间的内容;目标空间必须可变。


所以目标空间只能是字符数组,因为字符数组的内容才可以更改,而不能用指针:例如char* p = “abc”,因为这是常量字符串,里面的内容是不能够被修改的。



代码1:

#include
#include
int main()
{
	//将arr所指向的空间作为目标空间,可变空间
	char arr[20] = { 0 };
	char* p = "abcdef";//第一种
	char arr1[] = "hijklm";//第二种
	char arr2[] = { 'o','p','q','r','s','t','\0' };//第三种
	//将p所指向的空间作为源空间
	char* ret1 = strcpy(arr, p);
    printf("将p所指向的空间作为源空间时:%s\n", ret1);
	//将arr1所指向的空间作为源空间
	char* ret2 = strcpy(arr, arr1);
	printf("将arr1所指向的空间作为源空间时:%s\n", ret2); 
	//将arr2所指向的空间作为源空间
	char* ret3 = strcpy(arr, arr2);
	printf("将arr2所指向的空间作为源空间时:%s\n", ret3);
	return 0;
}

 对应上面的第一点和第三点:可以看到,不管源空间时第一种,第二种还是第三种,源空间的末尾都必须带有 '\0' ,而目标空间里,'\0' 可有可无,且目标空间必须足够大,且目标空间必须可变,才能完全拷贝过去。


对应上面的第二点:并且拷贝的时候源空间里的 '\0' 也拷贝了过去,也必须拷贝过去,因为库函数strcpy内部也是通过 '\0' 结束的,即 '\0' 也是函数strcpy结束的标志,这一点类似函数strlen。



自定义函数模拟实现库函数strcpy的功能: 

我们上面所说的,库函数strcpy的结束标志也是 '\0' ,那么函数的内部是如何实现的?我们可以自己定义一个函数实现相同的功能(特别是当题目中不允许用库函数strcpy拷贝内容的时候)。


#include
char* my_strcpy(char* dest, const char* src)
{
	char* a = dest;
	while (*src)//循环到指针指向'\0'时,跳出循环
	{
		*dest++ = *src++;
	}
	*dest = '\0';//跳出循环的时候,'\0'没有拷贝过去
	return a;
}
int main()
{
		//将arr所指向的空间作为目标空间,可变空间
	char arr[20] = { 0 };
	char* p = "abcdef";//第一种
	char arr1[] = "hijklm";//第二种
	char arr2[] = { 'o','p','q','r','s','t','\0' };//第三种
	//将p所指向的空间作为源空间
	char* ret1 = my_strcpy(arr, p);
    printf("将p所指向的空间作为源空间时:%s\n", ret1);
	//将arr1所指向的空间作为源空间
	char* ret2 = my_strcpy(arr, arr1);
	printf("将arr1所指向的空间作为源空间时:%s\n", ret2); 
	//将arr2所指向的空间作为源空间
	char* ret3 = my_strcpy(arr, arr2);
	printf("将arr2所指向的空间作为源空间时:%s\n", ret3);
	return 0;
}

 结果和用库函数strcpy拷贝的一样,最重要的是要将源空间里的 '\0' 拷贝过去。



2、字符串追加函数 2.1 库函数strcat

 库函数strcat是将一个字符串(或字符数组)的内容(源空间)追加到另外一个字符串(或字符数组)里面去(目标空间)。


从函数的申明里面可以看到,是将指针source所指向的源空间里面的内容追加到指针destination所指向的目标空间里面去;这里函数的返回类型是字符型指针,返回的是目标空间的地址。


使用库函数strcat要注意的几点:

第一点:源空间和目标空间里面的内容必须以 '\0' 结束,即如果是字符串,它自带 '\0' ;如果是字符数组,那么自己在定义字符数组的时候,数组的内容必须要有 '\0' ,目标空间和源空间必须要有 '\0' 也是函数strcat的追加的原理和结束标志。


第二点:追加的时候会将源空间里的第一个字符会覆盖掉目标空间的 '第三点' ,并且把自身的 '\

0' 追加到目标空间里面区。


第一点和第三点::目标空间足够大,以确保能存放源空间的内容;目标空间必须可变。


所以目标空间只能是字符数组,因为字符数组的内容才可以更改,而不能用指针:例如char* p = “abc”,因为这是常量字符串,里面的内容是不能够被修改的。



代码1:

#include
#include
int main()
{
	//将arr0、arr00、arr000所指向的空间作为目标空间,可变空间,必须带有'\0'
	char arr0[20] = "ppppp";
	char arr00[20] = "uuuuu";
	char arr000[20] = "vvvvv";
	char* p = "abcdef";//第一种
	char arr1[] = "hijklm";//第二种
	char arr2[] = { 'o','p','q','r','s','t','\0' };//第三种
	//将p所指向的空间作为源空间
	char* ret1 = strcat(arr0, p);
    printf("将p所指向的空间作为源空间时:%s\n", ret1);
	//将arr1所指向的空间作为源空间
	char* ret2 = strcat(arr00, arr1);
	printf("将arr1所指向的空间作为源空间时:%s\n", ret2); 
	//将arr2所指向的空间作为源空间
	char* ret3 = strcat(arr000, arr2);
	printf("将arr2所指向的空间作为源空间时:%s\n", ret3);
	return 0;
}

 对应上面的第二点:可以看到,源空间和目标空间的末尾都必须带有 '\0' ,且目标空间必须足够大,且目标空间必须可变,才能完全追加过去。


对应上面的覆盖掉目标空间的 '自定义函数模拟实现库函数strcat的功能:' 追加的时候会将源空间里的第一个字符会覆盖掉目标空间的 '比较的原理' ,并且把自身的 '\0' 追加到目标空间里面区。


和函数strcpy不同的是,目标空间和源空间必须都有 '\0' 才是函数strcat结束的标志。



自定义函数模拟实现库函数strcmp的功能: 

我们上面所说的,库函数strcat的结束标志也是 '\0' ,那么函数的内部是如何实现的?我们可以自己定义一个函数实现相同的功能(特别是当题目中不允许用库函数strcat追加内容的时候)。


#include
char* my_strcat(char* dest, const char* src)
{
	char* a = dest;
	while (*dest)//该循环是为了是指针dest指向目标空间的'\0'
	{
		dest++;
	}
	while (*src)
	{
		*dest++ = *src++;
	}
	*dest = '\0'; //跳出循环的时候,源空间里的'\0'没有拷贝过去
	return a;
}
int main()
{
	//将arr0、arr00、arr000所指向的空间作为目标空间,可变空间,必须带有'\0'
	char arr0[20] = "ppppp";
	char arr00[20] = "uuuuu";
	char arr000[20] = "vvvvv";
	char* p = "abcdef";//第一种
	char arr1[] = "hijklm";//第二种
	char arr2[] = { 'o','p','q','r','s','t','\0' };//第三种
	//将p所指向的空间作为源空间
	char* ret1 = my_strcat(arr0, p);
	printf("将p所指向的空间作为源空间时:%s\n", ret1);
	//将arr1所指向的空间作为源空间
	char* ret2 = my_strcat(arr00, arr1);
	printf("将arr1所指向的空间作为源空间时:%s\n", ret2);
	//将arr2所指向的空间作为源空间
	char* ret3 = my_strcat(arr000, arr2);
	printf("将arr2所指向的空间作为源空间时:%s\n", ret3);
	return 0;
}

 结果和用库函数strcat拷贝的一样,最重要的是追加的时候要将源空间里的第一个字符strncnp,并且把自身的 '\0' 追加到目标空间里面区。



3、 字符串比较函数 3.1 看函数strcmp

  库函数strcmp是比较两个字符串的大小的。


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

那么两个字符串strncat是是什么了?

比如 “abc” 和 “abdc”

是对应的字符的ASCII码值进行大小比较的,如果对应字符的ASCII码值相等,就依次比较下一个,'\0' 也要比较,直到比较出不相等的对应字符的ASCII码值为止。


但是如果两个字符串一样,比较到 '\0' 为止,'\0' 也要比较,就不再比较了,所以 '\0' 在函数strcmp里就没有前面的函数那么重要,它在strcmp函数里,只是为了防止两个字符串相等,必须要用 '\0' 来结束这个函数,因为一般来说,如果要比较两个字符串,那么肯定是会不一样的。



代码1:

#include
#include
int main()
{
	char* p = "abc";
	char* p1 = "abcd";
	int ret = strcmp(p, p1);
	if (ret == 0)
		printf("p=p1");
	else if (ret > 0)
		printf("p>p1");
	else
		printf("p

 两个字符串前三个字符a、b、c相等,第一个字符串的第四个字符 '\0' 小于第二个字符串的第四个字符 'd' ,所以代码结果是 p



 strncmp

函数的内部是如何实现的?我们可以自己定义一个函数实现相同的功能(特别是当题目中不允许用库函数strcmp比较大小的时候)。


#include
int my_strcmp(const char* str1, const char* str2)
{
	while (*str1 == *str2)
	{
		if (*str1 == 0)//防止两个字符串一样,用'\0'结束函数
		{
			return 0;
		}
		str1++;
		str2++;
	}
	if (*str1 > *str2)
	{
		return 1;
	}
	else
	{
		return -1;
	}
}
int main()
{
	char arr[] = "abcdef";
	char* p = "abcdhg";
	int ret = my_strcmp(arr, p);
	if (ret > 0)//通过返回值判断
	{
		printf("arr>p");
	}
	else if (ret < 0)
	{
		printf("arr

 

 需要注意的地方就是不要忘记如果两个字符串一样,需要用 '\0' 来结束函数。



上面所说的库函数是长度不受限制的字符串函数,那么长度受限制的库函数、和是如何实现的了?可以看这一篇文章:https://blog.csdn.net/m0_68136339/article/details/123906018 

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/562755.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-02
下一篇 2022-04-02

发表评论

登录后才能评论

评论列表(0条)