1.题目:算术表达式求值
功能:输入一个整数算术表达式字符串,分解出数值及运算符,并计算 输出结果。
要求:利用菜单可以循环实现求出加法、减法、乘法、除法算术表达式。
进一步要求*:
(1) 能够实现连续运算; 比如:123+233+555+666=
(2) 能够实现混合运算; 比如:120-23*5-20/4=
(3) 能够实现带括号的混合运算运算。 比如:12*(234-5)+(23+7)=
(4) 能够实现实数的各类运算。 比如:12.23*(12-3.7)+12.56=
(5) 能够实现多层括号嵌套运算 …(….(..)….(..(…))…)…
对不带括号的表达式容易计算,但是不要忽略除数为0的情况,此时表达式错误。对多括号的表达式可以用递归处理,也可以用数组模拟栈的方式进行解决,本代码对多层括号的表达式处理使用数组模拟栈的方式,带括号的简单混合运算则使用类似递归的方式,实际上本代码可以再简洁,直接全部用模拟栈的方式满足题目所有功能。
#include
#include
#include
#include
const int MAX_SIZE = 2019;
//存储操作数的栈
double stack_n[MAX_SIZE]; int t_n;
//存储运算符的栈
char stack_c[MAX_SIZE]; int t_c;
//函数声明
void add(); //减法
void sub(); //减法
void divi(); //除法
void muli(); //乘法
void mix(); //混合运算(不带括号)
//混合运算(带括号)
double mix_1();
void mix_plus();
//实数多括号 括号嵌套 运算
bool check(char ); //检查是否为运算符
char cmp(char , char ); //比较运算符之间的优先级
double cacu(double , char , double ); //进行相应运算符和操作数的运算
void fun(); //主要功能函数
int main() {
while(1) {
printf (" 菜单\n");
printf ("*************************************************\n");
printf ("# 1. 整数加法运算 #\n");
printf ("# 2. 整数减法运算 #\n");
printf ("# 3. 整数除法运算 #\n");
printf ("# 4. 整数乘法运算 #\n");
printf ("# 5. 整数混合运算 #\n");
printf ("# 6. 整数带括号混合运算 #\n");
printf ("# 7. 实数多括号混合运算 #\n");
printf ("# 0. 退出 #\n");
printf ("*************************************************\n");
printf ("请输入:");
int k;
scanf ("%d", &k);
while (k < 0 || k > 7) {
printf ("选择错误,请重新输入:");
scanf ("%d", &k);
}
getchar();
switch(k) {
case 0: exit(0);
case 1: {
//清屏函数
system("cls");
add(); break;
}
case 2: {
system("cls");
sub(); break;
}
case 3: {
system("cls");
divi(); break;
}
case 4: {
system("cls");
muli(); break;
}
case 5: {
system("cls");
mix(); break;
}
case 6: {
system("cls");
mix_plus(); break;
}
case 7: {
system("cls");
fun(); break;
}
}
}
return 0;
}
//连续加法
void add() {
while(1) {
printf ("请输入加法表达式:\n");
char c;
int sum = 0;
while((c = getchar())!= '\0') {
int a = 0;
//一直读数字直到非数字
while ('0' <= c && c <= '9') {
a = a * 10 + (c - '0');
c = getchar();
}
//将数字相加
sum += a;
if ( c == '=') break;
}
printf ("%d\n", sum);
printf ("继续请输入y或Y,输入其它返回菜单.\n");
getchar();c = getchar();
if (c != 'y' && c != 'Y') break;
}
system("cls");
}
//连续减法
void sub() {
while (1) {
printf ("请输入减法表达式:\n");
char c;
int sum = 0, flag = 0;
while((c = getchar())!= '\0') {
int a = 0;
//处理第一个数为负数的情况
if (c == '-') flag = 1;
while ('0' <= c && c <= '9') {
a = a * 10 + (c - '0');
c = getchar();
}
if (flag) a = -a, flag = 0;
sum += a;
if ( c == '=') break;
//将减数变为负数,然后与被减数相加处理
else if (c == '-') flag = 1;
}
printf ("%d\n", sum);
printf ("继续请输入y或Y,输入其它返回菜单.\n");
getchar(); c = getchar();
if (c != 'y' && c != 'Y') break;
}
system("cls");
}
//连续乘法
void muli() {
while(1) {
printf ("请输入乘法表达式:\n");
char c;
//flag = 1表示该数为负数
int sum = 1, flag = 0;
while((c = getchar())!= '\0') {
int a = 0, k = 0;
if (c == '-') flag = 1;
//读入数字
while ('0' <= c && c <= '9') {
a = a * 10 + (c - '0');
k = 1;
c = getchar();
}
if (flag) a = -a, flag = 0;
if (k) sum *= a;
if ( c == '=') break;
else if (c == '-') flag = 1;
}
printf ("%d\n", sum);
printf ("继续请输入y或Y,输入其它返回菜单.\n");
getchar(); c = getchar();
if (c != 'y' && c != 'Y') break;
}
system("cls");
}
//连续除法
void divi() {
while(1) {
printf ("请输入除法表达式:\n");
char c;
//flag = 1 表示该数为负数
double sum = 0, flag = 0;
while((c = getchar()) != '\0') {
//k = 1表示读取了数字,防止第一个数为负数时进行错误运算
int a = 0, k = 0;
if (c == '-') flag = 1;
while ('0' <= c && c <= '9') {
a = a * 10 + (c - '0');
k = 1;
c = getchar();
}
if (flag) a = -a, flag = 0;
//若读入第一个数,使sum = a
if (!sum && k) sum = a * 1.0;
//不是第一个数时
else if (k) {
//a为0的情况
if (a == 0) {
printf ("表达式错误!\n");
return;
}
sum /= (double)a;
}
if ( c == '=') break;
else if (c == '-') flag = 1;
}
printf ("%.2lf\n", sum);
printf ("继续请输入y或Y,输入其它返回菜单.\n");
getchar(); c = getchar();
if (c != 'y' && c != 'Y') break;
}
system("cls");
}
//混合运算
void mix() {
while(1) {
printf ("请输入混合运算表达式:\n");
char c;
//p = 1,运算符为"*",p = -1,运算符为"/"
int flag = 0, p = 0;
double temp, sum = 0;
while((c = getchar())!= '\0') {
int a = 0, k = 0;
if (c == '-') flag = 1;
while ('0' <= c && c <= '9') {
a = a * 10 + (c - '0');
k = 1;
c = getchar();
}
if (flag) a = -a, flag = 0;
if (c == '-') flag = 1;
//当前运算符为"*"
else if (c == '*' && k) {
//状态标志位0
if (!p) p = 1, temp = (double)a;
//前一个运算符为"/"
else if (p == -1) {
if (!a) {printf ("表达式错误!\n"); return;}
temp /= a, p = 1;
}
//前一个运算符为"*"
else temp *= a, p = 1;
}
//当前运算符为"/"
else if (c == '/' && k) {
//状态标志位0
if (!p) p = -1, temp = (double)a;
//前一个运算符为"*"
else if (p == 1) temp *= a, p = -1;
//前一个运算符为"/"
else {
if (!a) { printf ("表达式错误!\n"); return;}
temp /= a, p = -1;
}
}
//遇到优先级低的运算符时,进行运算并重置p
if ((c == '+' || c == '-' || c == '=') && p == 0 && k) sum += a;
else if ((c == '+' || c == '-' || c == '=') && p == 1 && k) sum += temp * a, p = 0;
else if ((c == '+' || c == '-' || c == '=') && p == -1 && k) {
if (a != 0) sum += temp / a, p = 0;
else { printf ("表达式错误!\n"); return;}
}
if (c == '=') break;
}
//输出结果
printf ("%.2lf\n", sum);
printf ("继续请输入y或Y,输入其它返回菜单.\n");
getchar(); c = getchar();
if (c != 'y' && c != 'Y') break;
}
system("cls");
}
//处理括号内的运算
double mix_1(){
char c;
int flag = 0, p = 0;
int temp, sum = 0;
while((c = getchar())!= ')') {
int a = 0, k = 0;
if (c == '-') flag = 1;
while ('0' <= c && c <= '9') {
a = a * 10 + (c - '0');
k = 1;
c = getchar();
}
if (flag) a = -a, flag = 0;
if (c == '-') flag = 1;
else if (c == '*' && k) {
if (!p) p = 1, temp = (double)a;
else if (p == -1) {
//if (!a) {printf ("表达式错误!\n"); return;}
temp /= a, p = 1;
}
else temp *= a, p = 1;
}
else if (c == '/' && k) {
if (!p) p = -1, temp = a;
else if (p == 1) temp *= a, p = -1;
else {
//if (!a) { printf ("表达式错误!\n"); return;}
temp /= a, p = -1;
}
}
if ((c == '+' || c == '-' || c == ')') && p == 0 && k) sum += a;
else if ((c == '+' || c == '-' || c == ')') && p == 1 && k) sum += temp * a, p = 0;
else if ((c == '+' || c == '-' || c == ')') && p == -1 && k) {
if (a != 0) sum += temp / a, p = 0;
//else { printf ("表达式错误!\n"); return;}
}
if (c == ')') break;
}
return sum;
}
//带括号混合运算
void mix_plus() {
while(1){
printf ("输入整数带括号的混合运算表达式:\n");
char c;
int flag = 0, p = 0;
double temp, sum = 0;
while((c = getchar())!= '\0') {
double a = 0;
int k = 0;
if (c == '-') flag = 1;
//读到"("调用函数计算
else if (c == '(') {
a = mix_1(), k = 1;
c = getchar();
//printf("%d\n",a);
}
while ('0' <= c && c <= '9') {
a = a * 10 + (c - '0');
k = 1;
c = getchar();
}
if (flag) a = -a, flag = 0;
if (c == '-') flag = 1;
else if (c == '*' && k) {
if (!p) p = 1, temp = a;
else if (p == -1) {
if (!a) {printf ("表达式错误!\n"); return;}
temp /= a, p = 1;
}
else temp *= a, p = 1;
}
else if (c == '/' && k) {
if (!p) p = -1, temp = a;
else if (p == 1) temp *= a, p = -1;
else {
if (!a) { printf ("表达式错误!\n"); return;}
temp /= a, p = -1;
}
}
if ((c == '+' || c == '-' || c == '=') && p == 0 && k) sum += a;
else if ((c == '+' || c == '-' || c == '=') && p == 1 && k) sum += temp * a, p = 0;
else if ((c == '+' || c == '-' || c == '=') && p == -1 && k) {
if (a != 0) sum += temp / a, p = 0;
else { printf ("表达式错误!\n"); return;}
}
if (c == '=') break;
}
printf ("%.2lf\n", sum);
printf ("继续请输入y或Y,输入其它返回菜单.\n");
getchar(); c = getchar();
if (c != 'y' && c != 'Y') break;
}
system("cls");
}
void fun() {
while (1) {
//重置栈
memset(stack_n, 0, sizeof(stack_n));
memset(stack_c, 0, sizeof(stack_c));
t_c = t_n = 0;
char str[2020];
printf ("输入实数混合运算表达式:\n");
scanf("%s", str); //获取表达式
double a, b;
int i = 0, count = 0, flag = 0; //count对小数位数计数, flag = 1表示负号
char c = str[i]; //记录i的上一个字符,i = 0时等于自身
stack_c[++t_c] = '='; //便于比较
while (str[i] != '=' || stack_c[t_c] != '=') {
//若不是操作数
if (!check(str[i])) {
//如果上一个字符是小数点
if (c == '.') count++;
//count > 0 进行有关小数的计算
if (count > 0) {
//取栈顶元素并出栈 计算后入栈
a = stack_n[t_n--];
if (a < 0) //负数
stack_n[++t_n] = a - (str[i] - '0') / pow(10, count);
else
stack_n[++t_n] = a + (str[i] - '0') / pow(10, count);
count++;
}
//有关整数
if (str[i] != '.' && !count) {
//若上一个字符是数字且操作数栈不为空
if (!check(c) && t_n > 0) {
a = stack_n[t_n--];
if (a < 0) //负数
stack_n[++t_n] = a * 10 - (str[i] - '0');
else
stack_n[++t_n] = a * 10 + str[i] - '0';
}
else {
if (flag)
stack_n[++t_n] = -(str[i] - '0');
else
stack_n[++t_n] = str[i] - '0';
flag = 0;
}
}
c = str[i++]; //字符数组下标移动并保存上一个字符
}
else
{
count = 0; //重置
//检查负数情况
if (check(c) && str[i] == '-') {
flag = 1; c = str[i++];
continue;
}
//运算符之间的比较和相应操作
switch (cmp(stack_c[t_c], str[i])) {
case '>':{ //当前运算符优先级低 取出栈顶运算符和操作数前两个数(两次出栈)进行运算,将结果入操作数栈
//然后再次与栈顶运算符比较直到遇见"=" 或 "<" 情况
char op = stack_c[t_c--];
a = stack_n[t_n--]; b = stack_n[t_n--];
//表达式错误
if (a == 0 && op == '/') {
printf ("表达式错误!\n");
return;
}
stack_n[++t_n] = cacu(b, op, a);
break;
}
case '=':{ //此时'(' == ')' 取出左括号
t_c--;
c = str[i++];
break;
}
case '<':{ //优先级比栈顶运算符高,入栈
stack_c[++t_c] = str[i];
c = str[i++];
break;
}
}
}
}
//输出结果
printf ("%.4lf\n", stack_n[t_n]);
printf ("继续请输入y或Y,输入其它返回菜单.\n");
getchar(); c = getchar();
if (c != 'y' && c != 'Y') break;
}
system("cls");
}
bool check(char c) {
//包含运算符的字符数组
char oper[7] = {'+','-','*','/','(',')','='};
for (int i = 0; i < 7; i++) {
//与字符c比较相等返回true否则循环结束返回false
if (oper[i] == c) return true;
}
return false;
}
char cmp(char x, char y) {
char c;
switch (x) {
case '+':
case '-':{
switch(y) {
case '+':
case '-':
case ')':
case '=':
c = '>'; break;
default: c = '<'; break;
}
break;
}
case '*':
case '/':{
switch(y){
case '(':
c = '<'; break;
default: c = '>';
}
break;
}
case '(':{
switch(y){
case ')':
c = '='; break;
default: c = '<';
}
break;
}
case ')':{
c = '>';
break;
}
case '=':{
switch(y){
case '=':
c = '='; break;
default: c = '<';
}
break;
}
}
return c;
}
double cacu(double a, char op, double b) {
double sum;
switch(op) {
case '+':
sum = a + b; break;
case '-':
sum = a - b; break;
case '*':
sum = a * b; break;
case '/':
sum = a / b; break;
}
return sum;
}