题目要求:
模拟简单运算器的工作。假设计算器只能进行加减乘除运算,运算数和结果都是整数,四种运算符的优先级相同,按从左到右的顺序计算。
输入格式:
输入在一行中给出一个四则运算算式,没有空格,且至少有一个操作数。遇等号”=”说明输入结束。
输出格式:
在一行中输出算式的运算结果,或者如果除法分母为0或有非法运算符,则输出错误信息“ERROR”。
输入样例:
1+2*10-10/2=
输出样例:
10
思路:
如何将等式的元素保存到数组中?
创建一个int数组,保存输入的等式元素。
不能对所有的元素都使用getchar()因为数字可能有多位。
因为每当读取一个运算符后(不包括‘=’),后面必定是一个数字,
所以可以每次读取并储存一个运算符后,
用scanf("%d",&equal[i])读取并储存一个数字。
这样就实现了将等式的所有元素都保存在等式数组中。
代码片段如下:
int equal[100] = {0}; //建立等式数组
int c; //创建字符变量
int i = 0, j, cnt; //运算符指针, 右操作数指针, 计算次数
int right; //创建右操作数变量
int tot; //创建累积量
scanf("%d", &equal[i]); //先把第一个数字储存到等式数组中
i++; //让储存等式元素的数组的索引+1
while( (c = getchar()) != '=')
{
equal[i] = c; //读取运算符号
i++; //让储存等式元素的数组的索引+1
scanf("%d", &equal[i++]); //读取数字并让储存等式元素的数组的索引+1
//(即不管读取的是数字还是符号都需要让索引+1)
switch (c) //如果读取了不是运算符号的字符,返回EORROR
{
case '+':
break;
case '-':
break;
case '*':
break;
case '/':
break;
default:
printf("ERROR\n");
return 0;
}
if (c == '/' && equal[i-1] == 0) //如果被除数是0,返回ERROR
{
printf("ERROR\n");
return 0;
}
}
如何利用等式数组进行从左向右的运算?
假设输入的字符串是1 + 2 * 10 - 10 / 2 =
通过上述保存等式数组的方法,得到的数组是:
元素 | 1 | + | 2 | * | 10 | - | 10 | / | 2 |
---|---|---|---|---|---|---|---|---|---|
索引 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
p.s.所有的运算符都是通过ASCII码的形式储存的,是int型,想得到字符类型需要用到类型转化,即(char)equal[i]
通过观察可以发现
运算符的索引是奇数(2n +1 )
算子(我更喜欢叫操作数)的索引是偶数(2n)。
于是我们可以建立一个累积变量(tot),让这个累计变量(tot)成为为运算的左操作数,元素中的每一个数字(除了第一个)成为右操作数。
e.g.
tot = 1 | i = 1; j = 2; |
---|---|
tot + 2 = 3 --> tot = 3 | n = 1;+ ----> equal(1) ; 2 ----> equal(2); i = 2 *n +1 = 3; n = n + 1 = 2; j = 2 * n = 4; |
tot *10 = 30 --> tot = 30 | n = 2;* ----> equal(3) ; 10 ----> equal(4); i = 2 *n +1 = 5;n = n + 1 = 3; j = 2 * n =6 ; |
tot - 10 = 20 --> tot = 20 | n = 3; + ----> equal(5) ; 2 ----> equal(6); i = 2 *n +1 = 7; n = n + 1 = 4; j = 2 * n = 8; |
tot / 2 = 10 --> tot = 10 | n = 4; + ----> equal(7) ; 2 ----> equal(8); i = 2 *n +1 = 9; n = n + 1 = 5; j = 2 * n = 10; |
代码片段如下:
int lene = i; // lene ---> length of equal
tot = equal[0]; // tot ---> total(累加值)
right = equal[2]; // right---> 右操作数(equal[0,2,4,6,8,...])
for (i = 1, j = 2, cnt = 1; i < lene;) // 计算等式(tot + or - or * or / equal[0,2,4,6,8,...])
{
switch ((char)equal[i])
{
case '+':
//printf("hr+\n");
tot += right;
//printf("tot = %d\n",tot);
break;
case '-':
//printf("hr-\n");
tot -= right;
//printf("tot = %d\n",tot);
break;
case '*':
//printf("hr*\n");
tot *= right;
//printf("tot = %d\n",tot);
break;
case '/':
//printf("hr/\n");
tot /= right;
//printf("tot = %d\n",tot);
break;
}
i = 2 * cnt + 1; // i是指向运算符号的指针,i = 1,3,5,7....
cnt++; // 计算的次数
j = 2 * cnt; // j是指向右操作数的指针, j = 2,4,6,8.....
right = equal[j];
}
最后tot的值即为等式的结果。
代码
#include <stdio.h>
int main()
{
int equal[100] = {0}; //建立等式数组
int c; //创建字符变量
int i = 0, j, cnt; //运算符指针, 右操作数指针, 计算次数
int right; //创建右操作数变量
int tot; //创建累积量
scanf("%d", &equal[i]); //先把第一个数字储存到等式数组中
i++; //让储存等式元素的数组的索引+1
while( (c = getchar()) != '=')
{
equal[i] = c; //读取运算符号
i++; //让储存等式元素的数组的索引+1
scanf("%d", &equal[i++]); //读取数字并让储存等式元素的数组的索引+1(即不管读取的是数字还是符号都需要让索引+1)
switch (c) //如果读取了不是运算符号的字符,返回EORROR
{
case '+':
break;
case '-':
break;
case '*':
break;
case '/':
break;
default:
printf("ERROR\n");
return 0;
}
if (c == '/' && equal[i-1] == 0) //如果被除数是0,返回ERROR
{
printf("ERROR\n");
return 0;
}
}
int lene = i; // lene ---> length of equal
tot = equal[0]; // tot ---> total(累加值)
right = equal[2]; // right---> 右操作数(equal[0,2,4,6,8,...])
for (i = 1, j = 2, cnt = 1; i < lene;) // 计算等式(tot + or - or * or / equal[0,2,4,6,8,...])
{
switch ((char)equal[i])
{
case '+':
//printf("hr+\n");
tot += right;
//printf("tot = %d\n",tot);
break;
case '-':
//printf("hr-\n");
tot -= right;
//printf("tot = %d\n",tot);
break;
case '*':
//printf("hr*\n");
tot *= right;
//printf("tot = %d\n",tot);
break;
case '/':
//printf("hr/\n");
tot /= right;
//printf("tot = %d\n",tot);
break;
}
i = 2 * cnt + 1; // i是指向运算符号的指针,i = 1,3,5,7....
cnt++; // 计算的次数
j = 2 * cnt; // j是指向右操作数的指针, j = 2,4,6,8.....
right = equal[j];
}
printf("%d\n", tot); // 打印出最后的计算值
return 0;
}