字符串函数和内存函数(一)

大家好哇!好久不见!这里是菜菜!

首先祝大家暑假快乐喔!


今天我们来了解了解字符串函数和内存函数。

目录

(一)字符串函数

(1)strlen

(2)strcpy

(3)strcat

(4)strcmp

(5)strstr

(6)strtok

(7)strerror

(二)内存函数

(1)memset

(2)memcpy

(3)memcpy

(4)memcmp


(一)字符串函数

        在C语言里有许多的字符串函数,我们今天就先说说那些常用的字符串函数:

        下面我们就将上面的字符串函数展开讲讲:

(1)strlen

size_t strlen ( const char * str );

        strlen函数是返回从字符串中'\0'前面至某个内存位置出现的字符个数。(注:统计的字符个数不包括'\0')

        我们观察strlen函数,它返回值类型为size_t(unsigned int),接收的参数为是个地址。

例:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abc\0def";
	printf("%zu\n", strlen(arr1));
	printf("%zu\n", strlen(arr2));

	printf("%zd\n", sizeof(arr1));
	printf("%zd\n", sizeof(arr2));
	return 0;
}

运行结果:

         在这里我们能看到数组arr1的是 6,但是字符串arr1的sizeof操作是 7,这说明我们在完成对字符串初始化后,系统会自动帮我们追加一个 '\0'(下面不再进行赘述)。同时,对比字符串arr1,字符串arr2在中间有一个字符'\0',相应的在调用函数strlen时,函数遇到'\0'字符时就会直接返回统计的字符个数,故返回为 3,但在sizeof操作里,因为字符串中间多了一个字符'\0',故大小为 8。

(2)strcpy

char* strcpy(char * destination, const char * source);

        strcpy函数遇见源字符串的 '\0'就会停止,但是strcpy函数会把 '\0'拷贝至目标字符串,因此目标空间必须足够大,确保能放源字符串。

        这里我们能看到 strcpy 函数的返回的是 char* 类型,即返回一个地址。接收的参数为两个地址,其中第二个地址用 const 修饰,表示指针 source 可以改变指向,但是其指向的值不可改变。

例:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[] = "abcde";
	char arr2[] = "xxxxxxxxxxxxx";
	printf("%s\n", arr2);
	strcpy(arr2, arr1);                    //将字符数组arr1拷贝至字符数组arr2中
	printf("%s\n", arr2);
	return 0;
}

 运行结果:

        在这里我们的字符串 arr2 的大小明显大于arr1,并且我们在调用 strcpy函数 以后输出,并没有将后续的字符 'x' 打印输出,说明在调用函数时,把 字符串arr1 中的字符 '\0'也拷贝至 字符串arr2中,我们也可以打开调试查看 字符串arr2 中的字符。

(3)strcat

char * strcat ( char * destination, const char * source );

         strcat函数将源字符串追加至目标,遇见源字符串的 '\0'就会停止,目标空间需要足够大,确保能够放下源字符串。

        这里我们能看到的 strcat函数 返回类型为 char* ,即返回一个地址。接收的参数为两个地址,其中第二个地址用 const 修饰,表示指针 source 可以改变指向,但是其指向的值不可改变。

例:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[] = "defg";
	char arr2[10] = "abc";
	strcat(arr2, arr1);            //将字符数组arr1追加至字符数组arr2中
	printf("%s\n", arr2);    
	return 0;
}

运行结果:

        这里是把 字符串arr1 追加至 字符串arr2 中,再对 字符串arr2进行输出,即得到结果。在追加字符串时,仍然会把 字符'\0'追加至目标字符串中。

        我们需要注意的是,strcat函数并不能追加自身字符串,因为 strcat函数 是遇见源字符串的 '\0' 才会停止,但是在自身追加过程中,目标字符串的'\0' 会被覆盖掉,又因为是自身追加,故源字符串的 '\0' 也被修改掉,从而使得strcat函数无法停止。

(4)strcmp

int strcmp ( const char * str1, const char * str2 );

        strcmp是比较字符串的函数:      

        比较原则:第一个字符串大于第二个字符串,则返回大于0的数字;第一个字符串等于第二个字符串,则返回0;第一个字符串小于第二个字符串,则返回小于0的数字。一般 strcmp函数 是用来判断两字符串是否相等。

        strcmp返回值是一个整形,而接受的参数是两个char* 的地址,因为不需要对传入的字符串进行修改,故使用const修饰。

例:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[] = "abcd";
	char arr2[] = "abca";
	char arr3[] = "abcd";
	printf("%d\n", strcmp(arr1, arr2));        //字符数组arr1与arr2进行比较
	printf("%d\n", strcmp(arr1, arr3));        //字符数组arr1与arr3进行比较
	return 0;
}

运行结果:

        首先,将 字符串arr1 与 字符串arr2 进行比较:将两个字符串的每个字符进行,因为字符在计算机内存储的是其ASCLL码,故直接比较其ASCLL值即可得出结果,当比较字符 'd' 与 'a' 时,因为字符 'd' 的ASCLL值大于 字符 'a',故strcmp函数返回值为1;当比较 字符串arr1 和 字符串arr3 时,因为两字符串内所有字符相等,故返回值为0。(strcmp函数并不能比较字符串的长度,而是比较其内字符的ASCLL码值)

(5)strstr

char * strstr ( const char *str1, const char * str2);

         strstr是查找字符串内是否存在目标字串,如果存在,则返回目标字串的地址,否则返回NULL。

        strstr函数返回的是 char* 类型的地址,接收的是两个 char* 类型的地址。

例:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
	char arr[] = "abcdefgh";
	printf("%s\n", strstr(arr, "bcde"));
	printf("%s\n", strstr(arr, "bcad"));
	return 0;
}

运行结果:

        因为strstr返回的是 char* 类型的地址,故在第一个输出中,因为 字符串arr 内存在 子串"bcde" ,故 strstr函数 返回的是其子串的地址,即 'b' 的地址;在第二个输出中,因为 字符串arr 不存在子串 "bcad" 故返回为NULL。

(6)strtok

char * strtok ( char * str, const char * sep );

        strtok函数 是用来截断字符串的,其中 str 是用来接收字符串的地址的, sep 是用来接收字符串截断标志(集合)的,strtok返回的是char* 类型的地址。strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(strtok函数会改变被接收字符串),strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串 中的位置。strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标 记。 如果字符串中不存在更多的标记,则返回 NULL 指针。

例:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
	char arr[] = "https://blog.csdn.net";
	printf("%s\n", strtok(arr, "://."));
	printf("%s\n", strtok(NULL, "://."));
	printf("%s\n", strtok(NULL, "://."));
	printf("%s\n", strtok(NULL, "://."));
	return 0;
}

运行结果:

        首先第一个输出里,调用strtok函数,其在传入的字符串中寻找截断字符标志,找到后将其修改为 '\0',再返回截断字符标志前的字符串的地址,在第二个输出里,调用strtok函数,因为接收的地址为NULL,所以strtok函数会从上一次修改的位置继续向后寻找,直至找到下一个阶段字符标志。如果相邻两截断字符标志内无字符串,则会跳过继续向后寻找。下面我们打开调试观察截断后字符串arr内的内容。

(7)strerror

char * strerror ( int errnum );

 返回错误码,所对应的错误信息。

例:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <errno.h>        //头文件
int main()
{
	FILE* fp = fopen("test.txt", "r");        //文件指针打开文件
	printf("%s\n", strerror(errno));          //输出错误码对应的错误信息
	return 0;
}

运行结果:

        打开文件失败,打印其错误信息。

(二)内存函数

(1)memset

void *memset( void *dest, int c, size_t count );

        memset函数是将地址dest起的第count个字节全部赋值为c。

        memset函数接收的是一个void * 地址,其是为了能够接收多种地址类型(下面不再进行赘述),另外接收的参数为size_t类型的值,用来记录赋值的字节数,而另一个参数c则是将赋值的内容。

例:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
	char arr[10] = { 0 };
	memset(arr, 'M', 9);        //自地址arr起的9个字节全部赋值为字符'M'
	printf("%s\n", arr);
	return 0;
}

运行结果:

         memset函数将自arr地址起的9个字节全部赋值为'M'。从结果上看,数组arr内确实赋值为'M',只选9个字节是因为需要留一个字符'\0'用于输出。

(2)memcpy

void * memcpy ( void * destination, const void * source, size_t num );

        memcpy是用于内存拷贝,作用范围比 strcpy函数 更广一些。

        memcpy接收的参数是两个 void* 类型的地址,另一个参数为size_t类型,即需要拷贝字节数。函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。 这个函数在遇到 '\0' 的时候并不会停下来。

例:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
struct Peo                              //定义一个结构体
{
	char name[10];
	int age;
}A, B;
int main()
{    //初始化
	char arr[] = "caicai";
	A.age = 20;

	memcpy(&A.name, arr, sizeof(arr));	//将字符串arr拷贝至结构体A的name里
	memcpy(&B, &A, sizeof(A));			//将结构体B内存拷贝至结构体A中
	printf("%s\n%d", B.name, B.age);

	return 0;
}

运行结果:

        首先定义一个结构体,再初始化一个字符数组,将字符数组内存拷贝至结构体A的name中,将A中的age赋值为20,再将结构体A内存拷贝至结构体B中。

(3)memmove

void * memmove ( void * destination, const void * source, size_t num );

        函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。

        memmove接收的参数为两个void* 类型的地址,另一个参数为size_t类型,即需要拷贝字节数。如果源空间和目标空间出现重叠,就得使用memmove函数处理。

例:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr + 2, arr, 20);					//从数组arr中,自地址arr开始拷贝20个字节(5个整形元素)至arr+2出
	for (int i = 0; i < 10; i++)				//循环输出数组元素
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

运行结果:

         因为 memmove(arr+2,arr,20),故从arr开始的20个字节拷贝至从arr+2的地址处的20个字节,20个字节即对应5个整形大小,故数组内元素为: 1 2 1 2 3 4 5 8 9 10.

(4)memcmp

int memcmp ( const void * ptr1,  const void * ptr2,  size_t num );

        比较从ptr1和ptr2指针开始的num个字节。

        memcmp接收两个地址,再从两个地址开始比较num个字节。该函数返回值意义与上述strcmp类型,这里不再进行赘述。

例:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
	int arr1[10] = { 1,2,3,4,5 };
	int arr2[10] = { 1,2,3,3,4 };
	printf("%d\n", memcmp(arr1, arr2, 12));		//比较数组arr1和数组arr2的前12个字节,即前3个元素
	printf("%d\n", memcmp(arr1, arr2, 16));		//比较数组arr1和数组arr2的前16个字节,即前4个元素
	return 0;
}

运行结果:

        第一个输出中,比较数组arr1和数组arr2的前12个字节,即前3个元素,因为两个数组前3个元素相等,故返回打印0;第二个输出中,比较数组arr1和数组arr2的前16个字节,即前4个元素,因为两个数组前4个元素不相等,数组arr2的第4个元素小于数组arr1的第4个元素,故返回打印1;

         


        今天就分享到这里了!

        您的点赞与关注是对菜菜最大的支持!

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值