模拟实现C库函数(2)

news2024/9/17 9:21:42

"烦恼无影踪,丢宇宙~"

上一篇的模拟实现了好几个库函数,strlen\strcpy\memcpy\memmove,那么这一篇又会增加几个常用C库函数的模拟实现 memset\itoa\atoi。

一、memset

memset - fill memory with a constant byte
#include <string.h>
void *memset(void *s, int c, size_t n);
The memset() function fills the first n bytes of the memory area pointed to by s with the constant byte c.
memset()函数 将会用常量字节c ,填充s指向的内存区域空间,填充前n个字节。
RETURN VALUE
The memset() function returns a pointer to the memory area s.
返回s的起始地址

下面的代码演示取自这里:Here

    //我们相对下面的数组手动进行初始化
    int arr1[10];
    int arr2[10];
    memset(arr1, 0, sizeof(int) * 10);
    memset(arr2, 1, sizeof(int) * 10);

为什么它们的区别这么大?16843009从哪里来的??那么一定跟它底层的实现是有关系的。

void* my_memset(void* s, int c, size_t n)
{
    const unsigned uc = c;
    unsigned char* su = s;
    for (;n > 0;++su,--n)
    {
        *su = uc;
    }
    return s;
}

第3行先将int类型的c强转为unsigend char。第4行将void* 也强转为unsigned char*。

变量类型的本质只是标志从某一内存地址开始读取的位数,强制转换就是改变读取位数的大小。改变的不是变量本身,而是从内存中读取每个bit的方式。

我们再回到第一个问题上来。将int类型强转为unsigend char,也就意味着本身要读取bit位数为32,但是截断了24位。只用读取8位。

当整数1被传入进来时 00000000 00000000 00000000 00000001(32)

实质上读取的时候是00000001(8)。(unsigend char)s每次将原内存的比特位置位: 00000001。循环4(int)n次后,也就是构一个int的大小:00000001 00000001 00000001 00000001

当memset结束后,以int大小取去32位比特时:

不过,对于设置0而言,memset(arr1, 0, sizeof(int) * 10)可以完美做到。比较32个位都是0。

二、atoi

atoi, atol, atoll, atoq - convert a string to an integer
#include <stdlib.h>
int atoi(const char *nptr);
The atoi() function converts the initial portion of the string pointed to by nptr to int.
atoi() 将nptr指向的初始字串部分,转换为int整数返回。

RETURN VALUE
The converted value.

一个字符串的输入可能有哪些情况?

"123"

" 123"

"'\0'123"

"-123"

"''\0'123"

"12'\0'3"

"abc"

"123abc"

  1. 空格直接跳过

  1. 遇到"-"时,会转换成整数的负号

  1. 当遇到'\0'时,函数就会终止

  1. 正常0时转为整数0

  1. 如果不是数字,那么也会直接终止

int my_atoi(char* nptr)
{
    assert(nptr);
    //符号
    int flag = 1;
    //返回的ret
    long long ret = 0;
    
    //1.跳过空格
    while (isspace(*nptr))
    {
        nptr++;
    }

    //2.是否遇到'\0'?
    if (*nptr == '\0') return 0;

    //3.正负号
    if (*nptr == '-')
    {
        flag = -1;
        nptr++;
    }
    else if (*nptr == '+')

    {
        nptr++;
    }
    else {
        //do nothing
    }

    //处理字串
    while (isdigit(*nptr))
    {
        //字符是否合法
        ret = ret * 10 + flag * (*nptr - '0');
        //但 不能超过 限制
        if ((ret > INT_MAX) || (ret < INT_MIN))
        {
            return 0;
        }
        nptr++;
    }

    //正常截止的情况是 走到nptr的最后 或者 "123abc" || "123'\0'324"
    if (*nptr == '\0')
    {
        return (int)ret;
    }
    else
    {
        //遇到了非法字符
        //返回已经转成字符的
        return (int)ret;
    }
    return 0;
}

测试;

三、itoa

Convert integer to string (non-standard function)
char * itoa ( int value, char * str, int base );

Converts an integer value to a null-terminated string using the specified base and stores the result in the array given by str parameter.
itoa()让一个整形值以base的基准,转化为以nullptr结尾的字串,并把结果存储在被str管理的数组中
注:base实质为进制数
Numerical base used to represent the value as a string, between 2 and 36, where 10 means decimal base, 16 hexadecimal, 8 octal, and 2 binary.(2<= base <=36)
#include <stdio.h>
#include <stdlib.h>

int main ()
{
  int i;
  char buffer [33];
  printf ("Enter a number: ");
  scanf ("%d",&i);
  itoa (i,buffer,10);
  printf ("decimal: %s\n",buffer);
  itoa (i,buffer,16);
  printf ("hexadecimal: %s\n",buffer);
  itoa (i,buffer,2);
  printf ("binary: %s\n",buffer);
  return 0;
}
                                                                       取自"cplusplus.com"例子

char* my_itoa(int value, char* str, int base)
{
    //存放 处理好的字串
    int a[100] = { 0 };
    int sum = value;
    char* cp = str;
    if (base < 2 || base > 36)//增加了对错误的检测
    {
        *cp++ = 0;
        *cp = '\0';
        return str;
    }
    //按正数转换
    if (sum < 0) sum = -sum;

    int i = 0;
    char zm[37] = "0123456789abcdef";
    while (sum > 0)
    {
        //sum%base 如果是 十进制的8 % 10 那么得到的是8
        //如果是 十六进制的8 % 16 8
        //如果是 二进制的 8 % 2  0
        printf("%c\n", zm[sum % base]);
        a[i++] = zm[sum % base];
        sum /= base;
    }

    if (value < 0)
    {
        *cp++ = '-';
    }

    //填充
    for (int j = i - 1; j >= 0; j--)
    {
        *cp++ = a[j]; //从高位到低位转换
    }
    //null结尾
    *cp = '\0';
    return str;
}

测试;

本篇到此也就结束了,感谢你的阅读。

祝你好运,向阳而生~

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

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

相关文章

机器自动翻译古文拼音 - 十大宋词 - 江城子·乙卯正月二十日夜记梦 苏轼

江城子乙卯正月二十日夜记梦 宋苏轼 十年生死两茫茫&#xff0c;不思量&#xff0c;自难忘。 千里孤坟&#xff0c;无处话凄凉。 纵使相逢应不识&#xff0c;尘满面&#xff0c;鬓如霜。 夜来幽梦忽还乡&#xff0c;小轩窗&#xff0c;正梳妆。 相顾无言&#xff0c;惟有泪千…

uniapp使用及踩坑项目记录

环境准备 下载 HBuilderX 使用命令行创建项目&#xff1a; 一些常识准备 响应式单位rpx 当设计稿宽度为750px的时&#xff0c;1rpx1px。 uniapp中vue文件style不用添加scoped 打包成h5端的时候自动添加上去&#xff0c;打包成 微信小程序端 不需要添加 scoped。 图片的…

SpringDataJpa set()方法自动保存失效

问题描述&#xff1a;springdatajpa支持直接操作对象设置属性进行更新数据库记录的方式&#xff0c;正常情况下&#xff0c;get()得到的对象直接进行set后&#xff0c;即使不进行save操作&#xff0c;也将自动更新数据记录&#xff0c;将改动持久化到数据库中&#xff0c;但这里…

20230126使AIO-3568J开发板在原厂Android11下跑起来

20230126使AIO-3568J开发板在原厂Android11下跑起来 2023/1/26 18:22 1、前提 2、修改dts设备树 3、适配板子的dts 4、&#xff08;修改uboot&#xff09;编译系统烧入固件验证 前提 因源码是直接使用原厂的SDK&#xff0c;没有使用firefly配套的SDK源码&#xff0c;所以手上这…

Linux安装mongodb企业版集群(分片集群)

目录 一、mongodb分片集群三种角色 二、安装 1、准备工作 2、安装 configsvr配置 router配置 shard配置 三、测试 四、整合Springboot 一、mongodb分片集群三种角色 router角色&#xff1a; mongodb的路由&#xff0c;提供入口&#xff0c;使得分片集群对外透明&…

【目标检测论文解读复现NO.27】基于改进YOLOv5的螺纹钢表面缺陷检测

前言此前出了目标改进算法专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读最新目标检测算法论文&#xff0c;…

【工程化之路】Node require 正解

require 实现原理 流程概述 步骤1&#xff1a;尝试执行代码require("./1"). 开始调用方法require.步骤2&#xff1a;此时会得到filename&#xff0c;根据filename 会判断缓存中是否已经加载模块&#xff0c;如果加载完毕直接返回&#xff0c;反之继续执行步骤3&…

python图像处理(laplacian算子)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 和之前的prewitt算子、sobel算子不同,laplacian算子更适合检测一些孤立点、短线段的边缘。因此,它对噪声比较敏感,输入的图像一定要做好噪声的处理工作。同时,laplacian算子设计…

Leetcode 03. 无重复字符的最长子串 [C语言]

目录题目思路1代码1结果1思路2代码2结果2该文章只是用于记录考研复试刷题题目 Leetcode 03: 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: s “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”&#xff0c;所…

尚医通-OAuth2-微信登录接口开发(三十一)

目录&#xff1a; &#xff08;1&#xff09;微信登录-OAuth2介绍 &#xff08;2&#xff09;前台用户系统-微信登录-准备工作 &#xff08;3&#xff09;微信登录-生成微信二维码-接口开发 &#xff08;4&#xff09;微信登录-生成验证码-前端整合 &#xff08;5&#xf…

Telerik DevCraft Ultimate R1 2023

Telerik DevCraft Ultimate R1 2023 Kendo UI R1 2023-添加新的Chip和ChipList组件。 KendoReact R1 2023&#xff08;v5.11.0&#xff09;-新的PDFViewer组件允许用户直接在应用程序中查看PDF文档。 Telerik JustLock R1 2023-Visual Studio快速操作菜单现在可以在创建通用…

蓝桥杯重点(C/C++)(随时更新,更新时间:2023.1.29)

点关注不迷路&#xff0c;欢迎推荐给更多人 目录 1 技巧 1.1 取消同步&#xff08;节约时间&#xff0c;甚至能多骗点分&#xff0c;最好每个程序都写上&#xff09; 1.2 万能库&#xff08;可能会耽误编译时间&#xff0c;但是省脑子&#xff09; 1.3 蓝桥杯return 0…

【数据库-通用知识系列-01】数据库规范化设计之范式,让数据库表看起来更专业

我们在设计数据库时考虑的因素包括读取性能&#xff0c;数据一致性&#xff0c;数据冗余度&#xff0c;可扩展性等&#xff0c;好好学习数据库规范化的知识&#xff0c;设计的数据库表看起来才专业。 范式一览 “键”理解&#xff1a; 超键&#xff1a;在关系中能唯一标识元组…

送什么礼物给小学生比较有纪念意义?适合送小学生的小礼物

送给小学生的礼物哪种比较有意义呢&#xff1f;送给学生的礼物&#xff0c;基本上是对学习有所帮助的&#xff0c;但是像送钢笔、练习册这些&#xff0c;有一部分学生是抗拒的&#xff0c;作为大人就是希望对视力、对成长有用的东西&#xff0c;我认为保护视力是现在许多家庭的…

isNotEmpty() 和 isNotBlank() 的区别,字符串判空, StringUtils工具包 StringUtil工具类,isEmpty() 和 isBlank() 的区别

目录1.StringUtils 和 StringUtilStringUtils 的依赖&#xff1a;StringUtils 的用法&#xff1a;StringUtil 工具类2. isNotEmpty() 和 isNotBlank()1.StringUtils 和 StringUtil 注&#xff1a;StringUtils 和 StringUtil 的区别&#xff08;StringUtil为自定义工具类&#…

以表达式作为template参数

目录 一.template参数的分类&#xff1a; 二.非类型参数与默认参数值一起使用 三.应用 一.template参数的分类&#xff1a; ①.某种类型&#xff1a; template<typename T>; ②.表达式(非类型)&#xff1a; template<int length,int position>; 其中length…

Liunx中shell命令行和权限的理解

文章目录前言1.shell外壳的理解2.关于权限理解1.Linux下的用户2.角色划分3.文件和目录的权限3.粘滞位3.总结前言 Linux中的操作都是通过在命令行上敲指令来实现的&#xff0c;本文将简单的介绍Linux中的外壳程序shell以及浅谈一下对Linux中的权限理解。 1.shell外壳的理解 Lin…

微信小程序开发(一)

1. 微信小程序的开发流程 2. 注册小程序 小程序注册页&#xff1a;https://mp.weixin.qq.com/wxopen/waregister?actionstep1 如已注册&#xff0c;直接登录 小程序后台 https://mp.weixin.qq.com/ 即可。 在小程序后台的 【开发管理】→ 【开发设置】下可以查看AppID&…

算法训练营DAY45|322. 零钱兑换、279.完全平方数

两道题思路上有相似之处&#xff0c;都是求得最少的种类方法&#xff0c;也就是说在完全背包里给定容量时&#xff0c;用最少的物品去装满背包。它和用最多的方法去装满背包也有一些相似&#xff0c;也就是说两者实际上是互通的。 322. 零钱兑换 - 力扣&#xff08;LeetCode&a…

HTML零散知识

1、代码规范与思路 参考凹凸实验室代码规范&#xff1a;Aotu.io - 前端代码规范 CSS编写顺序的思路 先确定盒子本身是如何布局 position: absolutefloat: left/rightdisplay: flex 盒子的特性和可见性 display: block/inline-block/inline/nonevisibility/opacity 盒子模型…