【C语言】strlen函数的讲解和模拟实现

简介: strlen函数我们应该不陌生,它可以帮助我们求字符串的长度(不包括’\0’),但里面还有一些细节需要我们注意。

strlen函数的讲解


strlen函数我们应该不陌生,它可以帮助我们求字符串的长度(不包括’\0’),但里面还有一些细节需要我们注意。看一下下面这张图:

2.png

strlen函数的头文件是<string.h>.如果要使用strlen这个函数,别忘记引头文件。

字符串是以 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数。以下是用strlen函数时可能会遇到的几种问题,先看代码:

#include<stdio.h>

#include<string.h>

int main()

{

char arr1[] = "qwer";

char arr2[] = { 'q','w','e','r' };

char arr3[] = { 'q','w','e','r','\0'};

char arr4[10]= { 'q','w','e','r' };

printf("arr1:%d\n", strlen(arr1));

printf("arr2:%d\n", strlen(arr2));

printf("arr2:%d\n", strlen(arr3));

printf("arr2:%d\n", strlen(arr4));

return 0;

}

码输出的结果是什么?大家可以先试着算一下。然后再看运行结果。

3.png

运行结果如图所示,arr1初始化的时候存放的是字符串,字符串的是以’\0’ 为结束标志的,所以arr1的大小为4。这个应该问题不大。

重点说一下下面这几个。

arr2:我在初始化arr2的时候,是对arr2是以字符进行初始化的,但是我没有设置arr的大小,所以编译器是不知道arr2的大小的,后面存放的是什么东西也是不知道的,但是strlen它是找’\0’的,并返回’\0’之前字符的个数。所以

在strlen找到’\0’之前,前面有36个字符。

arr3:arr3与arr2不同的是,但是我在最后输入了’\0’进行初始化,所以arr3很简单的就找到了’\0’,并返回4。

arr4:arr4与arr2不同的是:我这次设置了arr4的大小,然后我用字符对arr4进行了初始化,虽然是用字符进行的部分初始化,但是编译器会帮我把没初始化的地方默认初始化为0,‘\0’的ASCII码值就是0,C语言字符在内存的形式就是ASCII码值,所以后面没初始化的地方存放的都是’\0’。

我们再来看一个东西,由上面的图,我们还可以知道strlen的返回值是size_t,这是一个无符号数。如果不清楚这个地方,我们也可能会在使用strlen的时候出现一些问题。看一下下面的代码:

#include<stdio.h>

#include<string.h>

int main()

{

if (strlen("abc") - strlen("qwer") < 0)

{

 printf("1");

}

else

{

 printf("0");

}

return 0;

}

对于上面的代码的运行结果是什么?

按常理来说,前面的字符串大小为3,后面的为4,比4小应该会打印1。我们来看运行结果:

4.png

它的运行结果是0,难道前面的字符串大小比后面的大吗,其实不是。关键在于它的返回值是一个无符号数。无符号数只有正数,没有负数。3-4=-1,但是此时的-1并不是有符号数,而是一个无符号数,那么-1此时就是一个很大的正数。所以此时才会输出0

如果要解决这个问题,有以下两种解决方案:

方法1:不相减,进行比较:

#include<stdio.h>

#include<string.h>

int main()

{

if (strlen("abc") < strlen("qwer"))

{

 printf("1");

}

else

{

 printf("0");

}

return 0;

}

方法2:强制类型转换

#include<stdio.h>

#include<string.h>

int main()

{

if ((int)strlen("abc") -(int)strlen("qwer") < 0)

{

 printf("1");

}

else

{

 printf("0");

}

return 0;

}

说一下方法1,无符号数只有正数,没有负数,直接计算大小(正数)就可以直接比较了。方法2是强制转换为int类型的数据,整型是有符号数,有符号数就可以进行相减,结果为-1,就是-1。两种结果输出结果都是1.


strlen函数的模拟实现


讲完了strlen函要注意的问题,下面讲一下strlen函数的模拟实现。总共有三种方法:计数器方式,递归的方式和指针-指针的方式。


计数器方式


实现的思想:设置一个计数的变量,让一个字符指针遍历字符数组的每一个元素,如果指针指向的元素不是’\0’,计算器就自增,直到指针指向的元素是’\0’,就停止遍历,并返回计数器。

因为是模拟实现,我们就只求一致,返回值就设置为size_t。

实现代码如下:

#include<stdio.h>

#include<string.h>

#include<assert.h>

size_t my_strlen(const char* p)

{

int count = 0;

assert(p != NULL);//如果等于空指针就会报错

while((*p) != '\0')

{

 count++;

 p++;

}

return count;

}

int main()

{

char arr[] = "CSDN";

int ret = my_strlen(arr);

printf("%d", ret);

return 0;

}


递归的方式


代码实现的思想:这种方式是不用创建临时变量的一种方法, 只使用指针进行遍历,如果指针指向的不是’\0’,那么就返回1和指针指向后一个数据的结果。

size_t my_strlen(const char* p)

{

if ((*p) == '\0')

{

 return 0;

}

else

{

 return 1 + my_strlen(p+1);

}

}

int main()

{

char arr[] = "CSDN";

int ret = my_strlen(arr);

printf("%d", ret);

return 0;

}


指针减指针的方式


代码实现的思想:

元素名是首元素的地址,我们就在定义一个指针,指向这个数组,让这个指针进行遍历,指向的不是’\0’就让指针进行自增。最后让遍历完数组的指针减去数组名(也就是首元素的地址)。

注意:当两个指着指向同一块空间时,指针减指针的绝对值就是两个指针之间的元素个数,而不是 个数*数据类型所占的空间。

size_t my_strlen(const char* p)

{

char* s = p;

while((*s) != '\0')

{

 s++;

}

return s - p;

}

int main()

{

char arr[] = "CSDN";

int ret = my_strlen(arr);

printf("%d", ret);

return 0;

}

相关文章
|
1月前
|
存储 C语言
`scanf`是C语言中用于按格式读取标准输入的函数
`scanf`是C语言中用于按格式读取标准输入的函数,通过格式字符串解析输入并存入指定变量。需注意输入格式严格匹配,并建议检查返回值以确保读取成功,提升程序健壮性。
704 0
|
3月前
|
安全 C语言
C语言中的字符、字符串及内存操作函数详细讲解
通过这些函数的正确使用,可以有效管理字符串和内存操作,它们是C语言编程中不可或缺的工具。
255 15
|
9月前
|
存储 算法 C语言
【C语言程序设计——函数】素数判定(头歌实践教学平台习题)【合集】
本内容介绍了编写一个判断素数的子函数的任务,涵盖循环控制与跳转语句、算术运算符(%)、以及素数的概念。任务要求在主函数中输入整数并输出是否为素数的信息。相关知识包括 `for` 和 `while` 循环、`break` 和 `continue` 语句、取余运算符 `%` 的使用及素数定义、分布规律和应用场景。编程要求根据提示补充代码,测试说明提供了输入输出示例,最后给出通关代码和测试结果。 任务核心:编写判断素数的子函数并在主函数中调用,涉及循环结构和条件判断。
414 23
|
8月前
|
人工智能 Java 程序员
一文彻底搞清楚C语言的函数
本文介绍C语言函数:函数是程序模块化的工具,由函数头和函数体组成,涵盖定义、调用、参数传递及声明等内容。值传递确保实参不受影响,函数声明增强代码可读性。君志所向,一往无前!
226 1
一文彻底搞清楚C语言的函数
|
9月前
|
算法 C语言
【C语言程序设计——函数】利用函数求解最大公约数和最小公倍数(头歌实践教学平台习题)【合集】
本文档介绍了如何编写两个子函数,分别求任意两个整数的最大公约数和最小公倍数。内容涵盖循环控制与跳转语句的使用、最大公约数的求法(包括辗转相除法和更相减损术),以及基于最大公约数求最小公倍数的方法。通过示例代码和测试说明,帮助读者理解和实现相关算法。最终提供了完整的通关代码及测试结果,确保编程任务的成功完成。
325 15
【C语言程序设计——函数】利用函数求解最大公约数和最小公倍数(头歌实践教学平台习题)【合集】
|
9月前
|
C语言
【C语言程序设计——函数】亲密数判定(头歌实践教学平台习题)【合集】
本文介绍了通过编程实现打印3000以内的全部亲密数的任务。主要内容包括: 1. **任务描述**:实现函数打印3000以内的全部亲密数。 2. **相关知识**: - 循环控制和跳转语句(for、while循环,break、continue语句)的使用。 - 亲密数的概念及历史背景。 - 判断亲密数的方法:计算数A的因子和存于B,再计算B的因子和存于sum,最后比较sum与A是否相等。 3. **编程要求**:根据提示在指定区域内补充代码。 4. **测试说明**:平台对代码进行测试,预期输出如220和284是一组亲密数。 5. **通关代码**:提供了完整的C语言代码实现
168 24
|
9月前
|
存储 C语言
【C语言程序设计——函数】递归求斐波那契数列的前n项(头歌实践教学平台习题)【合集】
本关任务是编写递归函数求斐波那契数列的前n项。主要内容包括: 1. **递归的概念**:递归是一种函数直接或间接调用自身的编程技巧,通过“俄罗斯套娃”的方式解决问题。 2. **边界条件的确定**:边界条件是递归停止的条件,确保递归不会无限进行。例如,计算阶乘时,当n为0或1时返回1。 3. **循环控制与跳转语句**:介绍`for`、`while`循环及`break`、`continue`语句的使用方法。 编程要求是在右侧编辑器Begin--End之间补充代码,测试输入分别为3和5,预期输出为斐波那契数列的前几项。通关代码已给出,需确保正确实现递归逻辑并处理好边界条件,以避免栈溢出或结果
395 16
|
9月前
|
存储 编译器 C语言
【C语言程序设计——函数】分数数列求和2(头歌实践教学平台习题)【合集】
函数首部:按照 C 语言语法,函数的定义首部表明这是一个自定义函数,函数名为fun,它接收一个整型参数n,用于指定要求阶乘的那个数,并且函数的返回值类型为float(在实际中如果阶乘结果数值较大,用float可能会有精度损失,也可以考虑使用double等更合适的数据类型,这里以float为例)。例如:// 函数体代码将放在这里函数体内部变量定义:在函数体中,首先需要定义一些变量来辅助完成阶乘的计算。比如需要定义一个变量(通常为float或double类型,这里假设用float。
219 3
|
9月前
|
存储 算法 安全
【C语言程序设计——函数】分数数列求和1(头歌实践教学平台习题)【合集】
if 语句是最基础的形式,当条件为真时执行其内部的语句块;switch 语句则适用于针对一个表达式的多个固定值进行判断,根据表达式的值与各个 case 后的常量值匹配情况,执行相应 case 分支下的语句,直到遇到 break 语句跳出 switch 结构,若没有匹配值则执行 default 分支(可选)。例如,在判断一个数是否大于 10 的场景中,条件表达式为 “num> 10”,这里的 “num” 是程序中的变量,通过比较其值与 10 的大小关系来确定条件的真假。常量的值必须是唯一的,且在同一个。
184 2
|
9月前
|
存储 编译器 C语言
【C语言程序设计——函数】回文数判定(头歌实践教学平台习题)【合集】
算术运算于 C 语言仿若精密 “齿轮组”,驱动着数值处理流程。编写函数求区间[100,500]中所有的回文数,要求每行打印10个数。根据提示在右侧编辑器Begin--End之间的区域内补充必要的代码。如果操作数是浮点数,在 C 语言中是不允许直接进行。的结果是 -1,因为 -7 除以 3 商为 -2,余数为 -1;注意:每一个数据输出格式为 printf("%4d", i);的结果是 1,因为 7 除以 -3 商为 -2,余数为 1。取余运算要求两个操作数必须是整数类型,包括。开始你的任务吧,祝你成功!
158 1

热门文章

最新文章