【维生素C语言】附录:strlen 函数详解

  

  • 写在前面:本篇将专门为 strlen 函数进行讲解,总结了模拟实现 strlen 函数的三种方法,并对其进行详细的解析。手写库函数是较为常见的面试题,希望通过本篇博客能够加深大家对 strlen 的理解。

0x00 strlen函数介绍

【百度百科】strlen 所作的是一个计数器的工作,它从内存的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的内存区域)开始扫描,直到碰到第一个字符串结束符 \0 为止,然后返回计数器值(长度不包含 \0 )。

size_t strlen(const char* str);    // 求字符串长度

📜 头文件: string.h

📚 说明:字符串以 \0 作为结束标志,strlen 返回的是在字符串中 \0 前面出现的字符个数。因为求的是字符串的长度,也就是字符的个数,所以不包括  \0 字符。(注:sizeof 包括 \0 字符)

📌 注意事项:

  • 参数指向的字符串必须以  \0  结束
  • 函数的返回值为 size_t ,即无符号整数 (unsigned) 的别名。参见宏定义:typedef unsigned int size_t;

❓ 为什么返回无符号呢?

💡 既然是求字符串长度,那么出现负数就没有意义,所以使用 size_t 

💬 使用方法演示:

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

🚩  运行结果: 6

0x01 模拟实现:计数器(需创建临时变量)

💬 模拟实现 strlen 函数:

#include <stdio.h>size_t my_strlen(const char* str) {int count = 0; //创建计数器while (*str != '\0') { //对 str 解引用,如果 *str 不是 \0str++; // 指针向后移动1位(char)count++; // 计数器+1}return count; //返回计数器
}int main() {char arr[] = "abcdef";int len = my_strlen(arr);printf("len = %d\n", len);return 0;
}

💡 解析:加上 const 修饰提高代码的健壮性,用 const char* 接收传入的参数。因为 arr 数组名是首元素地址,所以需要用指针变量接收。创建变量 count 来作为计数器,在循环内进行指针加整数,直到碰到 \0 跳出循环,最后返回计数器 count

⚡ 简化: 

#include <stdio.h>size_t my_strlen(const char* str) {int count = 0;while (*str) {str++;count++;}return count;
}int main() {char arr[] = "abcdef";int len = my_strlen(arr);printf("len = %d\n", len);return 0;
}

0x02 模拟实现:用递归

💬 模拟实现 strlen 函数(禁止创建临时变量):

#include <stdio.h>size_t my_strlen(const char* str) {if (*str != '\0') {return 1 + my_strlen(str + 1);} else {return 0;}
}int main() {char arr[] = "abcdef";int len = my_strlen(arr);printf("len = %d\n", len);return 0;
}

💡 解析:首先进行判断,对 str 进行解引用,如果不是 \0 就返回 1 + my_strlen(str + 1) ,此时 " 1+ " 就起到了计数的作用,随后自己调用自己 my_strlen(str + 1) ,递归下去直到是 \0 为止,碰到后返回 0,随后再一步步倒回去,就可以返回长度了。当然,如果传入的字符串长度为 0,会直接走 else 返回 0。

📌 注意:不要将 my_strlen(str + 1)  写成 my_strlen(str++)  ,在这里使用 后置++ 是非常致命的!

0x03 模拟实现:指针减指针

💬 代码演示:模拟实现 strlen 函数(禁止创建临时变量):

#include <stdio.h>size_t my_strlen(const char* str) {const char* start = str; //字符串的起始位置就是strconst char* end = str;while (*end != '\0') {  //用来找到字符串的末尾处end++;}return end - start; //最后指针减指针,巧妙地得到了字符串的长度
}int main() {char arr[] = "abcdef";int len = my_strlen(arr);printf("len = %d\n", len);return 0;
}

 💡 解析:利用 " 指针减指针得到的是元素之间元素的个数" 这一特性得到字符串的长度。首先创建 start 变量用于记录字符串的起始位置,随后创建 end 变量并找到末尾位置( 不是 \0 就往后推进的方法 )。最后返回 end - start,末尾位置减去起始位置即可得到字符串的长度。

⚡ 其实库函数就用了这种方法,真的是妙不可言!不过将代码进一步地简化了: 

#include <stdio.h>size_t my_strlen(const char* str) {const char* end = str;while (*end++); return end - str - 1;
}int main() {char arr[] = "abcdef";int len = my_strlen(arr);printf("len = %d\n", len);return 0;
}

💡 解析:首先其实大可不必创建 start 变量,因为 str 本身就记录着起始位置。while 括号中这种情况下自然可以省去 \0 ,库函数作者直接将 end++ 的操作直接丢入判断条件中。*end++ 优先级相同,根据结合性(从右向左)。因为 while 循环条件会比循环体多执行一次,放进循环条件内的*end++ 因为这个 "特性" 多执行了一次,所以最后 end - start 要手动 -1。返回 end - start - 1 ,即字符串长度。

📌 注意事项:while 循环条件将会比循环体多执行一次。(摘自第二章)

【维生素C语言】第二章 - 分支和循环

📂 最后贴上 src 文件夹中的 strlen.c ,一起来欣赏欣赏:(和上面的代码原理一样,只是变量名不同)

/***
*strlen.c - contains strlen() routine
*
*       Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
*       strlen returns the length of a null-terminated string,
*       not including the null byte itself.
*
*******************************************************************************/#include <cruntime.h>
#include <string.h>#pragma function(strlen)/***
*strlen - return the length of a null-terminated string
*
*Purpose:
*       Finds the length in bytes of the given string, not including
*       the final null character.
*
*Entry:
*       const char * str - string whose length is to be computed
*
*Exit:
*       length of the string "str", exclusive of the final null byte
*
*Exceptions:
*
*******************************************************************************/size_t __cdecl strlen (const char * str)
{const char *eos = str;while( *eos++ ) ;return( eos - str - 1 );
}


本篇完

📌 [ 笔者 ]   王亦优
📃 [ 更新 ]   2021.10.1
❌ [ 勘误 ]   /* 暂无 */
📜 [ 声明 ]   由于作者水平有限,本文有错误和不准确之处在所难免,本人也很想知道这些错误,恳望读者批评指正!

📜 参考资料 

C++reference[EB/OL]. []. http://www.cplusplus.com/reference/.

Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. .

百度百科[EB/OL]. []. https://baike.baidu.com/.

比特科技. C++[EB/OL]. 2021[2021.8.31]. 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2778654.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Cobalt Strike 的使用及拓展

Cobalt Strike是一款以Metasploit为基础的GUI框架式渗透测试工具&#xff0c;集成了端 口转发、服务扫描、 自动化溢出、多模式端口监听、exe 、PowerShell木马生成 等&#xff0c;主要用于团队作战&#xff0c;能让多个渗透者同时连接到团体服务器上&#xff0c;共享渗透资 源…

Leetcode2560. 打家劫舍 IV

Every day a Leetcode 题目来源&#xff1a;2560. 打家劫舍 IV 解法1&#xff1a;二分答案 动态规划 给定数组 nums&#xff0c;从中选择一个长度至少为 k 的子序列 A&#xff0c;要求 A 中没有任何元素在 nums 中是相邻的。 最小化 max⁡(A)。 看到「最大化最小值」或者…

基于vue+node.js的校园跳蚤市场系统多商家

校园跳蚤市场系统可以在短时间内完成大量的数据处理、帮助用户快速的查找校园跳蚤市场相关信息&#xff0c;实现的效益更加直观。校园跳蚤市场系统中采用nodejs技术和mysql数据库。主要包括管理员、发布者和用户三大部分&#xff0c;主要功能是实现对个人中心、用户管理、发布者…

数据分析基础之《pandas(7)—高级处理2》

四、合并 如果数据由多张表组成&#xff0c;那么有时候需要将不同的内容合并在一起分析 1、先回忆下numpy中如何合并 水平拼接 np.hstack() 竖直拼接 np.vstack() 两个都能实现 np.concatenate((a, b), axis) 2、pd.concat([data1, data2], axis1) 按照行或者列…

【Opencv学习】04-图像加法

文章目录 前言一、图像加法混合1.1 代码1.2 运行结果 二、图像的按位运算-组合相加2.1 代码2.2 运行结果示例&#xff1a;PPT平滑切换运行结果 总结 前言 简单说就是介绍了两张图如何组合在一起。 1、混合&#xff0c;透明度和颜色会发生改变 2、组合&#xff0c;叠加起来。可…

大厂的供应链域数据中台设计

关注我&#xff0c;紧跟本系列专栏文章&#xff0c;咱们下篇再续&#xff01; 作者简介&#xff1a;魔都技术专家兼架构&#xff0c;多家大厂后端一线研发经验&#xff0c;各大技术社区头部专家博主&#xff0c;编程严选网创始人。具有丰富的引领团队经验&#xff0c;深厚业务架…

2/10 BFS初探

其实在我看来解决全排列问题&#xff0c;核心还是顺序&#xff0c;想清楚结束条件&#xff0c;然后输出&#xff0c;以n3为例 #include<iostream> using namespace std; const int N 10; int path[N];//保存序列 int state[N];//数字是否被用过 int n; void dfs(int u) …

FPGA_工程_基于rom的vga显示

一 框图 二 代码修改 module Display #(parameter H_DISP 1280,parameter V_DISP 1024,parameter H_lcd 12d150,parameter V_lcd 12d150,parameter LCD_SIZE 15d10_000 ) ( input wire clk, input wire rst_n, input wire [11:0] lcd_xpos, //lcd horizontal coo…

C++面向对象 Part 2

文章目录 类六个默认存在的成员函数构造函数&#xff1a;析构函数&#xff1a;拷贝构造函数:拷贝构造详解及细节&#xff1a; 赋值运算符重载;取地址及const取地址操作符重载const修饰的含义&#xff1a; 类六个默认存在的成员函数 构造函数 析构函数 拷贝构造函数 赋值运算…

【从Python基础到深度学习】3. Winscp与Ubuntu使用及配置

一、Ubuntu的使用 1.1 开启与关闭 1.2 修改Ubuntu分辨率 选择适合自己电脑大小的分辨率 1.3 Ubuntu终端 1.4 网络测试 终端中输入&#xff1a; ping www.baidu.com ctr C 退出ping命令 1.5 下载软件 连通安装源 sudo apt update 安装 ssh vim sudo apt install ss…

Verilog刷题笔记22

题目&#xff1a; Build a priority encoder for 8-bit inputs. Given an 8-bit vector, the output should report the first (least significant) bit in the vector that is 1. Report zero if the input vector has no bits that are high. For example, the input 8’b100…

使用耳机壳UV树脂制作一个耳机壳需要多长时间?

使用耳机壳UV树脂制作一个耳机壳所需的时间取决于多个因素&#xff0c;包括工艺流程、加工方式、设备和技术水平等。一般来说&#xff0c;制作一个耳机壳需要数小时到数天不等。 以下是影响制作时间的几个主要因素&#xff1a; 获取耳模时间&#xff1a;获取耳模的时间取决于…

爬虫2—用爬虫爬取壁纸(想爬多少张爬多少张)

先看效果图&#xff1a; 我这个是爬了三页的壁纸60张。 上代码了。 import requests import re import os from bs4 import BeautifulSoupcount0 img_path "./壁纸图片/"#指定保存地址 if not os.path.exists(img_path):os.mkdir(img_path) headers{ "User-Ag…

第66讲管理员登录功能实现

项目样式初始化 放assets目录下&#xff1b; border.css charset "utf-8"; .border, .border-top, .border-right, .border-bottom, .border-left, .border-topbottom, .border-rightleft, .border-topleft, .border-rightbottom, .border-topright, .border-botto…

【Dubbo源码二:Dubbo服务导出】

入口 Dubbo服务导出的入口&#xff1a;服务导出是在DubboBootstrapApplicationListener在监听到ApplicationContextEvent的ContextRefreshedEvent事件后&#xff0c;会触发dubboBootstrap.start(), 在这个方法中最后会导出Dubbo服务 DubboBootstrapApplicationListener Dub…

Java异常处理 throw和throws

目录 throwthrows实例制造异常 在Java中&#xff0c;throw和throws关键字都与异常处理有关&#xff0c;但它们的使用方式和目的有所不同。 throw throw关键字&#xff1a; * throw用于在代码中显式地抛出一个异常。你可以使用它来触发一个异常&#xff0c;并指定异常的类型。…

python接口自动化---接口测试报告模板(详解)

简介 接口测试报告是软件测试过程中非常重要的一部分&#xff0c;通过接口测试报告我们可以了解系统在接口层面上的稳定性和可靠性。下面是一个简单的接口测试报告模板&#xff1a; 测试概述 在这个部分中&#xff0c;您需要简要阐述接口测试的目的和范围。测试环境 在这个部…

网络的基本概念和socket编程

网络的基本概念 1.协议1.1 协议的基本概念1.2 常见的协议 2.分层模型2.1网络七层OSI 7层模型&#xff1a;物数网传会表应(口诀)2.2TCP/IP模型2.3数据通信的过程2.4网络的设计模式2.5以太网帧的格式 3.SOCKET编程3.1网络字节序3.2 相关结构体和函数3.3 代码实现 1.协议 1.1 协议…

NAS如何成为生产力?使用绿联DX4600 Pro搭建图床并实现创作自由

NAS如何成为生产力&#xff1f;使用绿联DX4600 Pro搭建图床并实现创作自由 哈喽小伙伴们好&#xff0c;我是Stark-C~ 关注我的小伙伴都知道&#xff0c;我之前有分享过我的创作过程与工具&#xff0c;其中介绍了我个人其实一直都是使用Markdown的编辑器来进行图文创作的。 我…

【数学建模】【2024年】【第40届】【MCM/ICM】【B题 搜寻潜水器】【解题思路】

一、题目 &#xff08;一&#xff09;赛题原文 2024 MCM Problem A: Resource Availability and Sex Ratios Maritime Cruises Mini-Submarines (MCMS), a company based in Greece, builds submersibles capable of carrying humans to the deepest parts of the ocean. A …