模拟简单运算器的工作。假设计算器只能进行加减乘除运算,运算数和结果都是整数,四种运算符的优先级相同,按从左到右的顺序计算。
输入在一行中给出一个四则运算算式,没有空格,且至少有一个操作数。遇等号”=”说明输入结束。
在一行中输出算式的运算结果,或者如果除法分母为0或有非法运算符,则输出错误信息“ERROR”。
1+2*10-10/2=
10
第一步:输出数据的计算过程分析:1+2*10-10/2=10
①先计算1+2=3 ②计算3*10=30 ③ 计算30-10=20 ④ 计算20/10=2 ⑤遇到等号输出结果
第二步:理清逻辑,编辑算法
问题求解的算法转化过程可能会遇到的几个问题:
问题①如何处理这种既有数字又有运算符整个合在一起的输入数据?
问题②如何实现从左往右的依次计算
针对问题①:显然我们目前所学知识不足以支撑我们一次性输入整个算式再来求解,所以我们应该分批处理输入的数据。
从而又引申出新的问题:问题③如何循环实现分批输入数据,循环的条件是什么,问题④怎样分批,按照什么切分数据。
针对问题③:由于循环控制次数不确定,但我们知道当输入的字符型数据为 ‘=’ 时即可结束循环,故优先选择while循环来实现该问题。while(字符变量 != '=' ) {..... }
针对问题④:由已知条件,
“输入在一行中给出一个四则运算算式,没有空格,且至少有一个操作数。”,
可以确定最开始的输入格式是 scanf("%d%c",&第一个整型变量,&字符型变量);由输入的字符变量,进而得到循环的判断条件。
进入循环以后,接下来要解决的问题是问题②如何实现从左往右的依次计算
我们在最开始的输入过程中已经输入了一个数字和一个操作符,进入循环以后我们还需要调用scanf("%d",&第二个整型变量),获取第二个操作数,然后才能继续计算。接下来就是根据之前输入的运算符确定计算方法。
针对这种有少数 固定判断条件的 选择分支语句 最好使用 swith() 语句:由于用的少,现在补充如下
详见教材:p57-p60
针对问题②,我们可以利用sum = sum+ i 这种计算原理 把计算的结果保存在第一个整型变量里面。 即 第一个整型变量 运算符= 第二个整型变量;
基本逻辑理清楚了大的框架也基本完成,再就是特殊条件处理和边界控制。
在一行中输出算式的运算结果,或者如果除法分母为0或有非法运算符,则输出错误信息“ERROR”。
该条件比较简单,我们直接开始尝试写代码。
#include <stdio.h> int main() { int x; //运算符前的数据存储在变量x中 int y; //运算符后面的存在y中 char ch; scanf("%d%c", &x, &ch); while(ch!='='){ //运算符合法,继续输入数据 scanf("%d",&y); //开始输入第二个数据 switch(ch){ case '+': x += y; continue; //本想着执行完这条语句后直接跳过后面的语句继续重新下一轮循环的 case '-': x -= y; continue; case '*': x *= y; continue; case '/': if(y!=0) { x /= y; continue; } else if(y == 0) printf("ERROR");break; default :printf("ERROR");break; } scanf("%c",&ch); //循环条件的变更 }//while printf("%d", x); return 0; }
哎呀!编译报错了。
:因为switch语句是选择语句,只能用break+,continue只能用于循环语句中,虽然这里是嵌套在了循环语句内,但由于作用域的原因,所以出错了
main.c:14:35: Error: 'continue' is only allowed inside loop statements.
case '+': x += y; continue;
我们的基本逻辑是想着直接跳出switch(),执行之后的语句,进行下一轮循环。
经过初次编译发现一个主要的语法上的细节。
因为switch语句是选择语句,只能用break,continue只能用于循环语句中(长记性!)
将上述代码中continue 全部替换成break语句 后继续进行调试验证:
$ ./main
1+2*10-10/2= //输入样例 成功输出
10 Program exited with status 0尝试除0
$ ./main
125/0=
ERROR125 Program exited with status 0$ ./main
125&5=
ERROR125 Program exited with status 0//输入样例 发现逻辑上有点小问题,出现错误以后不能中断后续所有信息
解决办法 设置一个出错标记的变量flag = 0,设置初值,出错以后标记位被修改比如 flag = 1;
然后再switch()语句后面先设置标记检查,若标记被修改则跳出循环,最后输出的时候还要判断一次标记位的信息,分类打印,实现最终的分类输出。
#include <stdio.h> int main() { int x; //运算符前的数据存储在变量x中 int y; //运算符后面的存在y中 int flag = 0; //出错标记位,出错会修改标记变量的值 char ch;//存储输入字符的变量 scanf("%d%c", &x, &ch); while(ch!='='){ //运算符合法,继续输入数据 scanf("%d",&y); //开始输入第二个数据 switch(ch){ //switch语句实现加减乘除的分类运算 case '+': x += y; break; //break实现跳出switch语句 case '-': x -= y; break; case '*': x *= y; break; case '/': if(y!=0) { //条件判断语句实现分母出错的判断 x /= y; break ; } else{ flag = 1 ; //出错修改标记位flag的值 break ; } default :flag = 1 ; break; //非法字符判断 } if(flag==1) break; //出错判断 标记位被修改跳出 break会while循环 scanf("%c",&ch); //****注意:while循环条件的变更,不然就死循环来了******* }//while if(flag==1) //实现分类输出 printf("ERROR"); else printf("%d", x); //正确输出 return 0; }
最后删除简单做一下简单的 优化和删除简单注释:得到
#include <stdio.h> int main() { int x,y,flag=0; char ch; scanf("%d%c", &x, &ch); while(ch!='='){ //运算符合法,继续输入数据 scanf("%d",&y); switch(ch){ //switch语句实现加减乘除的分类运算 case '+': x += y; break; case '-': x -= y; break; case '*': x *= y; break; case '/': if(y!=0) { x /= y; break ; } else{ flag = 1 ; break ; } default :flag = 1 ; break; } if(flag==1) break; //出错判断 scanf("%c",&ch); //:while循环条件的变更 } if(flag==1) printf("ERROR"); else printf("%d", x); return 0; } 从一开始就养成良好的代码书写规范: 一行只写一句话,空行将任务模块分块,调整好缩进 让自己的代码更加直观易懂,便于调试,更加优美!
■break,和continue 的使用场景和限定条件。
■将一整块输入条件拆解、分类处理的算法思维和实现过程。
■switch()语句的格式。
■循环内出错,如何跳出循环,并且与最终输出不产生冲突的处理