首页 > 其他分享 >atoi函数详解及模拟实现

atoi函数详解及模拟实现

时间:2024-03-24 23:34:23浏览次数:12  
标签:字符 详解 int ret atoi str printf 模拟

文章目录

atoi函数详解及模拟实现

函数详解

atoi函数包含在头文件 <stdlib.h>

int atoi(const char* str);

atoi将字符串str中的数字字符解释成整数以int类型的值返回。

举个例子:

#include <stdio.h>
#include <stdlib.h>
int main()
{
    printf("%d\n", atoi("123abc"));
    return 0;
}

打印结果是:

在这里插入图片描述

说到这,我们会想如果传入的字符串是类似"abc123ff567"这样的又该打印什么呢?是123还是123567,还是其他的。

答案是0。


接下来我们介绍一下atoi函数使用的一些注意事项和规则:

  • 如果传入的是NULL,会直接报错。

  • 如果是空字符串,直接返回0。

  • 如果转换后的值超出 int 的可表示值范围,则会导致未定义的行为。

​ 头文件 <limits.h> 内规定了int类型的最大值
在这里插入图片描述
除此之外,

atoi函数会先自动跳过所有空白字符,直到找到第一个非空字符,根据第一个非空字符,有如下规则:

  • 为数字字符,则继续寻找后面连续的数字字符,直到找到非数字字符,转换之前的数字字符
  • 为非数字字符,返回0。不过有特殊情况,如果第一个非空字符为’+‘或’-‘且后面的一位是数字字符,那么’+‘、’-'号作为后面连续数字字符转换后的符号,然后转换数字字符,直到找到非数字字符。例如" +123ggg"转换后为123(省略+号)、" -342opp"转换后为-342

我们看几组例子:

#include <stdlib.h>
#include <stdio.h>
int main()
{
    printf("%d\n", atoi(""));//空字符串
    printf("%d\n", atoi("a123"));//首非空字符不为数字字符
    printf("%d\n", atoi(" +-123end"));//首非空字符为'+',但是它后面一个字符不是数字字符
    printf("%d\n", atoi(" - 123end"));//首非空字符为'-',但是它后面一个字符不是数字字符
    printf("%d\n", atoi(" +12345678900"));//未定义的行为,返回值不是我们想要的
    printf("%d\n", atoi(" -12345678900"));//未定义的行为,返回值不是我们想要的
    printf("%d\n", atoi("   +123end"));//首非空字符为'+'且后面一个字符是数字字符
    printf("%d\n", atoi("  -12 3end"));//注意中间的空白字符不会跳过
    return 0;
}

打印结果为:

在这里插入图片描述

模拟实现

//我们将转换后超出int范围情况的返回值设置为0,以此表示未定义行为。
#include <limits.h>
#include <stdlib.h>
#include <ctype.h>

int my_atoi(const char* str)
{
    assert(str);//NULL情况
    long long ret = 0;
    int flag = 1;//标识符号
    while (isspace(*str))//跳过空白字符
    {
        str++;
    }
    if (*str == '\0')//判断为空字符串则返回0
        return 0;

    while (*str != '\0')
    {
        //第一个非空字符不为数字字符的特殊情况
        if (*str == '-' && isdigit(*(str + 1)))
        {
            flag = -1;
            str++;
        }
        else if (*str == '+' && isdigit(*(str + 1)))
        {
            flag = 1;
            str++;
        }
        //非空字符不为数字字符且不满足特殊情况
        else if (!isdigit(*str))
        {
            return 0;
        }
        //找到数字字符开始转换
        else
        {
            while (isdigit(*str))
            {
                ret = ret * 10 + (*str - '0');
                if (ret > INT_MAX || ret < INT_MIN)
                    return 0;
                str++;
            }
            ret = ret * flag;
            return (int)ret;
        }
    }
}


int main()
{
    printf("%d\n", my_atoi(""));
    printf("%d\n", my_atoi("a123"));
    printf("%d\n", my_atoi(" +-123end"));
    printf("%d\n", my_atoi(" - 123end"));
    printf("%d\n", my_atoi(" +12345678900"));
    printf("%d\n", my_atoi(" -12345678900"));
    printf("%d\n", my_atoi("   +123end"));
    printf("%d\n", my_atoi("  -12 3end"));
    return 0;
}

测试结果是:

在这里插入图片描述
为了方便观看,把模拟实现的函数单独拿出来。

int my_atoi(const char* str)
{
    assert(str);
    long long ret = 0;
    int flag = 1;
    while (isspace(*str))
    {
        str++;
    }
    if (*str == '\0')
        return 0;

    while (*str != '\0')
    {
        if (*str == '-' && isdigit(*(str + 1)))
        {
            flag = -1;
            str++;
        }
        else if (*str == '+' && isdigit(*(str + 1)))
        {
            flag = 1;
            str++;
        }
        else if (!isdigit(*str))
        {
            return 0;
        }
        else
        {
            while (isdigit(*str))
            {
                ret = ret * 10 + (*str - '0');
                if (ret > INT_MAX || ret < INT_MIN)
                    return 0;
                str++;
            }
            ret = ret * flag;
            return (int)ret;
        }
    }
}

以上就是对于atoi函数的全部介绍了。

标签:字符,详解,int,ret,atoi,str,printf,模拟
From: https://blog.csdn.net/xiaokuer_/article/details/136955304

相关文章

  • 模拟DNS服务
    #testindebian10#检查当前域名服务pingbaidu.com#注释DNS当前服务,并添加本机IPvi/etc/resolv.conf#nameserver108.61.10.10nameserver127.0.0.1#查看是否已安装bind9dpkg-l|grepbind9#安装bind9aptupdateaptinstallbind9#修改配置文件vi/e......
  • Offer必备算法16_字符串_四道力扣题详解(由易到难)
    目录①力扣14.最长公共前缀解析代码1(两两比较)解析代码2(统一比较)②力扣5.最长回文子串解析代码(中心拓展)③力扣67.二进制求和解析代码④力扣43.字符串相乘解析代码(无进位相乘)本篇完。①力扣14.最长公共前缀14.最长公共前缀难度简单编写一个函数来查找字符......
  • Elasticsearch 涉及的主要底层原理详解
    目录原理篇1.倒排索引原理2.文档写3.单个文档查询4.多个文档查询5.文档删除与更新6.集群组建7.集群选主8.集群数据读写如果你只是会用Elasticsearch而不了解它的运行机制,不是一个合格开发工程师。作为一名开发工程师,在掌握一项中间件的使用的同时,应该同时掌握该中间件的基本原......
  • MVC设计模式的详解及应用
    文章目录一、MVC是什么二、MVC的优点三、MVC的应用领域一、MVC是什么MVC全名是ModelViewController,是一种软件设计典范,也是一个框架模式。它将应用程序分成三个核心部件:模型(Model)、视图(View)和控制器(Controller)。每个部件都有自己的任务和责任。模型(M......
  • 登山小分队(dfs,模拟)
    原题链接:题目描述Foxity和他的好友们相约去爬山,但是他们每个人都来到了不同的山脚下。整个山的结构类似一棵"树",有很多的观光节点通过一条条山道连接起来。在图论中,树是一种无向图,其中任意两个顶点之间存在唯一一条路径。或者说,只要没有回路的连通图就是树。这个问题中,我们......
  • 软件工程与实践(第四版 新形态)第3章习题答案详解
    第三章一、填空题二、选择题三、简答题四、实践题一、填空题(1)方法或服务(2)类对象(3)类对象继承消息通信二、选择题(1)B(2)C(3)C(4)B(5)D三、简答题(1)什么叫面向对象?面向对象方法OOM的特点是什么?为什么用OOM开发软件?面向对象是一种软件开发方法,它将数据和操作数据的......
  • 详解rtklib中main函数如何配置文件(下)
    目录一、main函数流程总结二、分析识别-k后如何配置三、最后传参的数据文件处理方式 一、main函数流程总结详解rtklib中main函数如何配置文件(上)-CSDN博客在这片文章中讲解了rtklib中main函数的整个流程。(1)通过两种方法给main函数传递参数,并放在argv这个指针数组......
  • 设计模式-单例模式(模拟面试官八股)
    一、请说下设计模式中,你熟悉的设计模式单例模式二、单例模式你有了解吗单例模式是创建型设计模式,该类负责创建自己的对象,他确保一个类只有一个实例,并且提拱了一个去全局访问点来访问该实例。二、单例模式有几种实现方式 1.饿汉式(静态常量)优点:写法容易,在类加载的时候就......
  • Java序列化之Jackson详解
    目录1Jackson1.1Jackson简介1.2为什么选择Jackson1.3Jackson的基本功能1.3.1将Java对象转换为JSON字符串(序列化)1.3.2将JSON字符串转换为Java对象(反序列化)1.4Jackson库主要方法1.5使用Jackson基本步骤1.5.1添加依赖(Maven或Gradle)1.5.2创建Java对象模型1.5.3使用ObjectMa......
  • docker推拉时的数据交换详解
    前言docker用了这么久了,有没有想过,在执行dockerpush和dockerpull命令的时候,数据是如何传递的呢?换句话说,如果要实现一个镜像仓库,针对推拉的服务,如何实现接口呢?根据OCI分发规范文档的描述,已经对整个推拉过程中要调用的接口有描述了.但是,纸上学来终觉浅,......