(力扣简单题解)基本计算器 C语言

给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。

整数除法仅保留整数部分。

你可以假设给定的表达式总是有效的。所有中间结果将在 [-231, 231 - 1] 的范围内。

注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。

示例 1:

输入:s = "3+2*2"
输出:7

示例 2:

输入:s = " 3/2 "
输出:1

示例 3:

输入:s = " 3+5 / 2 "
输出:5

提示:

  • 1 <= s.length <= 3 * 105
  • s 由整数和算符 ('+', '-', '*', '/') 组成,中间由一些空格隔开
  • s 表示一个 有效表达式
  • 表达式中的所有整数都是非负整数,且在范围 [0, 231 - 1] 内
  • 题目数据保证答案是一个 32-bit 整数

解题思路:本质就是不同符号的计算结果放在栈中后进行累加得出结果:

由题目可以看出计算器输入时是由空格隔开的且是由char* s这样的字符串定义s

1.先梳理解题时需要的变量

 数组s的长度n;再定义一个栈stk 以及其索引top;

2.由于计算器每次不可能都输入的是个位数,当输入是多位数时需要进行

int n=strlen(s);
int num=0;
for(int i=0;i<n;i++){
    if(s[i]>=0&&s[i]<=9){
        num=num*10+(int)(s[i]-'0');
    }//(int)(s[i]-'0');
/*s[i] - '0':这部分代码的目的是将字符(如 '1'、'2' 等)转换成对应的整数(如 1、2 等)。在ASCII码
表中,字符 '0' 到 '9' 是连续排列的,且 '0' 的ASCII码值比实际的整数0大48(在大多数ASCII码表中)。
因此,通过从字符的ASCII码值中减去 '0' 的ASCII码值,可以得到该字符所代表的整数。例如,'1' 的ASCII码
值减去 '0' 的ASCII码值等于 1。
*/

}

(s[i]>=‘0’&&s[i]<=‘9’)可以用isdigit(s[i])来替换 不容易出错

3.利用switch来选择符号到底是' + ' ' - ' ' * ' ' /' 由于不管是数字还是符号其中都是由空格隔开所以我们每次只需要找空格就可以(且需要同时满足该符号是非数字的,最后一个空格的位置应该是(n(s数组的长度)-1)位置)

for (int i = 0; i < n; ++i) {
if (!isdigit(s[i]) && s[i] != ' ' || i == n - 1) {
            switch (symbol) {
                case '+':
                    stk[top++] = num;
                    break;
                case '-':
                    stk[top++] = -num;
                    break;
                case '*':
                    stk[top - 1] *= num;
                    break;
                case '/':
                    if (num != 0) {
                        stk[top - 1] /= num;
                    } else {
                        // Handle division by zero
                        printf("Error: Division by zero.\n");
                        return -1; // Or some error code
                    }
                    break;
            }
            if (i < n - 1) symbol = s[i];
            num = 0;
        }


}

我们还需要面对符号的优先级的问题时先处理乘法和除法把结果压入栈中,面对加法直接把数值压入栈中,面对减号对数值取反后压入栈中,一切结束后再进行统一的相加。所以我们需要给symbol初始化时给”+“。

  • 加号(+):将当前解析出的数(num)压入栈中,以便后续与另一个数相加。
  • 减号(-):将当前解析出的数的相反数(-num)压入栈中,以便后续与另一个数相减。
  • 乘号(*):将栈顶元素(stk[top - 1])与当前解析出的数(num)相乘,并将结果存回栈顶元素中。这里不需要调整栈顶指针(top),因为您正在原地修改栈顶元素。
  • 除号(/):首先检查除数(num)是否为0,以避免除零错误。如果不是0,则将栈顶元素除以当前解析出的数,并将结果存回栈顶元素中。如果除数为0,则打印错误消息并返回错误代码。
  • 假设输入表达式是 "3 * 4 + 2"

  • 读取 '3',将 3 存入 num,继续。
  • 读取 ' '(空格),忽略,继续。
  • 读取 '*',将 3stk[top++] = num;)推入栈中,设置 symbol 为 '*',重置 num 为 0,继续。
  • 读取 '4',将 4 存入 num,继续。
  • 读取 '+',此时 symbol 是 '*',执行乘法 stk[top - 1] *= num;(即 3 * 4),栈中现在是 [12],设置 symbol 为 '+',重置 num 为 0,继续。
  • 读取 '2',将 2 存入 num,继续。
  • 到达字符串末尾,执行加法 stk[top++] = num;(将 2 推入栈中),栈中现在是 [12, 2]
  • 最后,遍历栈并将所有元素相加得到最终结果 14

综上:完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

int calculate(char* s) {
    int n = strlen(s);
    int stk[n], top = 0;
    char symbol = '+';
    int num = 0;
    for (int i = 0; i < n; ++i) {
        if (isdigit(s[i])) {
            num = num * 10 + (s[i] - '0');
        }
        if (!isdigit(s[i]) && s[i] != ' ' || i == n - 1) {
            switch (symbol) {
                case '+':
                    stk[top++] = num;
                    break;
                case '-':
                    stk[top++] = -num;
                    break;
                case '*':
                    stk[top - 1] *= num;
                    break;
                case '/':
                    if (num != 0) {
                        stk[top - 1] /= num;
                    } else {
                        // Handle division by zero
                        printf("Error: Division by zero.\n");
                        return -1; // Or some error code
                    }
                    break;
            }
            if (i < n - 1) symbol = s[i];
            num = 0;
        }
    }
    int ret = 0;
    for (int i = 0; i < top; i++) {
        ret += stk[i];
    }
    return ret;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值