首页 > 试题广场 >

简单计算器

[编程题]简单计算器
  • 热度指数:22236 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
    读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值。

输入描述:
    测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格分隔。没有非法表达式。当一行中只有0时输入结束,相应的结果不要输出。


输出描述:
    对每个测试用例输出1行,即该表达式的值,精确到小数点后2位。
示例1

输入

1 + 2
4 + 2 * 5 - 7 / 11
0

输出

3.00
13.36
贴个垃圾题解(王道思路)
using namespace std;
#include <iostream>
#include <cstring>
#include <stack>
#include <sstream>
#include <map>
#include <iomanip>
template<class out_type, class in_value>
out_type convert(const in_value & t){
    stringstream stream;
    stream << t;
    out_type result;
    stream >> result;
    return result;
}
double func(char s, double m, double n){
    if(s == '*')return n*m;
    if(s == '/')return double(n/(m*1.0));
    if(s == '+')return n+m;
    return n-m;
}
int main(){
    string str;
    map<char, int> pr = {
        {'*', 2}, {'/', 2},
        {'+', 1}, {'-', 1},
        {'#', 0}
    };
    while(getline(cin, str) and str != "0"){
        stack<char> m;
        stack<double> n;
        istringstream is(str);
        string s;
        while(is>>s){
            if(s[0] >= '0' and s[0] <= '9'){
                n.push(convert<double>(s));
            }
            else{
                if(!m.empty()){
                    if(pr[m.top()] >= pr[s[0]]){
                        while(!m.empty() and pr[m.top()] >= pr[s[0]]){
                            double t1 = n.top();
                            n.pop();
                            double t2 = n.top();
                            n.pop();
                            char ss = m.top();
                            m.pop();
                            n.push(func(ss, t1, t2));
                        }
                        m.push(s[0]);
                    }
                    else{
                        m.push(s[0]);
                    }
                }
                else{
                    m.push(s[0]);
                }
            }
        }
        while(!m.empty()){
            double t1 = n.top();
            n.pop();
            double t2 = n.top();
            n.pop();
            char ss = m.top();
            m.pop();
            n.push(func(ss, t1, t2));
        }
        printf("%.2f\n", n.top());
        n.pop();
    }
    return 0;
}


发表于 2021-06-21 22:23:22 回复(0)
//1.根据运算符划分数字数组和字符数组2.处理乘法除法变换数字数组3.处理加减法获得结果
#include<stdio.h>
int main()
{
    char a[200],fuhao[100];
    float number[100]={0};int i,j,num;
    gets(a);
    num=0;//0---num数字的下标  0-num-1符号的下标
    //1.把数字符号 划分到两个数组
    for(i=0;a[i]!='\0';i++)
    {
        if(a[i]>='0'&&a[i]<='9')
        {
            number[num]=number[num]*10+(a[i]-'0');//解决位数问题
        }
        else if(a[i]=='+'||a[i]=='-'||a[i]=='*'||a[i]=='/'){
            fuhao[num]=a[i];
            num++;
        }
    }
    //2.处理乘法除法
	for(i=0;i<num;i++)
	{
		if(fuhao[i]=='*')
		{
			number[i]=number[i]*number[i+1];//两个数字相乘放在当前位置
           for(j=i+1;j<=num;j++)//把乘除的两个数变成一个数 后面的数字前移
                number[j]=number[j+1];
            for(j=i;j<num;j++)    //后面的符号前移
                fuhao[j]=fuhao[j+1];
            num--;i--;//长度减一, 再从当前位置开始计算
		}
		if(fuhao[i]=='/')
		{
			number[i]=number[i]/number[i+1];
			for(j=i+1;j<=num;j++)
                number[j]=number[j+1];
            for(j=i;j<num;j++)
                fuhao[j]=fuhao[j+1];
            num--;i--;
            
		}
	}
     //3.处理加减法
	float sum=number[0];
	for(i=0;i<num;i++)
	{
		if(fuhao[i]=='+')
			sum+=number[i+1];
		if(fuhao[i]=='-')
			sum-=number[i+1];
	}
	printf("%.2f\n",sum);
	return 0;
}

发表于 2020-04-16 13:50:27 回复(0)

这个程序是进阶版,加多了小括号。能实现+, -, *, / ,(,)。间接递归解决~
#include <bits/stdc++.h>
using namespace std;
double factor();
double term();
double expression();
char cleanspace(char ch){
		if(ch==' ') {
			cin.get();
			ch=cin.peek();
		}
		return ch;
}
double factor() {
	double result=0;
		char ch=cin.peek();
		 ch=cleanspace(ch);
		if(ch=='('){
			cin.get();
			result=expression();
			cin.get();
		}
		else{
			while(isdigit(ch)){
				cin.get();
				result=result*10+ch-'0';
				ch=cin.peek();
				ch=cleanspace(ch);
			}
		}
		return result;
}
double term() {
	double result=factor();
		while(true) {
		char ch=cin.peek();
		ch=cleanspace(ch);
		if(ch=='*'||ch=='/'){
			cin.get(); 
			double value=factor();
			if(ch=='*') result*=value;
			else if(ch=='/') result/=value;
		}
		else break;
		}
		return result;
}
double expression() {
	double result =term();
	
	while(true) {
		char ch=cin.peek();
		ch=cleanspace(ch);
		if(ch=='+'||ch=='-'){
			cin.get(); 
			double value=term();
			if(ch=='+') result+=value;
			else if(ch=='-') result-=value;
		}
		else break;
		}
		return result;

}
int main() {
	cout<<fixed<<setprecision(2)<<expression()<<endl;
	return 0;
}


发表于 2020-03-23 19:02:35 回复(1)
Java

import java.text.DecimalFormat;
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()){
            String s = scanner.nextLine();
            s=s.replace(" ","");
            //中缀表达式转为后缀表达式
            List<String> s1=transform(s);
            //后缀表达式计算求值
            double result= calculate(s1);
            DecimalFormat f = new DecimalFormat("0.00");
            System.out.println(f.format(result));
        }
    }

    private static List<String> transform(String s) {
        Stack<String> stack = new Stack<>();
        ArrayList<String> list = new ArrayList<>();
        for (int i = 0; i < s.length(); i++) {
            String c= String.valueOf(s.charAt(i));
            switch (c){
                //统一 + - 处理
                case "+":
                case "-":
                    while (!stack.empty()) list.add(stack.pop());
                    stack.push(c);
                    break;
                //统一 * / 处理
                case "*":
                case "/":
                    while (!stack.empty()&&(stack.peek().equals("*") || stack.peek().equals("/"))) list.add(stack.pop());
                    stack.push(c);
                    break;
                //0-9 处理
                default:
                    int num= Integer.parseInt(c);
                    while (i<s.length()-1&& Character.isDigit(s.charAt(i+1))){
                        num=num*10+s.charAt(i+1)-'0';
                        i++;
                    }
                    list.add(String.valueOf(num));
            }
        }
        while (!stack.empty())
            list.add(stack.pop());
        return list;
    }
    private static double calculate(List<String> list) {
        Stack<Double> stack = new Stack<>();
        for (String s : list) {
            switch (s) {
                case "+":
                    stack.push(stack.pop() + stack.pop());
                    break;
                case "-":
                    double first = stack.pop();
                    double second = stack.pop();
                    stack.push(second - first);
                    break;
                case "*":
                    stack.push(stack.pop() * stack.pop());
                    break;
                case "/":
                    double first1 = stack.pop();
                    double second1 = stack.pop();
                    stack.push(second1 / first1);
                    break;
                // num
                default:
                    stack.push(Double.parseDouble(s));
            }
        }
        return stack.pop();
    }

}


发表于 2020-03-19 21:57:56 回复(0)
#include<iostream>
#include<string>
#include<stack>
#include<iomanip>
using namespace std;
char str[220];
bool ret;
int pos;
int mag[][5]
{
	1,0,0,0,0,
	1,0,0,0,0,
	1,0,0,0,0,
	1,1,1,0,0,
	1,1,1,0,0,
};
stack<int>op;
stack<double>num;
void get(int& pos, bool& ret, int& i)
{
	if (i == 0 && op.empty() == true)
	{
		ret = true;
		pos = 0;
		return;
	}
	if (str[i] == 0)
	{
		ret = true;
		pos = 0;
		return;
	}
	if (str[i] >= '0' && str[i] <= '9')
	{
		ret = false;
		pos = 0;
		for (; str[i] != ' ' && str[i] != 0; i++)
		{
			pos = pos * 10 + str[i] - '0';
		}
		if (str[i] == ' ')
			i++;
		return;
	}
	else
	{
		ret = true;
		if (str[i] == '+')
		{		
			pos = 1;
		}
		else if (str[i] == '-')
		{			
			pos = 2;			
		}
		else if (str[i] == '*')
		{			
			pos = 3;			
		}
		else if (str[i] == '/')
		{		
			pos = 4;			
		}
		i += 2;
		return;
	}
}
int main()
{
	while (cin.getline(str, 220))
	{
		if (str[0] == '0' && str[1] == 0)break;
		int pos, idx = 0; bool ret;
		while (!op.empty())op.pop();
		while (!num.empty())num.pop();
		while (true)
		{
			get(pos, ret, idx);
			if (ret == false)
				num.push((double)pos);
			else
			{ 
				double temp;
				if (op.empty() == true || mag[pos][op.top()] == 1)
					op.push(pos);
				else
				{
					while (mag[pos][op.top()] == 0)
					{
						int t = op.top();
						op.pop();
						double b = num.top();
						num.pop();
						double a = num.top();
						num.pop();
						switch (t)
						{
						case 1:temp = a + b;
							break;
						case 2:temp = a - b;
							break;
						case 3:temp = a * b;
							break;
						case 4:temp = a / b;
							break;
						default :break;
						}
						num.push(temp);
					}
					op.push(pos);
				}
			}
			if (op.size() == 2 && op.top() == 0)
				break;
		}
		cout <<fixed <<setprecision(2) << num.top() << endl;
	}
	return 0;
}

编辑于 2020-03-11 00:58:37 回复(0)
AC的代码:
#include<stdio.h>
int main(){
char ch;
int tmp;
float S[100];
while(scanf("%d%c",&tmp,&ch)!=EOF){
if(tmp==0 && ch=='\n')break;
S[0]=(float)tmp;
int size=0;
char op;
while(scanf("%c",&op)!=EOF){
float b;

if(op==' ')continue;
if(op=='\n')break;
scanf("%f",&b);
switch (op)
{
case '+':
S[++size]=b ;
break;
case '-':
S[++size]=-b;
break;
case '*':
S[size]*=b;
break;
case '/':
S[size]/=b;
break;
}
}
float sum=0;
for(int k=0;k<=size;k++){
sum+=S[k];
}
printf("%.2f\n",sum);
/* code */
}

}

发表于 2019-04-10 12:12:49 回复(0)

这不是最好的写法,但是让想到了编译原理的递归下降分析,纯c写得比较繁琐见谅

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

double parseExpression();
double parseTerm();
double parseFactor();

double parseExpression() {
  double left=parseTerm();
  char op, c;
  while((op=getchar())==' ');
  if(op=='+'||op=='-') {
    while(op=='+'||op=='-') {
      while((c=getchar())==' '); ungetc(c, stdin);
      double right=parseTerm();
      if(op=='+') left+=right;
      else left-=right;
      while((op=getchar())==' ');
    }
  }
  return left;
}

double parseTerm() {
  double left=parseFactor();
  char op, c;
  while((op=getchar())==' ');
  if(op=='*'||op=='/') {
    while(op=='*'||op=='/') {
      while((c=getchar())==' '); ungetc(c, stdin);
      double right=parseFactor();
      if(op=='*') left*=right;
      else left/=right;
      while((op=getchar())==' ');
    }
  }
  ungetc(op, stdin);
  return left;
}

double parseFactor() {
  int x;
  scanf("%d", &x);
  return (double)x;
}

int main()
{
  char c;
  while((c=getchar())!=EOF) {
    if(c=='0') break;   /* this is cursory though */
    else {
      ungetc(c, stdin);
      printf("%.2f\n", parseExpression());
    }
  }

  return 0;
}
发表于 2018-03-11 22:04:43 回复(0)
#include<stdio.h>
int main(){
    int tmp;
    char ch;
    while(scanf("%d%c",&tmp,&ch)!=EOF){
        if(tmp==0&&ch=='\n')    continue;
        double ans[210]={0},sum=0;
        ans[0]=tmp;
        int size=0;    
        while(scanf("%c",&ch)!=EOF){
            scanf("%d",&tmp);        
            switch(ch){
                case '+':ans[++size]=tmp;break;
                case '-':ans[++size]=-tmp;break;
                case '*':ans[size]*=tmp;break;
                case '/':ans[size]/=tmp;break;
            }
            getchar();
        }
        for(int i=0;i<=size;i++)
            sum+=ans[i];
        printf("%.2lf\n",sum);
    }
}

发表于 2018-02-25 13:27:29 回复(14)

python3的解法如下,非常简单





while True:
    try:
        a=input()
        if a!="0":
            print("{0:.2f}".format(eval(a)))
    except:
        break
发表于 2017-10-06 21:25:55 回复(10)
考察的是栈的基本应用
#include <stdio.h>
#include <string.h>
#include <stack>
#define N 300
using namespace std;
stack<char> op;//栈,存储运算符
stack<double> data;//栈,存储数据
char str[N];//用来存用户输入的字符串

void Clear()//清空数据栈和运算符栈
{
    while(!op.empty()) op.pop();
    while(!data.empty()) data.pop();
}

int Priority(char c)//判断运算符优先级
{
    if(c=='+' || c=='-') return 1;
    else if(c=='*' || c=='/') return 2;
    else return 0;//如果是'#'则优先级为0
}

void GetNum(int &x, int &i)//读取字符串中的数字,x为数值,i为字符串下标
{
    x=0;
    while(str[i]!=' '&&str[i]!='\0')
    {
        x=x*10+(str[i]-'0');
        i++;
    }
    if(str[i]==' ') i++;
}

void CalOnce()
{//取两个数、一个运算符,运算结果存入data栈
    if(data.size()<2) return;//没那么多数就别算了(貌似用不到?)
    double b=data.top();
    data.pop();
    double a=data.top();
    data.pop();
    switch(op.top())
    {
        case '+': data.push(a+b); break;
        case '-': data.push(a-b); break;
        case '*': data.push(a*b); break;
        case '/': data.push(a/b); break;
    }
    op.pop();
    return;
}

void Calculate()
{//根据字符串进行运算,并输出结果
    int x, i=0;//从头开始分析字符串
    int len=strlen(str);
    Clear();//清空运算符栈和数据栈
    op.push('#');//#用来标记开始,其优先级为0
    while(i<len)
    {
        if('0'<=str[i]&&str[i]<='9')//碰到数字直接压入数据栈
        {
            GetNum(x, i);
            data.push((double)x);
        }
        else//碰到了运算符的话
        {
            if(Priority(str[i])>Priority(op.top())) op.push(str[i]);
            //优先级较高就直接压入运算符栈
            else{//优先级不高于栈顶运算符的话
                while(Priority(str[i])<=Priority(op.top()))
                {//不停运算直到可以压入
                    CalOnce();
                }
                op.push(str[i]);//压入运算符
            }
            i+=2;//跳过这个运算符顺便跳过空格
        }
    }
    while(Priority(op.top())!=0) CalOnce();
    //最后输入的数没处理,处理一下,假装输入了一个优先级很低的运算符
   printf("%.2lf\n", data.top());//输出结果
}

int main()
{
    while(gets(str))
    {
        if(strcmp("0", str)==0) break;
        Calculate();//计算并输出结果
    }
    return 0;
}

编辑于 2018-03-03 12:23:49 回复(3)
//参考楼上@苏合杭写的C++版本,注意cin和scanf的区别
#include<iostream>
using namespace std;
const int maxn=201;
int main()
{
    double temp,ans[maxn];
    char ch;
    while(cin>>temp&&temp)
    {
        int num=0;
        double sum=0;
        ans[num]=temp;
        while(cin>>ch>>temp)
        {
            switch(ch)
            {
            case '+':ans[++num]=temp;
                break;
            case '-':ans[++num]=-temp;
                break;
            case '*':ans[num]*=temp;
                break;
            case '/':ans[num]/=temp;
                break;
            }
            char c=cin.get();
            if(c=='\n')
                break;
        }
        for(int i=0;i<=num;i++)
            sum+=ans[i];
        printf("%0.2f\n",sum);
    }
    return 0;
}

发表于 2018-03-18 12:07:25 回复(5)
借鉴后缀表达式求值
#include<iostream>
using namespace std;
#include<string>
#include<vector>
#include<stack>
#include<iomanip>
/*读入一个只包含 +, -, *, / 的 非负整数 计算表达式,计算该表达式的值*/

int precedence(char op)//计算运算符优先级
{
	switch (op)
	{
	case '*':
	case '/':
		return 2; 
	case '+':
	case '-':
		return 1;
	case '@':
	default:
		return 0;
	}
}

void cal(char temp,stack<double> &num)
{
	double x = 0;
	switch (temp)
	{
	case '+':
	{
		x = num.top(); num.pop();
		x += num.top(); num.pop();
		num.push(x);
		break;
	}
	case '-':
	{
		x = num.top(); num.pop();
		x = num.top() - x; num.pop();
		num.push(x);
		break;
	}
	case '*':
	{
		x = num.top(); num.pop();
		x *= num.top(); num.pop();
		num.push(x);
		break;
	}
	case '/':
	{
		x = num.top(); num.pop();
		if (x == 0)
		{
			cout << "除数为零" << endl;
			exit(1);
		}
		else
		{
			x = num.top() / x; num.pop();
			num.push(x);
		}
		break;
	}
	default:
		break;
	}
}

double calculateValue(string str)
{
	stack<char> op;
	stack<double> num;
	op.push('@');
	char ch;
	int i = 0;
	while (i!=str.size())
	{
		ch = str[i];
		if (ch == ' ')
		{
			i++;
			continue;
		}
		else if(ch == '+' || ch == '-' || ch == '*' || ch == '/')
		{
			char temp = op.top();
			while (precedence(ch) <= precedence(temp))
			{
				cal(temp, num);
				op.pop();
				temp = op.top();
			}
			op.push(ch);
			i++;
		}
		else//数字
		{
			int y = 0;
			while (str[i] >= '0' && str[i] <= '9')
			{
				y = y * 10 + str[i] - '0';
				i++;
			}
			num.push(y);
		}
	}
	while (op.top() != '@')
	{
		cal(op.top(), num);
		op.pop();
	}
	return num.top();
}
int main()
{
	vector<string> expression;
	string str;
	while (getline(cin,str))
	{
		if (str == "0")
			break;
		expression.push_back(str);
	}
	for (int i = 0; i < expression.size(); i++)
		cout << setiosflags(ios::fixed)<<setprecision(2)
			<<calculateValue(expression[i]) << endl;
	return 0;
}

编辑于 2020-04-20 22:23:16 回复(0)
#include <stdio.h>
#include <string.h>
#define MAX 205

/*
这道题目主要采用栈来求解
为了锻炼使用语言解决问题的能力,这里通过数组来模拟栈
*/
struct Node
{
    double num;
    char op;
    int flag;
};

struct Node Stack[MAX];//符号栈
struct Node Queue[MAX];//用来存放后缀表达式
char str1[MAX];
char str2[MAX];
int op[256];

//将中缀表达式转化为后缀表达式
int Change(int length)
{
    double num;
    struct Node temp;
    int i;
    int cnt=0;
    int top=0;
    for(i=0;i<length;)
    {
        //如果是操作数
        if(str2[i]>='0'&&str2[i]<='9')
        {
            temp.flag=1;
            temp.num=0;
            while(str2[i]!='\0'&&str2[i]>='0'&&str2[i]<='9')
            {
                temp.num=temp.num*10+str2[i]-'0';
                i++;
            }
            Queue[cnt++]=temp;
        }
        //如果是运算符,则需要先比较运算符与当前栈顶符号的优先级
        //如果栈顶符号优先级更高,则要加入到队列数组当中
        //如果优先级较低的话,则将符号压入到符号栈当中
        else
        {
            temp.flag=0;
            while(top!=0&&op[str2[i]]<=op[Stack[top-1].op])//这里注意栈顶指针等于栈顶位置+1
            {
                Queue[cnt++]=Stack[--top];
            }
            temp.op=str2[i];
            Stack[top++]=temp;
            i++;
        }
    }
    while(top!=0)//清空栈,构造完整的后缀表达式
    {
        Queue[cnt++]=Stack[--top];
    }
    return cnt;
}

double Cal(int cnt)//计算后缀表达式
{
    double temp1,temp2;
    struct Node cur,temp;
    int top=0;
    int i,j;
    for(i=0;i<cnt;i++)
    {
        cur=Queue[i];
        if(cur.flag==1) Stack[top++]=cur;
        else
        {
            //特别注意top必须加入前缀--,因为top指针总是等于栈顶元素位置+1
            temp2=Stack[--top].num;//操作数2
            temp1=Stack[--top].num;//操作数1
            temp.flag=1;
            if(cur.op=='+') temp.num=temp1+temp2;
            else if(cur.op=='-') temp.num=temp1-temp2;
            else if(cur.op=='*') temp.num=temp1*temp2;
            else temp.num=temp1/temp2;
            Stack[top++]=temp;
        }
    }
    return Stack[top-1].num;
}

int main()
{
    op['+']=op['-']=1;
    op['*']=op['/']=2;
    while(fgets(str1,205,stdin)&&strcmp(str1,"0\n")!=0)
    {
        int len=strlen(str1);
        int i,j=0;
        for(i=0;i<len;i++)
        {
            if(str1[i]==' '||str1[i]=='\n') continue;
            else str2[j++]=str1[i];
        }
        str2[j]='\0';
        int cnt=Change(j);
        printf("%.2f\n",Cal(cnt));
    }
    return 0;
}

发表于 2018-09-05 06:50:57 回复(0)
提交通过后发现有个错误,那就是输入单独一个非零数时也会直接退出,不过好像没有这样的测试案例。要改也容易,加个判断就行。
#include<stdio.h>
#include<string.h>
int main(){
    double a[200],tem;
    char ch;
    while(scanf("%lf%c",&tem,&ch)!=EOF){ 
        a[0]=tem;
        int size=1;
        if(tem!=0&&ch=='\n'){printf("%0.2f\n",tem);continue;}//当只输入一个非零数时保证不退出
        if(tem==0&&ch=='\n')break;
        do{
            scanf("%c %lf",&ch,&tem);
            if(ch=='+')a[size++]=tem;
            if(ch=='-')a[size++]=-tem;
            if(ch=='*')a[size-1]=a[size-1]*tem;
            if(ch=='/')a[size-1]=a[size-1]/tem;
        } while(scanf("%c",&ch)!=EOF&&ch!='\n');
        double sum=0;
        for(int i=0;i<size;i++)
            sum+=a[i];    
        printf("%0.2f\n",sum);
    }
}

编辑于 2018-02-23 11:56:40 回复(0)

很服这种题,答案32.625精确之后竟然32.62
但是其他测试用例如果后面是5的话,却又进位,纠结死了

发表于 2018-01-06 23:54:51 回复(0)
#include <stdio.h>
#include <string.h>

int main(){
    char s[200];
    int i,j,len;
    float sum,tmp;
    while(gets(s)){
        if(!strcmp(s,"0")) break;
        len = strlen(s);
        float a[201]={0};
        tmp=0;
        i=0;
        while(s[i]>='0'&&s[i]<='9'){
                    tmp*=10;
                    tmp+=s[i]-'0';
                    i++;
        }        
        a[0]=tmp;
        for(j=0;i<len;i++){
            if(s[i]=='+'){
                tmp=0;
                i+=2;
                while(s[i]>='0'&&s[i]<='9'){
                    tmp*=10;
                    tmp+=s[i]-'0';
                    i++;
                }
                 a[++j]=tmp;
            }
            else if(s[i]=='-'){
                tmp=0;
                i+=2;
                while(s[i]>='0'&&s[i]<='9'){
                    tmp*=10;
                    tmp+=s[i]-'0';
                    i++;
                }
                 a[++j]=-tmp;                
            } 
            else if(s[i]=='*') {
                tmp=0;
                i+=2;
                while(s[i]>='0'&&s[i]<='9'){
                    tmp*=10;
                    tmp+=s[i]-'0';
                    i++;
                }                               
                a[j]*=tmp;
            }
            else if(s[i]=='/') {
                tmp=0;
                i+=2;
                while(s[i]>='0'&&s[i]<='9'){
                    tmp*=10;
                    tmp+=s[i]-'0';
                    i++;
                }                               
                a[j]/=tmp;              
            }
        }
        for(i=0,sum=0;i<=j;i++) sum+=a[i];
        printf("%.2f\n",sum);
    }
}

尝试没用栈实现๑乛◡乛๑
发表于 2021-02-03 21:24:18 回复(1)
在什么时候进栈的地方有难度
#include <iostream>
#include <stack>
#include <cstdio>
#include <cctype>
#include <string>
using namespace std;

int pri (char ch){//返回字符优先级
    int p=-1;
    if(ch=='#')
        p=0;
    else if(ch=='$')
        p=1;
    else if(ch=='+'||ch=='-')
        p=2;
    else
        p=3;
    return p;
}

double getNumber(string s, int& index){//返回字符串当前下标到下一个空格间的数字
    double ans=0;
    while(isdigit(s[index])){
        ans*=10;
        ans+=s[index]-'0';
        index++;
    }
    return ans;
}

double cal (double x, double y, char ch){//返回字符优先级
    double result=0;
    if(ch=='+')
        result=x+y;
    else if(ch=='-')
        result=x-y;
    else if(ch=='*')
        result=x*y;
    else if(ch=='/')
        result=x/y;
    return result;
}
       
int main(){
    string str;
    while(getline(cin,str,'\n') && str!="0"){
        
        int index=0;
        stack<double>num;
        stack<char>op;
        str+='$';
        op.push('#');
        while(index<str.length()){
            if(str[index]==' '){
                index++;
            }
            else if(isdigit(str[index])){
                num.push(getNumber(str, index));
            }
            else{
                if(pri(str[index])>pri(op.top())){//如果当前字符比栈顶字符的优先级高,则进栈
                    op.push(str[index]);
                    index++;
                }
                else{//如果当前字符比栈顶字符的优先级低,则计算栈里的
                    //数字的顺序别弄反了
                    double y = num.top();
                    num.pop();
                    double x = num.top();
                    num.pop();
                    char ch = op.top();
                    num.push(cal(x,y,ch));//结果再放入栈
                    op.pop();
                }
            }
        }
        printf("%.2f\n",num.top());
    }
    return 0;
}


发表于 2020-01-30 15:22:32 回复(0)
其实可以不使用栈, 大体思路是保持当前项的值和之前所有项的和。每次读一个操作符和数字。
如果是乘除,更新当前项的值,加减就将当前项的值加到和上,重置当前项为读进来的数。
灵感来自@苏合杭
#include <cstdio>
 
 int main(){
     double term = 0;
     char ch;
     while(scanf("%lf%c", &term, &ch) != EOF){
         double result = 0;
         if(term == 0.0 && ch == '\n') return 0;
         while(scanf("%c", &ch) != EOF){
             printf("op is %c\n", ch);
             int temp; scanf(" %d", &temp);
 
             switch(ch) {
                 case '+': {
                     result += term;
                     term = temp;
                     break;
                 }
                 case '-': {
                     result += term;
                     term = -temp;
                     break;
                 }
                 case '*': {
                     term *= temp;
                     break;
                 }
                 case '/': {
                     term /= temp;
                     break;
                 }
                 default: {
                     printf("*** up!\n");
                 }
             }
             char space = getchar();
             if(space == '\n') break;
         }
         printf("%.2lf\n", term + result); //最后一项和之前所有项的和。
     }
     
}

发表于 2018-09-05 16:32:11 回复(2)
#include <cstdio>
#include <string>
#include <stack>
#include <map>

using namespace std;

//表达式求值 
int main() {
	char buf[300];
	//优先级 
	map<char, int> priority = {
		{'$', 0},
		{'+', 1},{'-', 1},
		{'*', 2},{'/', 2}
	};
	
	while (fgets(buf, 300, stdin) != NULL) {
		string expr = buf;
		expr.pop_back();	//将末尾的换行符弹出
		
		if (expr == "0") {	//为 0 则结束 
			break;
		} 
		expr.push_back('$');//补充一个虚拟的终止符
		
		string num;			//用来收集单独的0-9以组成数字:1 2 3 4 ——> 1234
		stack<double> numstack;
		stack<char> operstack;
		
		for (int i = 0; i < expr.size(); i++) {
			if (expr[i] >= '0' && expr[i] <= '9') {
				num.push_back(expr[i]);
			}
			//如果是空格,说明数字拼好了 
			else if (expr[i] == ' ') {
				if (num != "") {
					//stod --> string to double
					numstack.push(stod(num));
					//将num重新设置为空 
					num = "";
				} 
			}
			// + - * / $
			else {
				if (expr[i] == '$') {
					if (num != "") {
					numstack.push(stod(num));
					num = "";
					} 
				}
				
				//当符号栈非空 && 栈内优先级 >= 当前符号优先级时 
				while (!operstack.empty() && priority[operstack.top()] >=  priority[expr[i]]) {
					double right = numstack.top();	//右操作数 
					numstack.pop();
					double left = numstack.top();	//左操作数 
					numstack.pop();
					char oper = operstack.top();	//运算符 
					operstack.pop();
					
					switch (oper) {
						case '+':
							numstack.push(left + right);
							break;
						case '-':
							numstack.push(left - right);
							break;
						case '*':
							numstack.push(left * right);
							break;
						case '/':
							numstack.push(left / right);
							break;
					} 
				}
				//所有比expr[i]优先级更高的运算符都计算过了 
				
				operstack.push(expr[i]); 
			} 
		}
		//输出最终结果 
		printf("%.2lf\n", numstack.top()); 
	}
}

发表于 2023-03-23 15:40:43 回复(0)
0/20组用例通过,提示段错误,但提示那个例子明明可以通过,实际输出和预期输出一样却显示错误。
发表于 2023-02-27 12:36:47 回复(1)