输入:通过 ”命令行参数“输入一个数学表达式。
输出:(1)表达式正确的情况下输出结果;(2)命令行参数不正确输出字符串ERROR_01;
(3)表达式存在格式错误输出字符串ERROR_02;(4)表达式在计算过程中出现逻辑错误输出字符串ERROR_03。
简明示例:
输入:(2+3)(3-1)^3 输出:40; 输入:((2+3)(3-1)^3输出:ERROR_02
注:1)数学表达式需支持小数、加减乘除、小括号、中括号、幂运算。为简化逻辑,不需要考虑负数情况。
2)不正确的表达式可能包括:字母、非运算符号、括号不匹配,运算符的排列不符合表达式形式等多种情况。
3)输出结果中有几位小数就输出几位小数。
4)表达式通过命令行参数读取 。
序号 表达式 结果 设计意图
1 1+2+3+4 10 加法测试
2 10-8-7-6 -13 减法测试
3 1234 24 乘法测试
4 8/2/2/2 1 除法测试
5 3^2+4^22 41 幂运算测试
6 (3+2)2/(4-1+2) 2 括号及优先级测试
7 1+[2-(34)] -9 括号及优先级测试
8 12345679*9 111111111 超长数字测试
9 3/5 0.6 结果为小数
10 3/0.6 5 输入为小数
11 (3-2)) ERROR_02 异常情况
12 (1++3) ERROR_02 异常情况
13 2/(5-5) ERROR_03 异常情况
要求:
1、实现栈的push、pop基本操作;
2、检测表达式的输入是否是正确的数学表达式;
3、对于正确的数学表达式求取其值。
题主可以看看这个,他的代码有问题,我给修改了下,主要功能都有,其他的可能需要你自己研究下了
https://ask.csdn.net/questions/7451896
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define INIT_STRING_SIZE 100
#define True 1
#define False 0
int saved_class[4] = {0, 0, 0, 0};
typedef struct aNum
{
double data;
char oper;
int dataClass;
int power;
struct aNum *next;
} num;
typedef struct
{
char *formula;
int length;
} string;
void setNULL(char *num) //清空一个字符串
{
int i = 0;
while (i < 5)
{
num[i] = NULL;
++i;
}
}
int countOperators(string *input, int *counter) // processing step 1
{ //计算运算符个数
int i = 0;
while (input->formula[i] != '\0')
{
switch (input->formula[i++])
{
case '+':
case '-':
case '*':
case '/':
++counter;
break;
default:
break;
}
++input->length;
}
return 1;
}
int getData(string *input, num *nums) // processing step 2
{ //把数字,符号和class存入nums的结构体
int i = 0; // counter of input->formula
int k = 0; // counter of temp;
int power = 0;
char temp[5];
int inBracket = False;
num *p = nums;
num *body;
while (i <= input->length)
{
if ((input->formula[i] < '0' || input->formula[i] > '9') && input->formula[i] != '.' && input->formula[i] != '^')
{ //进入此处时数据已经收集完毕
if (input->formula[i] == '(')
{
inBracket = True;
++i;
continue;
}
if (input->formula[i] == ')')
{
inBracket = False;
++i;
continue;
}
body = (num *)calloc(1, sizeof(num));
body->data = atof(temp); //得到数字
setNULL(temp); //归零temp
k = 0;
switch (input->formula[i])
{
case '+':
body->dataClass = inBracket == False ? 1 : 3; //计算当前运算符的等级
++saved_class[body->dataClass - 1]; //在等级数组里记录一次
body->oper = input->formula[i]; //得到运算符
break;
case '-':
body->dataClass = inBracket == False ? 1 : 3;
++saved_class[body->dataClass - 1];
body->oper = input->formula[i];
break;
case 'x':
case '*':
body->dataClass = inBracket == False ? 2 : 4;
++saved_class[body->dataClass - 1];
body->oper = input->formula[i];
break;
case '/':
body->dataClass = inBracket == False ? 2 : 4;
++saved_class[body->dataClass - 1];
body->oper = input->formula[i];
break;
default:
break;
}
if (power != 0)
{
body->power = power;
power = 0;
}
p->next = body;
p = p->next;
}
else if (input->formula[i] == '^')
{
power = input->formula[++i] - 48;
}
else
{
temp[k++] = input->formula[i];
}
++i;
}
return 1;
}
double compute(double num1, double num2, char opt)
{ //每次运算单独提取
double result;
switch (opt)
{
case '-':
result = num1 - num2;
break;
case '+':
result = num1 + num2;
break;
case 'x':
case '*':
result = num1 * num2;
break;
case '/':
result = num1 / num2;
break;
}
return result;
}
int processingData(num *nums) // processing step 3
{ // nums作为头结点是没有数据的
int s = 3; // saved_class
int i = 0;
num *p = nums;
num *p_front;
while (saved_class[s] == 0 && s > 0)
--s;
while (p->next->next != NULL) // class oper next 都可以
{
if (p->next->dataClass != s + 1)
{
p = p->next;
continue;
}
p_front = p;
p = p->next; // p此时指向待计算的第一个struct aNUm
if (p->power != 0)
{
p->data = pow(p->data, p->power);
p->power = 0;
}
if (p->next->power != 0)
{
p->next->data = pow(p->next->data, p->next->power);
p->next->power = 0;
}
p->next->data = compute(p->data, p->next->data, p->oper);
p_front->next = p->next;
free(p);
--saved_class[s];
while (saved_class[s] == 0 && s != 0)
--s;
p = nums;
}
if (nums->next->power != 0) //处理单个数字输入的情况,比如2^2
{
nums->next->data = pow(nums->next->data, nums->next->power);
}
printf("result=%lf\n", nums->next->data);
return 1;
}
int main()
{
int *counter = 0;
num *nums = NULL;
string *input;
input = (string *)calloc(1, sizeof(string));
input->formula = (char *)calloc(INIT_STRING_SIZE, sizeof(string));
puts("Input formula:");
scanf("%s", input->formula);
//得到运算符和运算符个数
countOperators(input, counter);
//根据运算符个数申请存储数字的空间
nums = (num *)calloc(1, sizeof(num));
//存储数字和运算符
getData(input, nums);
processingData(nums);
free(input->formula);
free(input);
free(nums->next);
free(nums);
system("pause"); //如果你是linux或者macos,可能需要去掉这句
return 0;
}
考研考不到这么难,搞懂四则的求法就可以了
可以考虑参考一下以下代码的思路:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<stack>
#include<algorithm>
using namespace std;
string str;
int que[10000], len = 0;
int prior[300];
stack<char>sta;
int calus(int a, int b, char s)
{
return s == '+' ? a + b : s == '-' ? a - b : s == '*' ? a * b : a / b;
}
int main()
{
cout << "Input" << endl;
prior['+'] = 1;
prior['-'] = 1;
prior['*'] = 2;
prior['/'] = 2;
while (sta.size() > 0)sta.pop();
cin >> str;
str = "(" + str + ")";
for (int i = 0; i < str.length(); i++)
{
if (str[i] >= '0'&&str[i] <= '9')
{
int number = str[i] - '0';
while (str[i + 1] >= '0'&&str[i + 1] <= '9') number = number * 10 + str[++i] - '0';
que[len++] = number;
}
else
{
if (str[i] == '(') sta.push(str[i]);
else if (str[i] == ')')
{
while (sta.top() != '(')
{
len--;
que[len - 1] = calus(que[len - 1], que[len], sta.top());
sta.pop();
}
sta.pop();
}
else
{
while (!sta.empty() && sta.top() != '('&&prior[sta.top()] >= prior[str[i]])
{
len--;
que[len - 1] = calus(que[len - 1], que[len], sta.top());
sta.pop();
}
sta.push(str[i]);
}
}
}
cout << "Output"<<endl;
cout << que[--len] << endl;
cout << "End" << endl;
// }
return 0;
}
文章链接:https://blog.csdn.net/Janchee/article/details/109532877
符合题目的要求加自测如下,实现栈操作和表达式求值。还有一些细节可以自己改改,下面是题目的测试,注意没有处理中间空格情况,所以输入不能有空格,要输入的话稍微过滤一下就行了
测试case 1:
1+2 *3
7
测试case 2:
1+2^3
9
测试case 3:
1+2/0.5
5.000000
测试case 4:
(2+3) *(3-1)^3
40
测试case 5:
(1+2
error_300
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define MAX_SIZE 100
#define EXP_DATA_INVALID 0
#define EXP_DATA_DOUBLE 1
#define EXP_DATA_INT 2
#define EXP_DATA_OP 3
char legel_letter[] = "1234567890.[]()+-*/^ ";
char legel_op[] = "[(+-*/^";
typedef struct _exp_data {
union {
double d_d;
int i_d;
char op;
} u;
int type;
} exp_data;
typedef struct _stack {
exp_data *data;
int top;
int size;
} stack;
void init(stack *s)
{
s->data = (exp_data *)malloc(sizeof(exp_data) * MAX_SIZE);
s->size = MAX_SIZE;
s->top = -1;
}
int empty(stack *s)
{
return s->top == -1;
}
exp_data top(stack *s)
{
exp_data invalid;
invalid.type = EXP_DATA_INVALID;
if (empty(s))
return invalid;
return s->data[s->top];
}
int push(stack *s, exp_data val)
{
if (s == NULL || s->top + 1 == s->size)
return 0;
s->top += 1;
s->data[s->top] = val;
return 1;
}
int pop(stack *s)
{
if (s == NULL || empty(s))
return 0;
s->top -= 1;
return 1;
}
int judge_oper(char *str, char letter)
{
char sub[1] = {0};
char *p;
sub[0] = letter;
sub[1] = '\0';
if(( p = strstr(str, sub)) == NULL) return 0;
else return 1;
}
int get_op_number(char *str, exp_data *val)
{
int i = 0;
int flag_d_d = 0;
char d_d_i[100] = {0};
for (; (str[i]>= '0' && str[i] <= '9') || str[i] == '.'; i++) {
if (str[i] == '.') flag_d_d = 1;
d_d_i[i] = str[i];
}
if (i > 0) {
if (flag_d_d) {
val->u.d_d = strtod (d_d_i, NULL);
val->type = EXP_DATA_DOUBLE;
} else {
val->u.i_d = strtod (d_d_i, NULL);
val->type = EXP_DATA_INT;
}
}
return i;
}
void do_op_number(stack *s, exp_data val)
{
exp_data top_1;
exp_data top_2;
char op;
int flag_d_oper1 = 0;
int flag_d_oper2 = 0;
double d_d;
if(empty(s)) {push(s, val); return;}
top_1 = top(s);
if (top_1.type != EXP_DATA_OP) { printf("error_1\n"); return; }
op = top_1.u.op;
if (op == '(' || op == '[') { push(s, val); return;}
pop(s);
top_2 = top(s);
if (top_2.type == EXP_DATA_INVALID || top_2.type == EXP_DATA_OP) { printf("error_1\n"); return;}
pop(s);
if (top_2.type == EXP_DATA_DOUBLE) flag_d_oper2 = 1;
if (val.type == EXP_DATA_DOUBLE) flag_d_oper1 = 1;
switch(op) {
case '+':
d_d = (flag_d_oper2 ? top_2.u.d_d : top_2.u.i_d) + (flag_d_oper1?val.u.d_d : val.u.i_d);
break;
case '-':
d_d = (flag_d_oper2 ? top_2.u.d_d : top_2.u.i_d) - (flag_d_oper1?val.u.d_d : val.u.i_d);
break;
case '*':
d_d = (flag_d_oper2 ? top_2.u.d_d : top_2.u.i_d) * (flag_d_oper1?val.u.d_d : val.u.i_d);
break;
case '/':
if ((flag_d_oper1?val.u.d_d : val.u.i_d) == 0) { printf("error_3\n"); return;}
d_d = (flag_d_oper2 ? top_2.u.d_d : top_2.u.i_d) / (flag_d_oper1?val.u.d_d : val.u.i_d);
break;
case '^':
d_d = pow((flag_d_oper2 ? top_2.u.d_d : top_2.u.i_d) , (flag_d_oper1?val.u.d_d : val.u.i_d));
break;
}
if(flag_d_oper1 || flag_d_oper2) {
val.type = EXP_DATA_DOUBLE;
val.u.d_d = d_d;
push(s, val);
} else {
val.type = EXP_DATA_INT;
val.u.i_d = (int)d_d;
push(s, val);
}
}
void do_op_brackets(stack *s, char letter)
{
exp_data top_1;
exp_data top_2;
top_1 = top(s);
pop(s);
//do (1+2)
do_op_number(s, top_1);
//do remove (1) and restore 1 to stack
top_1 = top(s);
pop(s);
top_2 = top(s);
pop(s);
push(s, top_1);
if ( letter == ')' ) {
if (top_2.type != EXP_DATA_OP || top_2.u.op != '(') {
printf("error_3\n");
return ;
}
}
if ( letter == ']' ) {
if (top_2.type != EXP_DATA_OP || top_2.u.op != '[') {
printf("error_3\n");
return ;
}
}
}
int need_compute(char cur_op, char pre_op)
{
//if (pre_op == '(' || pre_op == '[') return 0;
if (cur_op == '+' || cur_op == '-') return 1;
if (cur_op == '*' || cur_op == '/') {
if (pre_op == '+' || pre_op == '-') return 0;
else return 1;
}
if (cur_op == '^') return 0;
return 1;
}
void do_push_op_brackets(stack *s, char letter)
{
exp_data val;
val.type = EXP_DATA_OP;
val.u.op = letter;
exp_data top_1, top_2, top_3;
if (empty(s) || letter == '(' || letter == '[' || letter == '^') {
if (push(s, val) == 0) { printf("push brackets error\n"); }
return;
}
while(!empty(s)) {
top_1 = top(s);
pop(s);
if(empty(s)) { push(s, top_1); push(s, val); return;}
top_2 = top(s);
if(top_2.type == EXP_DATA_OP && (top_2.u.op == '(' || top_2.u.op == '[')) {
push(s, top_1); push(s, val); return;
}
pop(s);
if(empty(s)) { push(s, top_2); push(s, top_1); push(s, val); return;}
top_3 = top(s);
pop(s);
if (top_2.type != EXP_DATA_OP) { printf("error_3\n"); return; }
if (need_compute(letter, top_2.u.op)) {
push(s, top_3); push(s, top_2);
do_op_number(s, top_1);
} else {
push(s, top_3); push(s, top_2); push(s, top_1);
push(s, val);
return;
}
}
push(s, val);
}
void do_compute(char *exp)
{
stack s;
exp_data val;
int i = 0, jump = 0;
char letter;
init(&s);
letter = exp[i];
while(letter != '\0') {
if (judge_oper(legel_letter, letter) == 0) { printf("error_0\n"); break;}
if (judge_oper(legel_op, letter)) { do_push_op_brackets(&s, letter); }
if (letter == ')' || letter == ']') { do_op_brackets(&s, letter); }
if (letter == '.' && (i == 0 || exp[i-1] > '9' || exp[i-1] < '0')) {printf("error_00\n"); break;}
if ((letter >= '0' && letter <= '9') || letter == '.') {
jump = get_op_number(&exp[i], &val);
if (!jump) { printf("error_000\n"); break;}
push(&s, val);
i+=jump;
jump = 0;
} else i++;
letter = exp[i];
}
if(empty(&s)) { printf("error_30\n"); goto err; }
exp_data top_1, top_2;
while(!empty(&s) && s.top >= 2) {
top_1 = top(&s);
pop(&s);
do_op_number(&s, top_1);
}
//do last result
top_1 = top(&s);
pop(&s);
if (!empty(&s)) { printf("error_300\n"); goto err; }
if (top_1.type == EXP_DATA_OP) printf("error_3000\n");
else {
if (top_1.type == EXP_DATA_DOUBLE) printf("%lf\n", top_1.u.d_d);
else printf("%d\n", top_1.u.i_d);
}
err:
if (s.data) free(s.data);
}
int main()
{
char exp[100];
scanf("%s", exp);
do_compute(exp);
return 0;
}
#include "stdio.h"
int n,i; /* 请注意这里的n与i设置为全局变量的用意 */
float val[100]; /* 这个数组用来收集字符流中的数 */
char c[1000],fu[100]; /* c数组是字符流,而fu数组用来收集计算符号+-* /和{、}*/
float digui()
{
float he=0,ji=0; /* he代表加减运算结果,ji代表乘除运算结果 */
char hefu='+'; /* 每次进入递归是,都要把标示符he设置为0,hefu设置为+。但那个标示符ji可以不用设置 */
for( ;fu[i]!='}'&&fu[i]!='=';i++)
{
switch(fu[i])
{
case '{':
i++;
digui(); // 如果遇到圆括号,则优先计算圆括号里面的内容
break;
case '+':
if(hefu=='+') {val[n] = he + val[n];he = val[n];}
else {val[n] = he - val[n],he = val[n];} // 如果+、-后面的符号依然是加减,则可以进行计算
hefu = '+';
n++;
break;
case '-':
if(hefu=='+') {val[n] = he + val[n];he = val[n];}
else {val[n] = he - val[n];he = val[n];} // 同上
hefu = '-';
n++;
break;
case '*': // 如果遇到优先级高一级的乘符号【或除符号】,则进入循环,直至遇到非乘除符号时推出
{
ji=val[n]; // ji在这里被设置
while(1)
{
if(fu[i] == '*')
{
if(fu[i+1] == '{') // 如果在乘除循环里遇到圆括号,则递归调用自身,就是优先计算圆括号里面的内容
{
i+=2;n++;
ji = ji * digui();
}
else
{
ji = ji*val[n+1];
i++;n++;
}
}
else if(fu[i] == '/')
{
if(fu[i+1] == '{')
{
i+=2;n++;
ji = ji / digui();
}
else
{
ji = ji/val[n+1];
i++;n++;
}
}
else break; // 遇到非乘除符号,退出
}
val[n] = ji; // 乘除循环结束,把n现在指向的数设置成循环计算的结果数,以便它以后可以与he计算,最后得出前面所有数的运算结果
if(fu[i]=='+'||fu[i]=='-')
i--;
break;
}
case '/': //这个与上面那个case里面的作用一样
{
ji = val[n];
while(1)
{
if(fu[i] == '*')
{
if(fu[i+1] == '{')
{
i+=2;n++;
ji = ji * digui();
}
else
{
ji = ji*val[n+1];
i++;n++;
}
}
if(fu[i] == '/')
{
if(fu[i+1] == '{')
{
i+=2;n++;
ji = ji / digui();
}
else
{
ji = ji/val[n+1];
i++;n++;
}
}
else break;
}
}
val[n] = ji;
if(fu[i]=='+'||fu[i]=='-')
i--;
break;
}
}
if(hefu == '+') val[n] = he + val[n]; // 到这里就是到了一个递归的结束,然后根据hefu的状态决定进行+运算或-运算
else val[n] = he - val[n];
return val[n]; // 最后我们需要返回这个值
}
void main()
{
int a=0,j=0;float b=0,d=0,g=10;;
gets(c);
for(i=0;c[i]!=0&&i<1000;i++)
{
if(c[i]>='0'&&c[i]<='9')
{
while(c[i]>='0'&&c[i]<='9')
{
b=(c[i]-'0')+b*10;
i++;
}
if(c[i]=='.')
{
i++;
while(c[i]>='0'&&c[i]<='9')
{
d=d+(c[i]-'0')/g;
g*=10;
i++;
}
} // 以上是手机输入流中的数
val[n]=b+d;
n++;
}
b=0;d=0;g=10;
}
for(i=0;c[i]!=0;i++)
{
if(c[i] < '0' || c[i] > '9')
fu[j++]=c[i];
} // 这个则是收集输入流中的运算符
j=n;
i=0;
n=0; // 这里的清零是必须的
printf(":::::%f\n", digui());
}
就是一个数学表达式的解析和结果计算,push和pop只是方法只有,实现的方法有很多种