题目要求如下:
由于会输入1行的字符串,其中输入只有数字和运算符,因此可以使用C中的strtok函数按照空格将字符串拆分为多个片段,再读取每个片段中的内容。
这里我们定义了1个结构体Stack,其有4个成员,a表示前1个元素,b表示后1个元素,o表示操作符,而length是当前位置。
由于输入的字符串最多200个字符,除去前后元素及运算符,因此最多67组,这里直接向上舍入为70。
当读入数字字符串时,需要将字符串的值转换为对应的10进制数。
这个简单的计算器可以使用栈来轻松的解决,一般情况下会将中缀表达式转换为后缀表达式来轻松的解决。而这里直接简单粗暴,直接按照读取的顺序查看输入的值。
下面是对应的操作过程:
- 当首次读取到数字字符串时,将其存储到结构体的a成员中
- 当读取到运算符时,将其压入栈中o成员中。如果运算符是加法或减法,让length成员值加1表示压栈,并设置优先级变量priority的值为0。因为对于乘法和除法来说,其优先级更高,将其设置为0可以看成是重置其优先级。
- 当读取到下1个数字字符串时,如果此时运算符符号为减法,那么让当前值为负数,并设置其运算符为加号。然后再将该值压入b成员中
- 对于读取到数字字符串,如果运算符为乘法或除法,那么查看当前优先级变量priority的符号,如果该变量的值为0,表示之前没有出现过除法或乘法,而如果当前栈的长度大于1,那么将其优先级设置为1,并读取b成员中的元素。因为这说明之前元素是按加法或减法处理的,因此要对其符号进行修正。
下面是实现的代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
double a[70];
double b[70];
char o[70];
int length;
} Stack;
int main() {
char line[201] = {0};
while (gets(line) != NULL) {
if(strcmp(line, "0")==0){
break;
}
char *delimiter = " ";
char *token = strtok(line, delimiter);
int is_operator = 0;
int priority = 0;
Stack stack = {0};
while (token) {
if (token[0] >= '0' && token[0] <= '9') {
// 字符串转数字
int l = strlen(token);
int total = 0, k = 1;
for (int i = l - 1; i >= 0; --i) {
total += k * (token[i] - '0');
k *= 10;
}
// 乘法
if (is_operator == 3) {
double tmp;
if (priority == 0 && stack.length > 1) {
priority = 1;
tmp = stack.b[stack.length - 1];
} else {
tmp = stack.a[stack.length - 1];
}
// 进行乘法处理
stack.a[stack.length - 1] = tmp * total;
// 上1个元素设置为0,已经已经被处理过了
stack.b[stack.length - 1] = 0;
if (stack.length>1){
// 设置当前运算符为1个元素的符号
stack.o[stack.length - 1] = stack.o[stack.length - 2];
}else{
// 设置为默认的加号
stack.o[stack.length - 1] = '+';
}
} else if (is_operator == 4) {
// 除法
double tmp;
if (priority == 0 && stack.length > 1) {
priority = 1;
tmp = stack.b[stack.length - 1];
} else {
tmp = stack.a[stack.length - 1];
}
stack.a[stack.length - 1] = tmp / total;
stack.b[stack.length - 1] = 0;
if (stack.length>1){
stack.o[stack.length - 1] = stack.o[stack.length - 2];
}else{
stack.o[stack.length - 1] = '+';
}
} else if (is_operator > 0) {
// 加法与减法
if (stack.o[stack.length-1]=='-'){
total = 0 - total;
stack.o[stack.length-1] = '+';
}
stack.b[stack.length - 1] = total;
} else {
stack.a[stack.length++] = total;
}
} else {
// 将操作符压入栈中
if (strcmp(token, "+") == 0) {
is_operator = 1;
stack.length++;
priority = 0;
stack.o[stack.length - 1] = '+';
} else if (strcmp(token, "-") == 0) {
is_operator = 2;
stack.length++;
priority = 0;
stack.o[stack.length - 1] = '-';
} else if (strcmp(token, "*") == 0) {
is_operator = 3;
stack.o[stack.length - 1] = '*';
} else if (strcmp(token, "/") == 0) {
is_operator = 4;
stack.o[stack.length - 1] = '/';
}
}
token = strtok(NULL, delimiter);
}
double tmp = 0.0;
for (int j = 0; j < stack.length; ++j) {
char op = stack.o[j];
// 根据操作符进行对应操作,此时只有加法或减法
if (op == '+') {
tmp += stack.a[j] + stack.b[j];
} else {
tmp += stack.a[j] - stack.b[j];
}
}
printf("%.2f\n", tmp);
}
return 0;
}
实际上整个过程是将拆分的字符串使用结构体继续存储,使用加法对结果进行累加。其中的o用于后续整个过程完成后对前后运算的运算。
下面来看1个简单的例子:
30 / 90 - 26 + 97 - 5 - 6 - 13 / 88 * 6 + 51 / 29 + 79 * 87 + 57 * 92
首先读取30,接着读取/,当读入90时发现当前运算符为除法,那么将第1个元素读出除以后1个元素,将其值写入到第1个元素中,将其2个元素设置0。则第1组操作完成。
接着读入,发现是减号,将栈长度增加,此时a元素为0,再读入下1个元素26,发现运算符为减号,则b中存储是-26。
以此类推,直到13/88*6时,当读取除号,使用13/88,设置优先级为1,结果写入a成员中。读入数字6,由于之前优先级不为0,读取a成员中的值对其进行操作,并设置其操作符为之前的减号。
接着读取加号,对操作符进行重置。以此类推,直到整个过程完成。
其运算过程如下:
30/90 + 0 0 + -26 0 + 97 0 + -5 0 + -6 -13/88*6 + 0 51/29 + 0 79 * 87 + 0 57 ** 92 + 0
因此其最终结果为12178.21。
最后是通过后的结果:

本文介绍了一种使用栈结构处理算术表达式的简易计算器实现方法。通过分析输入字符串中的数字和运算符,利用C语言实现了基本的四则运算。文章详细解释了如何处理不同优先级的运算符,并提供了一个具体示例。
326

被折叠的 条评论
为什么被折叠?



