每日一题——逆波兰表达式求值(前缀、中缀、后缀表达式的说明,库函数atoi()的解析)

news2024/12/23 8:36:18

文章目录

  • 每日一题
    • 逆波兰表达式求值
      • 中缀,前缀(波兰),后缀(逆波兰)表达式的基本概念
      • 逆波兰表达式的优点和计算方法
        • 优点
        • 计算方法
      • 思路
        • 函数原型
        • 如何将数字入栈
          • 库函数atoi()
      • 实现代码

每日一题

逆波兰表达式求值

题目链接

在这里插入图片描述

中缀,前缀(波兰),后缀(逆波兰)表达式的基本概念

  • 逆波兰表达式即所谓的后缀表达式
  • 我们常见的数学表达式如:3 + 4、5 + (6 -3) * 2……等,都是中缀表达式,中缀表达式的操作符位于操作数的中间
  • 中缀表达式:也叫波兰表达式,如- × + 3 4 5 6前缀表达式的操作符位于操作数的前面
  • 后缀表达式:也叫逆波兰表达式,如3 4 + 5 × 6 -后缀表达式的操作符位于操作数的后面

逆波兰表达式的优点和计算方法

优点

  • 省略了括号,使表达式更加简洁明了,减少了歧义。
  • 方便计算机进行计算,因为计算机可以使用栈来实现对后缀表达式的计算,而不需要使用递归或复杂的算法
  • 可以避免运算符优先级的问题,因为后缀表达式中运算符的优先级是通过运算符在表达式中的位置来确定的,而不是通过运算符本身的优先级来确定的。
  • 可以方便地转换成前缀表达式,因为后缀表达式的计算顺序与前缀表达式的计算顺序相反,只需将后缀表达式中的操作数和运算符反转即可得到前缀表达式。

计算方法

  • 适合用栈操作运算遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中

思路

函数原型

int evalRPN(char** tokens, int tokensSize)
  • 可能有小伙伴会疑惑,为什么要传入二级指针呢?tokens存储的是数字字符‘0’ ~ ‘9’,和操作符字符‘+’, ‘-’ ,‘*’, ‘/’,我们又不改变数组的值,只是对其进行解引用,为什么要传入二级指针呢?其实,大家可能忽略了一点,即被操作的数字不一定是个位数, 如果被操作的是一个十位数及其以上的数,那么就需要一个字符串来存储这多个数字字符,继而我们可以得到,我们需要用一个字符指针数组来存储这多个字符串
  • tokensSize就是字符串指针数组中字符串的个数

如何将数字入栈

  • 如果被操作数是一个个位数,那么好办,用 StackPush(st, tokens[i][0] - '0')这个操作就好了(StackPush是入栈函数)
  • 但如果被操作数是以一个十位数及其以上的数字呢?那我们就要对多个字符进行处理,如果是一个负数就更麻烦了。那有没有简单的操作呢?
    • 这里我们就需要用到==库函数atoi()==了
库函数atoi()
  • 函数原型 int atoi(const char *str )

  • str即传入的字符串

  • 函数功能:把字符串转换成整型数

  • 返回值:此值由将输入字符作为数字解析而生成。 如果该输入无法转换为该类型的值,则atoi的返回值为 0

  • 注:该函数的返回值是int类型,因此传入的字符串所表示的值不能超过int所能表示的范围

  • EG:

    #include <stdio.h>
    #include <stdlib.h>
     
    int main()
    {
    	int a;
     
    	char *ptr1 = "3124";
    	char *ptr2 = "0";
    	char *ptr3 = "12.33";
    	char *ptr4 = "-1245";
    	char *ptr5 = "+21";
    	char *ptr6 = "s3241";
        char *ptr7 = "*3241";
        char *ptr8 = "/3241";
     
    	a = atoi(ptr1);
    	printf("\"%s\"\t-> %d\n",ptr1, a);
     
    	a = atoi(ptr2);
    	printf("\"%s\"\t-> %d\n",ptr2, a);
     
    	a = atoi(ptr3);
    	printf("\"%s\"\t-> %d\n",ptr3, a);
     
    	a = atoi(ptr4);
    	printf("\"%s\"\t-> %d\n",ptr4, a);
     
    	a = atoi(ptr5);
    	printf("\"%s\"\t-> %d\n",ptr5, a);
     
    	a = atoi(ptr6);
    	printf("\"%s\"\t-> %d\n",ptr6, a);
        
        a = atoi(ptr7);
    	printf("\"%s\"\t-> %d\n",ptr7, a);
        
        a = atoi(ptr8);
    	printf("\"%s\"\t-> %d\n",ptr8, a);
     
    	return 0;
    }
    
    • 可以得到如下结果:

      在这里插入图片描述

  • 缺陷分析:我们可以看到,如果传入的是无效的字符串,那么返回值就是0,那么在不知道传入的字符串是否有效的情况下,我们就会不知道字符串到底是无效字符串还是本来是是字符串“0”。

实现代码

  • 有了以上的准备,这题就好写了,直接上代码。
#include<assert.h>

typedef struct Stack
{
    int* stack;
    int top;
}ST;

//判断栈空
bool StackEmpty(ST *st)
{
    return st->top == 0;
}

//初始化栈
void StackInit(ST* st, int len)
{
    st->stack = (int*)malloc(sizeof(int) * len);
    st->top = 0;
}

//入栈
void StackPush(ST* st, int val)
{
    st->stack[st->top] = val;
    st->top++;
}

//出栈,并返回栈元素
int StackPop(ST* st)
{
    assert(!StackEmpty(st));
    st->top--;
    return st->stack[st->top];
}

int evalRPN(char** tokens, int tokensSize) {
    ST* st = (ST*)malloc(sizeof(ST));	//申请栈内存
    StackInit(st, tokensSize);	//初始化栈
    
    for (int i = 0; i < tokensSize; i++)
    {
        //如果是操作符,并且字符串的长度为1(排除负数的情况)
        if (strlen(tokens[i]) == 1 && 
        (tokens[i][0] == '+'|| 
        tokens[i][0] == '-' || 
        tokens[i][0] == '*' || 
        tokens[i][0] == '/'))
        {
            //取出栈顶的两个元素
            int num_1 = StackPop(st);
            int num_2 = StackPop(st);
            
            switch (tokens[i][0])
            {
            case '+':
                StackPush(st, num_2 + num_1);
                break;
            case '-':
                StackPush(st, num_2 - num_1);
                break;
            case '*':
                StackPush(st, num_2 * num_1);
                break;
            case '/':
                StackPush(st, num_2 / num_1);
                break;
            }
        }
        //如果是操作数
        else
        {
            StackPush(st, atoi(tokens[i]));       //利用atoi库函数,直接将字符串转换为数字,入栈
        }
    }
    
    //返回最后的结果
    return st->stack[--(st->top)];
}

tips:本篇对库函数atoi()的解析,对atoi()函数解析以及缺陷分析,以及对atoi()、atof()的改造这篇博文多有参考,如果读者想对这个库函数有更深的了解,可以去看看大佬写的博客。

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

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

相关文章

chatgpt赋能python:Python代码转换:如何将代码从Python2转换为Python3

Python 代码转换&#xff1a;如何将代码从 Python 2 转换为 Python 3 作为一位有10年 Python 编程经验的工程师&#xff0c;我们都知道 Python 的两个主要版本&#xff1a;Python 2 和 Python 3。不过&#xff0c;Python 2 已于2020年正式停止支持&#xff0c;因此&#xff0c…

MySQL-7-权限与密码

一、用户授权与权限撤销 1.1、用户授权: 赋予权限:grant all on *.* to root192.168.4.% identified by "123456";从网络访问本地数据库时:只有 增删改查权限,本地登录则有所有权限。 新建用户,并赋予权限:格式&#xff1a;grant 权限列表 on 库名.表名 to 用户…

图数据库的一些概览

图数据库 图数据库是一种根据节点和边存储数据的数据库。数据以非常灵活的方式存储&#xff0c;无需遵循预定义的模型。该图形成了两个节点之间的关系&#xff0c;这种关系可以是有向的也可以是无向的。这些数据库旨在处理数据/节点之间的复杂关系。 节点用于存储数据。每个节…

chatgpt赋能python:Python-高效的SEO工具

Python - 高效的SEO工具 Python作为一种高效且易于学习的编程语言&#xff0c;广泛应用于各种领域&#xff0c;包括机器学习、数据分析、网站开发等。Python的灵活性和可扩展性也使它成为一种优秀的SEO工具。 Python在SEO中的应用 Python可用于SEO行业中的多个方面。例如&am…

IDEA内操作框文件地址生成+IDEA数组传参处理+springboot缺少依赖问题

1&#xff0c;IDEA内查询文件本地所属位置 首先在输入框内我们输入以下指令即可查询该目录下文件&#xff1a; lscd即是可进入指定目录 这样我们即可进行文件浏览与进入文件等操作 pwd即可生成该文件目录下的文件地址 2&#xff0c;IDEA数组传参处理 当结果是以数组形式被输…

chatgpt赋能python:Python信息查询的完全指南

Python信息查询的完全指南 Python是一种开源、解释性高级编程语言&#xff0c;广泛应用于数据科学、机器学习、人工智能、Web开发和自动化任务等领域。Python的简洁易读、高效快速的特点&#xff0c;使其成为程序员和企业的首选语言。然而&#xff0c;学习Python并不容易&…

Docker v24.0.0 发布

导读Docker 24.0.0 现已发布&#xff0c;具体更新内容如下&#xff1a; New 引入对 containerd 作为内容存储的实验性支持&#xff08;替换现有的存储驱动程序&#xff09;。moby/moby#43735, other moby/moby pull requests--hostCLI flag 现在支持 ssh:// 主机地址中的路径组…

Java基础(8)——java的异常机制初步

引出 java异常机制初步 异常是什么 程序运行时&#xff0c;产生非正常的结果。 java异常体系 异常的体系&#xff1a; 异常是可抛出的 不同的异常处理&#xff1a; 如果一个异常类继承Exception,可检测异常&#xff1a;必须处理继承RuntimeException,运行时异常&#xff0c…

chatgpt赋能python:Python是否需要付费?

Python是否需要付费&#xff1f; Python是一种高级动态编程语言&#xff0c;文件以.py为扩展名。它具有广泛的应用&#xff0c;包括构建网站、数据分析和科学计算等领域。Python是一种免费开源软件&#xff0c;在大多数情况下不需要任何费用。然而&#xff0c;在某些情况下&am…

java反射获取方法以及调用方法

Class类中获取方法&#xff1a; public Method[] getMethods();//获取包括自身和继承&#xff08;实现&#xff09;过来的所有的public方法——Method不支持泛型<>&#xff0c;即后面不接<> public Method[] getDeclaredMethods();//获取自身所有的方法(private、…

SQL-计算连续签到天数

1、应用场景 现在有一份用户签到行为数据&#xff0c;记录了用户ID&#xff0c;签到日期。 在业务场景中&#xff0c;通常会要求用户连续签到&#xff0c;如果断签则要重新开始计数。 所以需要基于上述数据&#xff0c;计算筛选出连续签到天数大于n天的用户。 日期用户ID20…

chatgpt赋能python:Python仿真模拟:介绍与应用

Python仿真模拟&#xff1a;介绍与应用 Python是一种流行的编程语言&#xff0c;其与技术仿真的结合越来越受欢迎&#xff0c; 广泛用于各种仿真和模拟应用程序中。在本文中&#xff0c;我们将介绍Python仿真模拟的基本原理&#xff0c;及其在不同领域中的应用和优势。 什么是…

在酒店房间中的数据库索引

如果你经常去酒店&#xff0c;你会看到一块类似下面的标牌&#xff0c;指引你到达房间。这能够帮助你方便快速地找到房间&#xff0c;特别是当酒店拥有许多房间时。 以一个有9层的酒店为例。你的房间号是917。第一步是找到你的房间在哪一层&#xff0c;通常第一个数字表示楼层…

[数据结构习题]链表——单链表重排

[数据结构习题]链表——单链表重排 &#x1f449;知识点导航&#x1f48e;&#xff1a;【数据结构】线性表——顺序存储 &#x1f449;知识点导航&#x1f48e;&#xff1a;【数据结构】线性表——链式存储 &#x1f449;[王道数据结构]习题导航&#x1f48e;&#xff1a; p …

DAY02_MySQL高级-约束数据库设计多表查询事务

目录 1 约束1.1 概念1.2 分类1.3 非空约束1.4 唯一约束1.5 主键约束1.6 默认约束1.7 约束练习1.7.1 修改自增序列号 1.8 外键约束1.8.1 概述1.8.2 语法1.8.3 练习 2 数据库设计2.1 数据库设计简介2.2 表关系(一对多)2.3 表关系(多对多)2.4 表关系(一对一)2.5 数据库设计案例 3 …

kubernetes之client-go informer源码分析

一、概念 informer 是 client-go 中的核心工具包&#xff0c;在kubernetes中&#xff0c;各个组件通过HTTP协议跟 API Server 进行通信。如果各组件每次都直接和API Server 进行交互&#xff0c;会给API Server 和ETCD造成非常大的压力。在不依赖任何中间件的情况下&#xff0…

从零开始手写VIO 第3讲 基于优化的 IMU 与视觉信息融合

技巧性u初始值&#xff0c;更新的原因都不知道杂来的 F(x)是复杂的非线性函数&#xff0c;所以没法直接求导0得到最小值。所以展开 两种方法来下降&#xff0c;一种是先找一个方向&#xff0c;在确定一个步长line search。另一种是先确定区域&#xff0c;再找一个点。 J是FX的雅…

docker架构速看(1)-启动

Docker架构速看(1)-启动 ​ Docker是常用的容器管理工具&#xff0c;这篇文章对Docker架构结合源码做简要分析&#xff0c;由于也只使用过很少的命令&#xff0c;所以只分析image和container的相关部分。 源码准备 ​ Docker源码可以在github上找到&#xff0c;当前已更名为…

Vector-常用CAN工具 - VN5000接口以太网包过滤

目录 一、什么是硬件过滤&#xff1f; 1、什么时候应该过滤硬件&#xff1f; 2、需要注意什么&#xff1f; 3、如何过滤VN5000接口上的以太网报文&#xff1f; &#xff08;1&#xff09;Vector Hardware Manager &#xff08;2&#xff09;Vector Hardware Config 一、…

Benewake(北醒) 快速实现 TF03-485 与电脑通信操作说明

目录 一、前言二、工具准备1. USB-RS485 转接板或北醒 TF 系列专用转接板2. TF03-4853. PC&#xff1a;Windows 系统4. 串口助手软件、上位机 WINCC 三、连接方式方案一&#xff1a;USB-RS485 连接电脑与雷达(1) USB-RS485 转接板接口说明(2) TF03-485 引脚定义(3) 连接方式 方…