下面首先记录浮点数四则运算器输入模块的编写。
思路和要求记录如下:
全局变量:
string dat--保存正在输入的串
string all[]--保存输入完成的串
map用于计数
flag用于记录应该执行哪一种输出模式
x用于记录已经输入的数据的个数
一、对输入数据的预处理。
用getchar输入,保存到string中。会出现以下一些情况:
1.输入了' ':一个串输入完成,保存,清空后输入新的串。
2.输入了\n':输入完成了一个表达式,本次输入结束。
3.过程中输入了'=':说明这是变量赋值语句,应该输出变量的值。
4.输入的串为"exit":说明计算完成,程序停止。
5.其他情况则保存字符。
其中,1. 2. 4. 5.都易于实现,而对于3. 可以采用将等号之前的部分保存为一个串,等号之后的部分保存为另一个串,后续使用map处理。
!6.这里可以进行的表达式错误类型判断:括号的匹配。
可这样进行:令code=0,当输入'('时code1++;当输入')'时code--; 用这样的逻辑,我们可以区分出以下情况:
1)输入结束时flag<0,说明有')'多余,flag=1,记为error code 1:extra ')'。
2)输入结束时flag>0,说明有‘('多余,flag=2,记为error code 2:extra '('。
输入模块(包括头文件)代码尝试编写:
1 #include<iostream> 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<algorithm> 5 #include<map> 6 #include<stack> 7 #include<queue> 8 9 using namespace std; 10 11 string dat; 12 string all[100]; 13 map<string,double> cnt; 14 map<string,double>::iterator iter; 15 int flag=0; 16 int x=0; 17 18 void Getdata(){ 19 x=0; 20 flag=0; 21 dat=""; 22 for (int i=0;i<100;i++){ 23 all[i]=""; 24 } 25 int code=0; 26 char a=0; 27 cout<<"in>>"; 28 while (1){ 29 a=getchar(); 30 if (a=='('){ 31 code++; 32 } 33 if (a==')'){ 34 code--; 35 } 36 if (a==' '){ 37 all[x]=dat; 38 x++; 39 dat=""; 40 continue; 41 } 42 if (a=='\n'){ 43 all[x]=dat; 44 dat=""; 45 if (flag==3){ 46 cnt[all[x-1]]=atof(all[x].c_str()); 47 } 48 if (all[x]=="exit"){ 49 flag=4; 50 } 51 if (code<0){ 52 flag=1; 53 } 54 if (code>0){ 55 flag=2; 56 } 57 return ; 58 } 59 if (a=='='){ 60 flag=3; 61 all[x]=dat; 62 x++; 63 dat=""; 64 continue; 65 } 66 dat+=a; 67 } 68 }
测试这一段输入模块的测试用主程序:
1 int main(){ 2 while (1){ 3 Getdata(); 4 if (flag==1){ 5 printf("out>>error code 1:extra ')'\n"); 6 continue; 7 } 8 if (flag==2){ 9 printf("out>>error code 2:extra '('\n"); 10 continue; 11 } 12 if (flag==3){ 13 printf("out>>%.2lf\n",cnt[all[x-1]]); 14 continue; 15 } 16 if (flag==4){ 17 break; 18 } 19 if (flag==0){ 20 printf("out>>"); 21 for (int i=0;i<x;i++){ 22 printf("%s ",all[i].c_str()); 23 } 24 printf("%s\n",all[x].c_str()); 25 continue; 26 } 27 } 28 return 0; 29 }
运行结果与预期相同。
这里意识到可以增加运算器的功能——给多个变量名赋同一个值。
于是将输入模块代码中的第45行到47行修改为:
1 if (flag==3){ 2 for (int i=0;i<x;i++){ 3 cnt[all[i]]=atof(all[x].c_str()); 4 } 5 }
这样就同时给多个同样数值的变量赋了同一个值。
(我喜欢写每一行内容很少行数很多的代码……捂脸……因为看起来整齐)
二、对输入数据的运算过程。(初步规划)
首先记录一下已经输入好的数据的保存位置。
·cnt[all[i]]保存了在exit之前的所有的变量值,以最后一次输入为准。 map类
·all[300]中保存了每一次输入后所有的数据。 string类
·x记录了all中数据的个数,一直到all[x]都有数据填充。 int类
现在all[300]中保存了可能含有字母元的中缀表达式,可以将其转化为前缀表达式后运算输出结果。
到这里已经基本结束了,转化方法和运算方法在 【数据结构】栈与队列Part2:栈的应用之表达式转换 已经有所操作。
但是还有一个遗留的问题:错误类型的判断。
期望能做到的有:
1.能够识别除数是否为0。
2.能够识别是否出现了不合法运算式,比如5 6 * 3,这里5和6中间缺少运算符。
PLUS:能够识别缺少运算符的位置。
3.能够识别没有赋初值的字母元。
由于数据的保存方式,2和3都很容易实现,但1的识别依然是一个难点。
想到的解决方式是运算过程遇到'/'时检测被除数。
这样基本就可以编辑出完整的浮点数四则运算器。
Part2将会是运算输出模块的编写和运行。