C语言模拟实现:atoi函数
在实现atoi之前我们先来了解一下atoi函数的作用是什么:
目录
1.实例演示
2.模拟实现
2.1 判断是否为空指针
2.2判断是否为空字符串
2.3判断正负号
2.4判断非数字字符
2.5判断是否越界
2.6完整代码
1.实例演示
//实例演示
#include <stdio.h>
#include <stdlib.h>
int main()
{printf("%d\n", atoi("0"));printf("%d\n", atoi("1234"));printf("%d\n", atoi("-1234"));printf("%d\n", atoi("+1234"));printf("%d\n", atoi("12a4"));return 0;
}
2.模拟实现
如果单从对atoi函数的解释上来看,就是将字符串转化为整数,如果只是简单的按照将字符串转化为整数的思路来模拟实现atoi函数,也可以,但是远远不够,但是还是给大家来演示一下:
要想将字符数字转化为整数数字,之前提到过:数字1加上字符0就转化为了字符1
(1 + '0' = '1') ,给字符1减去字符0就得到了数字1('1' - '0' = 1),所以在模拟实现atoi的时候就可以使用这样的方法,使用指针来遍历字符串,给第一个字符减字符0得到该数字,然后地址加一转化第二个字符,直到遇到'\0'.
//模拟实现
#include <stdio.h>
int my_atoi(const char* str)
{int ret = 0;while (*str){//将转化后的值赋值给retret = ret * 10 + (*str - '0');//ret = 0 * (10 + '1') - '0'//ret = 1 * (10 + '2') - '0'//ret = 12 * (10 + '3') - '0'//ret = 123 * (10 + '4') - '0'//ret = 1234//转化成功之后地址加1str++;}return ret;
}
int main()
{char str[] = {"1234"};int ret = my_atoi(str);printf("%d\n", ret);return 0;
}
虽然这样实现可以将字符串转化为整数,但是还是存在许许多多的问题:
1. 如果传递的是空指针
2. 如果传递的是空字符串
3. 如果传递的是带'+'、'-'的字符串
4. 如果传递的是非数字字符
5. 转化之后的值越界
所以以上的问题都是在写代码的时候要考虑的,那么接下来我们来一一的解决:
2.1 判断是否为空指针
判断一个指针是否为空指针,用到assert这个宏来断言,但是在使用这个宏时需要包含头文件<assert.h>
#include <assert.h>
int my_atoi(const char* str)
{//1.//判断是否为空指针//assert来断言assert(str);
}
2.2判断是否为空字符串
若为空字符串,那么它的整个字符串都是'\0',所以要通过指针来判断它是否为'\0',如果为'\0',那么就要返回0,但是存在一个问题,如果传给atoi的就是字符0呢?,那也返回的是0,那到底返回的0是合法转化还是非法转化的呢?因此我们需要进行判断。在这里可以使用枚举,将非法和合法都列举出来,然后先将其设置为非法,如果是合法的转化,在后面的设置中将其转化为合法就可以了。
enum State
{VALID, //合法INVALID //非法
};
//先将State设置为非法enum State date = INVALID;
int my_atoi(const char* str)
{//1.//判断是否为空指针//assert来断言assert(str);//2.//判断是否为空字符串if (*str == '\0'){return 0; //这里返回的时候,date还是非法,所以表示非法转化}
}
2.3判断正负号
判断正负这一步需要在转化字符为数字的时候将正负号添加进去,因此我们可以设置一个标记正负号的值,如果为正号就不变,若为负号就变为负数
#include <stdio.h>
#include <assert.h>
enum State
{VALID, //合法INVALID //非法
};
//先将State设置为非法enum State date = INVALID;
int my_atoi(const char* str)
{//1.//判断是否为空指针//assert来断言assert(str);//2.//判断是否为空字符串if (*str == '\0'){return 0; //这里返回的时候,date还是非法,所以表示非法转化}//3.//判断正负int flag = 0;if (*str == '+'){flag = 1;str++;}else if (*str == '-'){flag = -1;str++;}
}
2.4判断非数字字符
在之前的字符分类函数中提到过判断数字字符,其中有一个函数是isdigit,它是用来判断10进制的数字,它在使用的时候需要包含头文件<ctype.h>
//4.//判断是否为非数字字符long long ret = 0; //设置一个值来进行存放转化之后的值//这里使用long long类型的ret是为了在转化的时候防止转换之后的值溢出while (*str){if (isdigit(*str)) //isdigit函数是用来判断是否为10进制的数字{ret = ret * 10 + flag * (*str - '0'); //如果为10进制数字就正常转化//将flag也引入来表示正、负数}else //如果不为10进制的数字就将之前转化的返回{return (int)ret; //因为ret是long long类型,而atoi的返回类型是int所以要强制类型转化}str++;}
2.5判断是否越界
整形的最大值是一个INT_MAX的值,最小值是一个INT_MIN的值,所以我们需要将转化之后的值进行判断,如果转换之后在这个范围内,那表示正常转化,如果超出了这个范围,则表示非法转化,在使用时需要包含头文件<limits.h>
//4.//判断是否为非数字字符long long ret = 0; //设置一个值来进行存放转化之后的值//这里使用long long类型的ret是为了在转化的时候防止转换之后的值溢出while (*str){if (isdigit(*str)) //isdigit函数是用来判断是否为10进制的数字{ret = ret * 10 + flag * (*str - '0'); //如果为10进制数字就正常转化//将flag也引入来表示正、负数//5.//判断是否越界if (ret > INT_MAX || ret < INT_MIN){return (int)ret;}}else //如果不为10进制的数字就将之前转化的返回{return (int)ret; //因为ret是long long类型,而atoi的返回类型是int所以要强制类型转化}str++;}//正常遍历完字符串之后if (*str == '\0'){//当正常转化完之后,将date赋值为合法date = VALID;}return (int)ret;
2.6完整代码
#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include <limits.h>enum State
{VALID, //合法INVALID //非法
};
//先将State设置为非法
enum State date = INVALID;
int my_atoi(const char* str)
{//1.//判断是否为空指针//assert来断言assert(str);//2.//判断是否为空字符串if (*str == '\0'){return 0; //这里返回的时候,date还是非法,所以表示非法转化}//3.//判断正负int flag = 0;if (*str == '+'){flag = 1;str++;}else if (*str == '-'){flag = -1;str++;}//4.//判断是否为非数字字符long long ret = 0; //设置一个值来进行存放转化之后的值//这里使用long long类型的ret是为了在转化的时候防止转换之后的值溢出while (*str){if (isdigit(*str)) //isdigit函数是用来判断是否为10进制的数字{ret = ret * 10 + flag * (*str - '0'); //如果为10进制数字就正常转化//将flag也引入来表示正、负数//5.//判断是否越界if (ret > INT_MAX || ret < INT_MIN){return (int)ret;}}else //如果不为10进制的数字就将之前转化的返回{return (int)ret; //因为ret是long long类型,而atoi的返回类型是int所以要强制类型转化}str++;}//正常遍历完字符串之后if (*str == '\0'){//当正常转化完之后,将date赋值为合法date = VALID;}return (int)ret;}
int main()
{char str[] = { "-123456" };printf("转化前:> %s\n", str);int ret = my_atoi(str);if (date == INVALID){printf("非法转化:> %d\n", ret);}elseprintf("合法转化:> %d\n", ret);return 0;
}
总结:
1. 模拟实现atoi函数时不能只简单的去将数字字符转化为整数,还得考虑其它因素(空指针、空字符串、正负数、是否为数字字符、越界)。
2. 使用各种辅助函数时对应头文件的包含。
3. 熟悉字符分类函数。
4. 字符数字如何转化为整数数字
关于atoi函数的模拟实现就写到这里,如果大家喜欢,请留下你的三连,抱拳感谢了!!
相关文章:

C语言模拟实现:atoi函数
在实现atoi之前我们先来了解一下atoi函数的作用是什么: 目录 1.实例演示 2.模拟实现 2.1 判断是否为空指针 2.2判断是否为空字符串 2.3判断正负号 2.4判断非数字字符 2.5判断是否越界 2.6完整代码 1.实例演示 //实例演示 #include <stdio.h> #include …...

LeetCode.每日一题 2427. 公因子的数目
Halo,这里是Ppeua。平时主要更新C语言,C,数据结构算法......感兴趣就关注我吧!你定不会失望。 🌈个人主页:主页链接 🌈算法专栏:专栏链接 我会一直往里填充内容哒! &…...

蓝牙BQB认证 - HFP profile配置说明
零.声明 本专栏文章我们会以连载的方式持续更新,本专栏计划更新内容如下: 第一篇:蓝牙综合介绍 ,主要介绍蓝牙的一些概念,产生背景,发展轨迹,市面蓝牙介绍,以及蓝牙开发板介绍。 第二篇:Trans…...

【接口测试工具】Eolink Apikit 快速入门教程
Eolink Apikit 下载安装【官方版】:https://www.eolink.com/apikit 发起 API 测试 进入 API 文档详情页,点击上方 测试 标签,进入 API 测试页,系统会根据 API 文档自动生成测试界面并且填充测试数据。 填写请求参数 首先填写好请…...

使用Python和OpenCV实现实时人脸检测并保存截图
在本篇博客中,我们将使用Python和OpenCV库实现一个实时人脸检测的小项目。我们将利用OpenCV中的Haar级联分类器来检测摄像头捕获的图像中的人脸。 项目功能 通过摄像头实时捕获视频流。使用Haar级联分类器检测视频帧中的人脸。在检测到的人脸周围绘制矩形框。实时…...

[linux kernel]slub内存管理分析(7) MEMCG的影响与绕过
文章目录背景前情回顾描述方法约定MEMCG总览省流总结简介slub 相关 memcg机制kernel 5.9 版本之前结构体初始化具体实现kernel 5.9-5.14kernel 5.14 之后突破slab限制方法cross cache attackpage 堆风水总结背景 前情回顾 关于slab几个结构体的关系和初始化和内存分配和释放的…...

MySQL创建数据库(CREATE DATABASE语句)
在 MySQL 中,可以使用 CREATE DATABASE 语句创建数据库,语法格式如下: CREATE DATABASE [IF NOT EXISTS] <数据库名> [[DEFAULT] CHARACTER SET <字符集名>] [[DEFAULT] COLLATE <校对规则名>]; [ ]中的内容是可选的。语…...

【JavaWeb】4—Tomcat
⭐⭐⭐⭐⭐⭐ Github主页👉https://github.com/A-BigTree 笔记链接👉https://github.com/A-BigTree/Code_Learning ⭐⭐⭐⭐⭐⭐ 如果可以,麻烦各位看官顺手点个star~😊 如果文章对你有所帮助,可以点赞👍…...

宝塔Linux面板部署Python flask项目
目录 👉1、前言 👉2、安装python项目管理器 👉3、上传项目文件及文件夹 👉4、配置项目 👉5、请求测试 学习记录: 👉1、前言 写在前面:前几天我们实现了外网内外登录正方教务系…...

spring中产生bean的几种方式
BeanImportMyImportSelector implements ImportSelectorMyImportBeanDefinitionRegistarimplements ImportBeanDefinitionRegistrarFactoryBean这里着重讲解FactoryBean如何判断当前bean是否是FactoryBeanorg.springframework.beans.factory.support.AbstractBeanFactory#isFac…...

OD-火星文计算(Python)
火星文计算 题目描述 已经火星人使用的运算符号为# $ 其与地球人的等价公式如下x#y2*x3*y4x$y3*xy2x y是无符号整数 地球人公式按照c语言规则进行计算 火星人公式中$符优先级高于#相同的运算符按从左到右的顺序运算 输入描述 火星人字符串表达式结尾不带回车换行 输入的字符…...

【vue3教程】初入了解vue3的基本结构
前言 Animatrix:黑客帝国 Blade Runner:银翼杀手 Cowboy Bebop:星际牛仔 Dragon Ball:龙珠 Evangelion:新世纪福音战士 Ghostin the Shell:攻壳机动队 Hunter X Hunter:全职猎人 Initial D&…...

智慧供水综合运营平台解决方案
一、概述 建设背景: 供水系统是城市生存、发展的基础,供水事业的发展与城市的社会经济发展息息相关,其服务质量的好坏不仅关系到供水企业自身的利益,也直接影响到社会的稳定和政府形象。住房城乡建设部于2012年12月5日正式发布了《…...

文件系统、描述符和缓冲区
目录 🏆一、文件系统 1、open ①对open接口的介绍 ②接口使用 2、write接口 3、read接口 🏆二、深入理解文件描述符fd 1、fd具体实质 2、文件fd的分配规则 3、fd重定向 ①输出重定向 ②追加重定向 ③输入重定向 ④文件的引用计数 🏆三…...

java微服务商城高并发秒杀项目--009.流控规则和降级规则
线程流控(只要线程数达到了指定数量,访问就会被流控):warm up流控效果(慢慢增加QPS的数量,之后最后达到阈值,这种情况下,一开始会容易限流,后期就不会限流了)…...

php编写的脚本,如何才能在windows系统运行呢?
咱们要在Windows系统上运行PHP脚本,需要安装PHP解释器和Web服务器。 以下是基本的步骤,很简单: 下载PHP解释器:可以从官方网站 https://windows.php.net/download/ 下载Windows版本的PHP解释器。根据你的操作系统和需要的版本选…...

政务综合服务平台建设项目方案书
本资料来源公开网络,仅供个人学习,请勿商用,如有侵权请联系删除 目 录 第一章 项目整体概述 1.1. 项目名称 1.2. 建设单位 1.3. 编写依据 1.3.1 相关政策 1.3.2 技术标准 1.4. 建设目标、规模、内容、建设期 1.4.1 建设目标 1.4.2 …...

python好玩的短代码
Python语言是一种流行的编程语言,在 Python语言中有很多有趣的特性,比如: 1.变量可以定义为字符串,也可以定义为字符串对象 2.变量可以用来初始化一个函数或模块,函数或者模块可以定义成一个类,这个类被称为…...

会Python如何学习C#的几个关键点
Python和C#都是常用的编程语言,但两者之间存在一些重要的区别。如果你已经掌握了Python并希望学习C#,以下是几个关键点: 面向对象编程(OOP):C#是一种严格的面向对象编程语言,而Python则具有更灵…...

索引失效原则与查询优化
数据库调优的维度: 索引建立SQL优化(本文重点)my.cnf的调整(线程数,缓存等)分库分表 SQL查询优化的技术从大方向上可以分为 物理查询优化,逻辑查询优化 物理查询优化:即通过建立索…...

读完这篇文章你就彻底了解了什么是AES算法
目录 导论 介绍加密算法的定义和基本概念 解释加密算法在现代通信和存储系统中的重要性...

ArrayDeque类常用方法
数据结构 ArrayDeque类是 双端队列的线性实现类。 具有以下特征: ArrayDeque是采用数组方式实现的双端队列。ArrayDeque的出队入队是通过头尾指针循环,利用数组实现的。ArrayDeque容量不足时是会扩容的,每次扩容容量增加一倍。ArrayDeque可…...

Leetcode.130 被围绕的区域
题目链接 Leetcode.130 被围绕的区域 mid 题目描述 给你一个 m x n的矩阵 board,由若干字符 X和 O,找到所有被 X围绕的区域,并将这些区域里所有的 O用 X填充。 示例 1: 输入:board [[“X”,“X”,“X”,“X”],[“X…...

MySQL-四大类日志
目录 🍁MySQL日志分为4大类 🍁错误日志 🍃修改系统配置 🍁二进制日志 🍃查看二进制日志 🍃删除二进制日志 🍃暂时停止二进制日志的功能 🍁事务日志(或称redo日志) 🍁慢查…...

新加坡量子软件公司Horizon完成1810万美元A轮融资
(图片来源:网络) 近期,Horizon宣布已完成来自印度红杉资本、腾讯、SGInnovate、Pappas Capital和Expeditions Fund的1810万美元A轮投资。 Horizon是一家开发新一代编程工具的公司,总部位于新加坡,它致力…...

Spring学习(四):Scope的介绍及其失效解决方案
目录 一、spring当中有哪些scope 二、scope初始化与销毁演示 2.1 scope的初始化 2.2 scope的销毁 三、scope失效及其解决方案 3.1 scope失效演示 3.2 scope失效解决方案一:Lazy 3.3 scope失效解决方案二:设置proxyMode属性 3.4 scope失效解决…...

【学习集合--Set】
学习内容: Set集合概述Set集合实现—HashSet LinkedHashSet和TreeSet 学习产出: Set集合概述 Set中不存在值相同的节点。将两个对象e1.equals(e2),如果结果为true,或者(e1e2)内存地址相等,就认为两个对象…...

函数的参数
函数的默认实参 函数默认参数:函数的形参可以有默认值,如果我们自己传入参数,就用自己的数据,如果没有,那么用默认值 特别注意*: 如果某个位置有了默认参数,那么从这个位置往后,必…...

数组(八)-- LC[53][152] 最大子数组之和与乘积最大子数组
1 最大子数组之和 1.1 题目描述 题目链接:https://leetcode.cn/problems/maximum-subarray/ 1.2 求解思路 1. 暴力法 class Solution:def maxSubArray(self, nums: List[int]) -> int:length len(nums)max_sum float(-inf)for i in range(length):sum_sub_…...

docker2-zabbix
安装最新版docker yum remove docker docker-common docker-selinux docker-engine yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo yum makecache fast yum list docker-ce --showduplicates | sort -r yum install docke…...