C语言-字符串函数+内存函数

目录

1. 字符串函数

1.1 strlen

1.2 strcpy 

1.3 strcat 

1.4 strcmp  

1.5 strncpy

1.6 strncat

1.7 strncmp 

1.8 strstr 

1.9 strtok  

1.10 strerror 

1.11 字符分类函数

2. 内存函数

2.1 memcpy 

2.2  memmove

2.3 memcmp

2.4 memset


1. 字符串函数

1.1 strlen

✨ 函数定义

size_t strlen ( const char * str );

✨ 函数作用 :计算一个字符串的长度

✨ 函数使用

int main()
{
	char s[] = "qwerty"

	size_t len = strlen(s);  //但其实这里的类型应该是size_t(无符号)

	printf("%zu", len);      // 结果是6

	return 0;
}

✨ 注意事项

  • 字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )
  • 参数指向的字符串必须要以 '\0' 结束
  • 函数的返回值为size_t,是无符号的

✨ strlen模拟实现

//1.计数器
int my_print(const char* str)
{
	assert(str);

	int cnt = 0;  //定义一个计数器
	while (*str)
	{
		str++;
		cnt++;
	}

	return cnt;
}
//2.递归
int my_print(const char* str)
{
	assert(str);
	

	if (!(*str))        //当*str为0时,返回0
	{
		return 0;
	}

	return 1 + my_print(str + 1);
}
//3.指针-指针
int my_print(const char* str)
{
	assert(str);

	const char* start = str;   //保存字符串的起始地址
	while (*str)
	{
		str++;                //字符串结束标志 \0 的地址
	}

	return (int)(str - start);

}

1.2 strcpy 

✨ 函数定义

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

✨ 函数作用 :将一个字符串从源(source)拷贝到目的(destination)

✨ 函数使用

int main()
{
	char dest[] = "teststring";
	char src[] = "aaaa";

	printf("%s", strcpy(dest, src));        //strcpy的返回值是目标空间的起始地址
	//结果是aaaa,后面的字符哪去了?原因是,strcpy拷贝时,将aaaa后面的\0一起拷过去了并覆盖一个字符,整个s里面是 aaaa\0tring\0

	return 0;
}

✨ 注意事项

  • 源字符串必须以 '\0' 结束
  • 会将源字符串中的 '\0' 拷贝到目标空间
  • 目标空间必须足够大,以确保能存放源字符串
  • 目标空间必须可变 

✨ strcpy模拟实现 

char* my_strcpy(char* dest, const char* src)
{
	assert(dest && src);

	char* start = dest;                 //保存字符串的起始地址

	while (*dest++ = *src++)            //逐个拷贝字符串,当拷贝到\0时,将\0拷贝过去后,表达式结果为0(假),出循环
	{
		;
	}

	return start;
}

1.3 strcat 

✨ 函数定义

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

✨ 函数作用 :将一个源字符串拼接到目的字符串后面

✨ 函数使用

int main()
{
	char dest[20] = "teststring";
	char src[] = "aaaa";

	printf("%s", strcat(dest, src));    //strcat的返回值是目标空间的起始地址
	//把src字符串(包括最后的\0)接到dest字符串后面,结果是teststringaaaa\0,这说明会把dest里原有的的\0用第一个a替换

	return 0;
}

✨ 注意事项

  • 源字符串必须以 '\0' 结束
  • 目标空间必须有足够的大,能容纳下源字符串的内容
  • 目标空间必须可修改 

✨ strcat模拟实现 

char* my_strcat(char* dest, const char* src)
{
	assert(dest && src);

	char* start = dest;               //保存字符串的起始地址

	while (*dest)                     //找到目的字符串中的\0,dest指向\0
	{
		dest++;
	}

	while (*dest++ = *src++)            //类似strcpy,一一拷贝
	{
		;
	}

	return start;
}

1.4 strcmp  

✨ 函数定义

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

✨ 函数作用 :比较两个字符串的大小

✨ 函数使用

int main()
{
	char src[] = "teststring";
	char cmp[] = "testq";

	printf("%d\n", strcmp(src, cmp));    //strcmp逐一比较src和cmp的每个字符,如果src>cmp,则返回正值 =返回0 <返回负值,这里是s>q,返回1
	return 0;
}

✨ strcmp模拟实现 

int my_strcmp(const char* src, const char* cmp)
{
	assert(src && cmp);

	while (*src == *cmp)                //逐一判断对应字符是否相等
	{
		if (*src == '\0')             //当找到 \0 = \0 ,说明比较完成且两字符串相等
		{
			return 0;
		}
		src++;
		cmp++;
	}

	int ret = (*s > *c) ? 1 : -1;   //走到这里说明找到了第一对不相等的字符,进行比较
	return ret;
}

1.5 strncpy

✨ 函数定义

char * strncpy ( char * destination, const char * source, size_t num );

✨ 函数作用 :将一个源字符串的n个字符拷贝到目的字符串

✨ 函数使用

int main()
{
	char dest[20] = "teststring";
	char src[] = "aaaaaa";

	printf("%s\n", strncat(dest, src, 7)); //如果给的n超过了(比如这里s有6个字符能拷过去,写了拷7个),也只会拷6个
	return 0;
}

✨ strncpy模拟实现  

char* my_strcpy(char* dest, const char* src, size_t n)
{

	assert(dest && src);

	char* start = dest;                 //保存字符串的起始地址

	while (n && (*dest++ = *src++))    //逐个拷贝字符串,当拷贝到\0或n为零时,将\0拷贝过去后,表达式结果为0(假),出循环
	{
		n--;
	}

	return start;

}

1.6 strncat

✨ 函数定义

char * strncat ( char * destination, const char * source, size_t num );

✨ 函数作用 :将一个源字符串的n个字符拼接到目的字符串后面 

✨ 函数使用

int main()
{
	char dest[20] = "teststring";
	char src[] = "aaaaa";

	printf("%s\n", strncat(dest, src, 7)); //如果给的n超过了(比如这里s有6个字符能拷过去,写了拷7个),也只会拷6个
	return 0;
}

✨ strncat模拟实现  

char* my_strncat(char* dest, const char* src, size_t n)
{
	assert(dest && src);

	char* start = dest;               //保存字符串的起始地址

	while (*dest)                     //找到目的字符串中的\0,d指向\0
	{
		dest++;
	}

	while (n && (* dest++ = *src++))            //类似strcpy,一一拷贝
	{
		n--;
	}

	*dest = '\0';                             //拷贝完成后在末尾补上\0
	return start;
}

1.7 strncmp 

✨ 函数定义

char * strncat ( char * destination, const char * source, size_t num );

✨ 函数作用 :比较两个字符串的前n个字符的大小 

✨ 函数使用 

int main()
{
	char src[] = "teststring";
	char cmp[] = "teststa";

	printf("%d\n", strncmp(src, cmp, 7));    //比较前n个,有不同,立即返回,比较完无不同,返回0
	return 0;
}

✨ strncmp模拟实现   

int my_strncmp(const char* src, const char* cmp,size_t n)
{
	assert(src && cmp);

	while (n && (*src == *cmp))                //逐一判断对应字符是否相等
	{
		n--;
		if (*src == '\0' || n == 0)          //当找到 \0 = \0或者比较完了 n 对,此时 n = 0 ,说明比较完成
		{
			return 0;
		}
		src++;
		cmp++;
	}

	int ret = (*src > *cmp) ? 1 : -1;          //走到这里说明找到了第一对不相等的字符,进行比较
	return ret;
}

1.8 strstr 

✨ 函数定义

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

✨ 函数作用 :若str2字符串是str1字符串的一个字串,则返回该字串在str1中的位置

✨ 函数使用

int main()
{
	char dest[] = "teststring";
	char src[] = "str";

	printf("%s\n", strstr(dest, src)); //找出dest中src的子串,并把子串的首地址返回
    //这里打印 string
	return 0;
}

✨ strstr模拟实现    

char* my_strstr(const char* dest, const char* src)
{
	assert(dest && src);

	const char* s1 = dest;
	const char* s2 = src;
	const char* cur = dest;

	while (*cur)
	{
		s1 = cur;
		s2 = src;

		while (*s1 && *s2 && (*s1 == *s2))
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return (char*)cur;
		}
		cur++;
	}

	return NULL;
}

1.9 strtok  

✨ 函数定义

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

✨ 函数作用 :用sep里的字符来分隔str的字符串

✨ 函数使用

int main()
{
	char str[] = "teststring";        
	const char* sep = "ei";    //在str中先遇到e停下来,打印t,再引用strtok时,将源置为NULL,就在sep中找第二个             
	char buf[50] = { 0 };
	strcpy(buf, str);
	char* stra = NULL;
	for (stra = strtok(buf, sep);stra != NULL;stra = strtok(NULL, sep))
	{
		printf("%s\n",stra);
	}

    //打印结果:t
               ststr
               ng

	return 0;
}

 ✨ 注意事项

  • sep参数是个字符串,定义了用作分隔符的字符集合
  • 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记
  • strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改)
  • strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置
  • strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记
  • 如果字符串中不存在更多的标记,则返回 NULL 指针

1.10 strerror 

✨ 函数定义

char * strerror ( int errnum )

✨ 函数作用 :返回错误码,所对应的错误信息

✨ 函数使用

int main()
{
	//printf("%s\n", strerror(0));    // No error
	//	
	//	
	//printf("%s\n", strerror(1));   // Operation not permitted
	//printf("%s\n", strerror(2));   // No such file or directory
	//printf("%s\n", strerror(3));   // No such process

	int* p = (int*)malloc(INT_MAX);  //分配空间太大导致失败,返回一个空指针
	if (p == NULL)
	{
		printf("%s\n", strerror(errno));  //errno是一个全局变量,一旦发生错误,就会将错误码放到errno中

	}

	return 0;
}

1.11 字符分类函数

函数符合条件为真
iscntrl 任何控制字符
isspace空白字符:空格‘ ’,换页‘\f’,换行'\n',回车‘\r’,制表符'\t'或者垂直制表符'\v'
isdigit十进制数字 0~9
isxdigit 十六进制数字,包括所有十进制数字,小写字母a~f,大写字母A~F
islower小写字母a~z
isupper大写字母A~Z
isalpha字母a~z或A~Z
isalnum字母或者数字,a~z,A~Z,0~9
ispunct标点符号,任何不属于数字或者字母的图形字符(可打印)
isgraph任何图形字符
isprint任何可打印字符,包括图形字符和空白字符

 ✨ 函数使用

int main()
{
	printf("%d\n", isdigit('5'));  //isdigit,如果参数是数字字符,返回真
	printf("%d\n", isdigit('z'));  //否则,返回假(0)

	printf("%d\n", islower('a'));  //islower,如果参数是小写字符,返回真
	printf("%d\n", islower('A'));  //否则,返回假

	printf("%d\n", isalnum('A'));  //isalnum,如果参数是字母或者数字,返回真
	printf("%d\n", isalnum(',')); //否则,返回假

	return 0;
}


字符转换
int main()
{
	printf("%c\n", tolower('A')); //大写转小写
	printf("%c\n", toupper('a')); //小写转大写
	return 0;
}

2. 内存函数

2.1 memcpy 

✨ 函数定义 

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

✨ 函数作用 :将source指针指向的内存地址中的num个字节数据拷贝到destination指针指向的内存中

✨ 注意事项

  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置
  • 这个函数在遇到 '\0' 的时候并不会停下来
  • 如果source和destination有任何的重叠,复制的结果都是未定义的

✨ 函数使用

int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[5] = { 0 };

	memcpy(arr2, arr1, 20); //20是将20个字节(5个整形)从源拷贝到目的
	
	for (int i = 0;i < 5;i++)
	{
		printf("%d ", arr2[i]);
	}

    //1 2 3 4 5

	return 0;
}

✨ memcpy模拟实现     

void* my_memcpy(void* dest, const void* src, size_t cnt)
{
	assert(dest && src);

	void* start = dest;    //先保存初始地址

	while (cnt--)
	{
		*(char*)dest = *(char*)src;  //一个字节一个字节的取,将void* 类型的指针先强转为char*的指针再解引用
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}

	return start;
}

2.2 memmove

✨ 函数定义 

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

✨ 函数作用 :实现重叠的内存拷贝

✨ 注意事项

  • 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的
  • 如果源空间和目标空间出现重叠,就得使用memmove函数处理

✨ 函数使用

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr + 2, arr, 20);     //1,2,1,2,3,4,5,8,9,10
	my_memmove(arr + 2, arr, 20);
	for (int i = 0;i < 10;i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

✨ memmove模拟实现    

void* my_memmove(void* dest, const void* src, size_t cnt)
{
	assert(dest && src);

	void* start = dest; //先保存初始地址

	//判断从前往后拷贝还是从后往前拷贝,就是看源和目的的交界处,是位于源的前方还是后方
	//1 2 3 4 5 6 7 8 9 假设源是3 4 5 6 ,目的是1 2 3 4 ,相交是3 4,是源的前方
	//1 2 3 4      目的
	//    3 4 5 6  源    (为确保源在拷贝过程中数据不变,先把相交处拷贝了,所以从前往后拷贝)
	//
	//    3 4 5 6  源
	//          6 7 8 9 目的 (为确保源在拷贝过程中数据不变,先把相交处拷贝了,所以从后往前拷贝)
	if (dest < src)
	{
		//从前向后拷贝
		void* start = dest;

		while (cnt--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		//从后向前拷贝
		while (cnt--)
		{
			*((char*)dest + cnt) = *((char*)src + cnt);
		}
	}

	return start;
}

2.3 memcmp

✨ 函数定义 

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

✨ 函数作用 :内存中数据的比较

✨ 注意事项 

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

✨ 函数使用 

int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 1,2,3,4,0x11223305 };
	//int ret = memcmp(arr1, arr2, 17); //前16和17个字节都一样,返回0
	int ret = memcmp(arr1, arr2, 18);  //第18个字节arr1是00, arr2是33, arr1小, 返回-1
	printf("%d\n", ret);
	return 0;
}

2.4 memset

✨ 函数定义

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

✨ 函数作用 :将dest指针指向内存的count个字节数据设为字符c()

✨ 函数使用 

int main()
{
	int arr[] = { 1,2,3,4,5 };
	memset(arr, 0, 19);
	for (int i = 0;i < 5;i++)
	{
		printf("%d\n", arr[i]);
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值