C语言字符串常见的几个函数(上)~

147 阅读8分钟

前言部分:

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

  笔者之前就有过关于字符串函数的讲解部分!有意者,请参考笔者代码!!笔者在之前就写过100++的文章,一直在学习C语言的路上!坚持着书写代码!!有不懂得问题请及时私聊

1.函数介绍:

求字符串长度(strlen函数)

对于strlen 统计的是在字符串中 ‘\0'之前出现的字符个数(不包含'\0')

请参考代码:

#include <stdio.h>
#include <string.h>
int main()
{
	// a b c d e f \0 一共7个元素
	char arr[] = "abcdef";
	printf("%d\n", strlen(arr));
	return 0;
}

代码的运行结果为:

34fb156ce67a42da9de78fb952dcc450.png 上述代码中:char arr[] = "abcdef"; 一共有 a b c d e f \0 一共7个元素 ,但是当\0的位置在:

a b c \0 d e f 的时候,代码的运行结果为:

c355167adfae4ab3a25944f5b72c363e.png 对于:char arr[]={'a','b','c'};此时:代码的运行结果就是随机值了!! 代码的运行结果为:

daecd27c705e4e869e79334a4e4d5e15.png 在上述的代码中,多次使用到了strlen函数!!下面笔者对strlen这个函数进行讲解:

726947815ef045df935959469e17678d.png size_t strlen (const char* str)

const char* str :指针—》地址—》首字符的地址!

对于strlen函数,本文主要有一下讲解!!

1.参数指向的字符串必须以'\0'结束!

2.注意函数的返回值为:size_t类型(无符号的整型)易错部分,紧急必坑!!

3.学会strlen函数的模拟实现!!

证明:返回值为size_t (无符号整型)!

请看笔者代码:

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

这个代码中:strlen("abc") - strlen("abcdef") 对于该字符串的大小,想必读者肉眼都能看清楚!3-6=-3!!!直接的想法便是:'<' ;那么便是大错特错了!!怎可能会是按照这样的想法来呢??

请看打印的结果:

82d06076099049e881254bfd59633766.png 若有不相信的读者,可以自行尝试!!

原因在于:打印的结果为:size_t类型(无符号的整型)!!对于无符号数-无符号数=无符号数!想必读者没有多大的疑问吧!!

因此,可以总结的来说!字符串的长度不可能为负数!所以,strlen函数为无符号数!

下面笔者来对strlen函数进行模拟实现!!请各位老铁仔细欣赏!!走神将会错过好戏!

#include <stdio.h>
#include <string.h>
#include <assert.h>
 
size_t my_strlen(const char* str)
{
	assert(str);
	const char* start = str;//记录起始地址
	const char* end = str;  //记录结束地址
	while (*end != '\0')
	{
		end++;
	}
	return end - start;  //结束时候的位置减去起始位置等于中间的字符个数
}
 
int main()
{
	char arr[] = "abcdef";
	int len = my_strlen(arr);
	printf("%d\n", len);
	return 0;
}

在上述代码中:笔者对strlen统计字符串长度的函数来进行模拟实现了一下!!

1.对于在main函数里面:这里的int len = my_strlen(arr); arr是指:起始地址,即'a'的地址!!

2.对于size_t my_strlen(const char* str) 是按照strlen 函数的类型来进行定义的!!偷偷告诉各位老铁一句:不能将size_t换为void ,若是进行替换将会出现错误!!对于:const char* str 是用指针来进行接收,前面加了const 是指对arr不能进行修改,这样显得更加完美!const 修饰的是:* str !

3.对于 assert(str); 断言,保证str 不为空指针!!因为,在后面有部分代码是对:str进行*(解引用操作)所以要确保str不为空指针!

  1. 在while循环里面,end为什么能进行++操作呢??原因在于:const修饰的是:*end, 并没有限制end !!但是,对于const * char end 这样进行书写,将会限制end进行++操作!!

5.end - start :两个指针相减,得到的是两个指针之间的元素个数!!即字符串的长度!

代码的运行结果为:

8fcb6458964c4b29959a2b1d35dcdd29.png 对于字符串统计:strlen函数的讲解,及其模拟实现 部分就到此结束,各位老铁,若有不同的想法,请及时联系笔者!!将会竭尽全力帮助各位老铁度过难关!

字符串拷贝函数:strcpy的详解及模拟实现!!!

对于字符串拷贝函数,之前在学习字符串时候,就已经学习过,但那只是片面的学习了一下,并没有经过系统的分析!只是大概的学习了一下!在关键的地方有时候还不知道该怎么用!所以出现学习跟没有学一样的效率!因此,笔者最近再次系统的学习了一下:所以才打算发一篇文章: 字符串拷贝函数:strcpy的详解及模拟实现 !来与大家共勉!

首先对于字符串拷贝函数:strcpy 我们需要知道:

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

上述的代码是指:在strcpy函数使用的时候,需要注意的格式问题!!对于destination 是指 :目的地 , source 是指:源头!!该片段的总体意思是:将源头拷贝到目的地!

对于本文的学习之前,需要知道一下知识储备!:

1.源字符串必须以'\0'结尾!

2.strcpy字符串拷贝函数:会将源字符串中的'\0'拷贝到目标空间!

3.目标空间必须足够大,以确保能存放源字符串!!

4.目标空间必须可变!(不能被const修饰)!

5.要学会strcpy字符串拷贝函数的模拟实现!

对于strcpy字符串拷贝函数!我们先做一下知识储备:

#include <stdio.h>
#include <string.h>
int main()
{
	char arr[10] = { 0 };
	const char* p = "abcdef";
	strcpy(arr, p);
	printf("%s\n", arr);
	return 0;
}

这段代码就是对于:strcpy字符串拷贝函数的简单实现!!想必大家也都能看懂!

代码的运行结果为:

eba61c4e72a2432d8afc0dba468ca3b9.png 但是对于:const char* p = "abcdef";中的'\0'要不要拷贝到arr[10]里面去??心存疑惑!!

因此,我们可以将arr[10]数组进行初始化为:arr[10]="xxxxxxxxx"!!这样操作,加上调试,更能直观的看出来!

因此更改后的代码为:虽然结果也是一样的,但是在调试的过程中,可以显现出来:strcpy字符串拷贝函数:会将源字符串中的'\0'拷贝到目标空间!

399fda11631d4d58a648601b2b510d95.png 代码调试前的结果为:

3b39ab82a6064b42865adcc8b6332024.png 请注意:arr[10]数组里面值的变化!

代码调试完成以后的结果为:

abb2b19034a04078b34a9bc56bea2d71.png 综上代码的调试结果所述:strcpy字符串拷贝函数:会将源字符串中的'\0'拷贝到目标空间!

但是,在使用strcpy拷贝字符串中,必须要知道'\0‘所在的位置:因此,对于字符数组的拷贝就会出现问题!!请看下列代码::

#include <stdio.h>
#include <string.h>
int main()
{
	char arr[10] = "xxxxxxxxx";
	char arr2[] = { 'a','b','c' };
	strcpy(arr, arr2);
	printf("%s\n", arr);
	return 0;
}

对于上述的代码中:由于在字符数组中:'\0'的位置并不知道,导致越界访问,所以会出现错误!!

请看代码的运行结果:

b42d5a684c0a43de84628fa6d4c44c48.png 对于上述的出现错误的代码,笔者就不再进行调试了!请各位老铁可以理解一下!!

但是,当使用字符数组进行strcpy进行拷贝时候,手动放置一个'\0'!也可以进行正常的拷贝使用!!

660cdb92b4164a65945fa25309f217e1.png 在这个代码中,拷贝的时候,也会将'\0'进行拷贝!!对于此问题,我们依然 可以通过调试来进行分析!

在调试完成之前的:

2194c749b0214600a0ff5bd4351cfcd3.png 调试完成之后:

ae941e369a284ffd829fafb20e474e19.png 在上述的调试结果中:我们可以清晰地看出来!在字符数组中,手动放置的'\0'也会进行拷贝!!

结合以往经验,笔者苦心专研了两个错误写法,下面请笔者……看一下代码:

1.目标空间必须足够大,以确保能存放源字符串!!否则,将会出现崩溃现象!!错误演示,请忽模仿

#include <stdio.h>
#include <string.h>
int main()
{
	char arr[3] = { 0 };
	char arr2[] = "abcdef";
	strcpy(arr, arr2);
	printf("%s\n", arr);
	return 0;
}

代码的运行结果为:

590375e9603940a2ac0a1ea615584318.png 程序崩溃!!

2.目标空间必须可变!(不能被const修饰,常量字符串不可被修改)!错误演示,请忽模仿

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

该段代码的运行结果为:

156d3bca8f0f445e99ac6ae4c84a85ee.png 直接出现错误,不能被更改!!

上面两个是笔者之前专研的!!对于其他的bug若是读者有不同的想法,请私聊笔者哟!

下面笔者进行对strcpy字符串拷贝函数的模拟实现!!!也到了该拿出压箱底的实力了!!

请看笔者代码:

#include <stdio.h>
#include <string.h>
#include <assert.h>
 
char* my_strcpy(char* dest, const char* src)
{
	assert(dest);
	assert(src);
	char* ret = dest;
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}
 
int main()
{
	char arr1[20] = "abc";
	char arr2[] = "hello wang";
	my_strcpy(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

对于上述代码中:

  1. assert(dest); assert(src); 断言,因为在后面的文章中,对dest 与src都进行了解引用操作,所以在使用之前要确保不是空指针!!

2.在while循环里面,为什么是:*dest++ = *src++ 而不是:*dest=*src; dest++; src++;呢 ???其实主要的原因还是在于拷贝'\0'的问题,当while 循环里面判断出来是'\0'则会进行跳出,不会拷贝'\0';所以进行了上述while循环里面的操作!!实现先赋值在判断!!

3.为什么在最后的返回值是:return ret;????而不是 return dest;??? 原因在于:随着dest++与src++的赋值,dest早已不再指向起始位置!!

代码的运行结果为:

650e7702315b4a849d66bc815139a7f3.png 上述就是笔者对该strcpy字符串拷贝函数的模拟实现的解析,若有不懂得老铁,请私聊笔者哟!!