热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

将符号串解析为表达式

将符号串解析为表达式原文:https://www . geesforgeks . org/parsing-字符串到表达式/给定一

将符号串解析为表达式

原文:https://www . geesforgeks . org/parsing-字符串到表达式/

给定一个表达式为由数字和基本算术运算符(+、-、、/)组成的字符串 str ,任务是求解该表达式。注意本程序使用的数字为一位数,不允许使用括号。
例:*

输入: str = "3/3+46-9"
输出: 16
自(3 / 3) = 1 和(4 * 6) = 24。
于是整体表达式变成(1+24–9)= 16
输入:str =“9 * 5-4 * 5+9”
输出:* 16

方法:创建一个堆栈类来存储数字和运算符(都是字符)。堆栈是一种有用的存储机制,因为在解析表达式时,需要频繁访问最后存储的项;而堆栈是一个后进先出(后进先出)容器。
除了 Stack 类之外,还创建了一个名为 express(expression 的缩写)的类,表示整个算术表达式。此类的成员函数允许用户使用字符串形式的表达式初始化对象,解析表达式,并返回结果算术值。
下面是算术表达式的解析方法。
一个指针从左边开始,迭代查看每个字符。它可以是数字(始终是 0 到 9 之间的一位数字符)或运算符(字符+、-、、和/)。
如果字符是一个数字,则被推送到堆栈上。遇到的第一个运算符也被推入堆栈。诀窍是处理后续的操作符。请注意,当前运算符无法执行,因为它后面的数字尚未被读取。找到一个运算符只是一个信号,表明我们可以执行存储在堆栈中的前一个运算符。也就是说,如果序列 2+3 在堆栈上,我们会等到找到另一个运算符后再执行加法。
因此,只要当前字符是运算符(除了第一个),前一个数字(在前面的例子中是 3)和前一个运算符(+)就会从堆栈中弹出,将它们放在变量 lastval 和 lastop 中。最后,弹出第一个数字(2),对两个数字进行算术运算(得到 5)。
但是,当遇到优先级高于+和–的
和/时,表达式无法执行。在表达式 3+4/2 中,在执行除法之前不能执行+运算。所以,2 和+被放回堆栈,直到执行除法。
另一方面,如果当前操作符是+或-,可以执行上一个操作符。也就是说,当表达式 4-5+6 中遇到+时,可以执行-,当表达式 6/2-3 中遇到–时,可以进行除法运算。表 10.1 显示了四种可能性。

| 上一个操作员 | 当前操作员 | 例子 | 行动 |
| --- | --- | --- | --- |
| +或– | *或/ | 3+4/ | 按下上一个运算符和上一个数字(+,4) |
| *或/ | *或/ | 9/3* | 执行前一个运算符,推送结果(3) |
| +或– | +或– | 6+3+ | 执行前一个运算符,推送结果(9) |
| *或/ | +或– | 8/2- | 执行前一个运算符,推送结果(4) |

以下是上述方法的实现:

卡片打印处理机(Card Print Processor 的缩写)

// C++ implementation of the approach
#include
#include
using namespace std;
// Length of expressions in characters
const int LEN = 80;
// Size of the stack
const int MAX = 40;
class Stack {
private:
    // Stack: array of characters
    char st[MAX];
    // Number at top of the stack
    int top;
public:
    Stack()
    {
        top = 0;
    }
    // Function to put a character in stack
    void push(char var)
    {
        st[++top] = var;
    }
    // Function to return a character off stack
    char pop()
    {
        return st[top--];
    }
    // Function to get the top of the stack
    int gettop()
    {
        return top;
    }
};
// Expression class
class Express {
private:
    // Stack for analysis
    Stack s;
    // Pointer to input string
    char* pStr;
    // Length of the input string
    int len;
public:
    Express(char* ptr)
    {
        pStr = ptr;
        len = strlen(pStr);
    }
    // Parse the input string
    void parse();
    // Evaluate the stack
    int solve();
};
void Express::parse()
{
    // Character from the input string
    char ch;
    // Last value
    char lastval;
    // Last operator
    char lastop;
    // For each input character
    for (int j = 0; j         ch = pStr[j];
        // If it's a digit then save
        // the numerical value
        if (ch >= '0' && ch <= '9')
            s.push(ch - '0');
        // If it's an operator
        else if (ch == '+' || ch == '-'
                 || ch == '*' || ch == '/') {
            // If it is the first operator
            // then put it in the stack
            if (s.gettop() == 1)
                s.push(ch);
            // Not the first operator
            else {
                lastval = s.pop();
                lastop = s.pop();
                // If it is either '*' or '/' and the
                // last operator was either '+' or '-'
                if ((ch == '*' || ch == '/')
                    && (lastop == '+' || lastop == '-')) {
                    // Restore the last two pops
                    s.push(lastop);
                    s.push(lastval);
                }
                // In all the other cases
                else {
                    // Perform the last operation
                    switch (lastop) {
                    // Push the result in the stack
                    case '+':
                        s.push(s.pop() + lastval);
                        break;
                    case '-':
                        s.push(s.pop() - lastval);
                        break;
                    case '*':
                        s.push(s.pop() * lastval);
                        break;
                    case '/':
                        s.push(s.pop() / lastval);
                        break;
                    default:
                        cout <<"\nUnknown oper";
                        exit(1);
                    }
                }
                s.push(ch);
            }
        }
        else {
            cout <<"\nUnknown input character";
            exit(1);
        }
    }
}
int Express::solve()
{
    // Remove the items from stack
    char lastval;
    while (s.gettop() > 1) {
        lastval = s.pop();
        switch (s.pop()) {
        // Perform operation, push answer
        case '+':
            s.push(s.pop() + lastval);
            break;
        case '-':
            s.push(s.pop() - lastval);
            break;
        case '*':
            s.push(s.pop() * lastval);
            break;
        case '/':
            s.push(s.pop() / lastval);
            break;
        default:
            cout <<"\nUnknown operator";
            exit(1);
        }
    }
    return int(s.pop());
}
// Driver code
int main()
{
    char string[LEN] = "2+3*4/3-2";
    // Make expression
    Express* eptr = new Express(string);
    // Parse it
    eptr->parse();
    // Solve the expression
    cout <solve();
    return 0;
}

Output: 

4

时间复杂度 : O(N)。
辅助空间 : O(N)。


推荐阅读
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
  • 电话号码的字母组合解题思路和代码示例
    本文介绍了力扣题目《电话号码的字母组合》的解题思路和代码示例。通过使用哈希表和递归求解的方法,可以将给定的电话号码转换为对应的字母组合。详细的解题思路和代码示例可以帮助读者更好地理解和实现该题目。 ... [详细]
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • IhaveconfiguredanactionforaremotenotificationwhenitarrivestomyiOsapp.Iwanttwodiff ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
author-avatar
书友54330525
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有