写了一个计算器程序,想分享给大家;同时写到最后感觉有点凌乱,希望各位帮忙给优化下,共同提高。这个计算器可以计算输入的字符串,字符串中可以含括号,可以是小数,也可以包含负数。此程序被拆分在5个文件中,我按文件一一罗列吧:
编写环境:VC++6.0。
第一个main函数所在文件:
#include<stdio.h> #include<stdlib.h> #include<ctype.h> int main() { char *s1; int i; double c; double calc(char *s); int brk(char *st); while(1) { s1=(char *)malloc(50); //为s1分配地址和空间。 scanf("%s",s1); //输入并得到s1字符串。 i=brk(s1); //执行所有"()"中的计算式。 c=calc(s1); //计算最后的不带"()"的s1。 printf("%g\n",c); //输出最后结果。 printf("--------Press Up/Down Arorw or Begain Next Input:\n"); //提示执行下一次运算。 free(s1); //释放s1内存空间。 } }
第二个函数文件:
#include<stdio.h> #include<stdlib.h> #include<ctype.h> double calc(char *s) //把s拆解成double型数组和保存操作符的字符型数组, { //并利用两个数组计算结果。 int i=0,j=0,k=0,num=1,end=0,sub=0; //num、end、sub为开关标识。 double *sn; char *sc,*sp; void mathc(double *a,char *s); sn=(double *)malloc(51); //用于存放s中所有的数字串。 sc=(char *)malloc(50); //用于存放s中所有的操作符。 sp=(char *)malloc(10); //遍历s中的各个数字串,并保存其中。 //while(!isdigit(*s)) // s++; //c=*s; //if(c==‘-‘) //{ // *sp=c; // i=1; // s++; //} for(;*s!=‘\0‘;s++) //遍历s所有字符。 { if(!isdigit(*s) && *s!=‘+‘ && *s!=‘-‘ && *s!=‘*‘ && *s!=‘/‘ && (接上一行) *s!=‘.‘) //如果字符不是数字且不是操作符及小数点则输出错误。 { printf("Error 6: illegal input!\n"); return 0; } if(isdigit(*s)||*s==‘.‘) //如果字符是个数字或者小数点。 { //if(c==‘-‘) *(sp + i++)=*s; //i++; num=0; //把这3个开关置为0。 end=0; sub=0; continue; } if(sub==1) //sub用于标识s中负数,比如"-5", //但是如果有两个"--"则是错误, // 除了类似"4--5"【等价于4-(-5)】的情况。 { //"--"前没有数字的情况是不允许的。 printf("Error 7: too many operator!\n"); return 0; } if(num==1) //num==1说明是字符串刚开始(即第一个字符) { //或者上一次执行的是“+-*/”。 if(*s!=‘-‘) //开始不是"-"或"+*/"后面不是"-"。 { //(注意在这个时候肯定也不是数字, //因为数字已经被判断过了。) printf("Error 8: too many operator!\n"); return 0; } else { *(sp + i++)=*s; //开始是个"-"或者前一个字符是"+*/"。 sub=1; //把sub置为1,即下一个字符不能再是"-", //注意这是在num==1的情况下。 end=0; //执行的是数字字符部分,此程序把 //这种情况下的负号做为了数字的一部分。 continue; //执行下一次循环。 } } if(*s==‘+‘||*s==‘-‘||*s==‘*‘||*s==‘/‘) //如果执行的字符是操作符。 { *(sp+i)=‘\0‘; //是sp结束,即结束数字字符部分。 i=0; //使下一次sp从0开始计数。 end=1; //标识数字字符部分执行结束。 *(sn + j++)=atof(sp); //把sp转换为double型数组。 if(*(s+1)==‘\0‘) //如果下一个元素为s的的结束, //则不往下执行,即不保存这个操作符。 break; *(sc + k++)=*s; //既然s的下一个元素不是结束, //那么把这个字符串保存到sc中。 num=1; //因为刚保存的是个操作符, //下一个不能再是操作符,除了"-"。 continue; } } if(*s==‘\0‘&&end==0) //s的最后一个字符是数字字符,执行这一部分语句。 { *(sp+i)=‘\0‘; //使sp结束。 //i=0; if(*(sp+i-1)==‘-‘) //如果上一个字符只是一个"-"号,则输出错误。 { printf("Error 9: illegal input!\n"); return 0; } *(sn + j++)=atof(sp); //把sp转换成double数组保存到sn中。 } *(sn+j)=‘\0‘; //是sn和sc结束。 *(sc+k)=‘\0‘; mathc(sn,sc); //把sn和sc传给mathc函数计算s的结果。 return *sn; //mathc的计算结果是保存在sn中的, } //把sn返回即可。
第三个函数文件:
#include<stdio.h> void mathc(double *a, char *s) //执行计算。 { int i; double sum; void offsetd(double *s,int n1, int n2); void offsetc(char *s,int n1,int n2); for(i=0;*(s+i)!=‘\0‘;i++) //先计算“/”。 if(*(s+i)==‘/‘) { if(*(a+i+1)==0) //不能除以0。 { printf("Error 5: illegal input 0!\n"); break; } sum = *(a+i) / *(a+i+1); *(a+i)=sum; offsetd(a,i+1,1); offsetc(s,i,1); i=-1; } for(i=0;*(s+i)!=‘\0‘;i++) //计算"*"。 if(*(s+i)==‘*‘) { sum = *(a+i) * *(a+i+1); *(a+i)=sum; offsetd(a,i+1,1); offsetc(s,i,1); i=-1; } for(i=0;*(s+i)!=‘\0‘;i++) //计算"-"。 if(*(s+i)==‘-‘) { sum = *(a+i) - *(a+i+1); *(a+i)=sum; offsetd(a,i+1,1); offsetc(s,i,1); i=-1; } for(i=0;*(s+i)!=‘\0‘;i++) //计算"+"。 if(*(s+i)==‘+‘) { sum = *(a+i) + *(a+i+1); *(a+i)=sum; offsetd(a,i+1,1); offsetc(s,i,1); i=-1; } }
第四个函数文件:
#include<stdio.h> #include<string.h> void offsetd(double *s,int n1, int n2) //使double数组的n1+n2处的元素往前移动n2。 { for(;*(s+n1)!=‘\0‘;n1++) *(s+n1) = *(s+n1+n2); } void offsetc(char *s,int n1, int n2) //与offsetd功能相同,只是s数组元素是字符型。 { for(;*(s+n1)!=‘\0‘;n1++) *(s+n1) = *(s+n1+n2); } void repl(char *c1,char *c2,int i,int j) //使用c2替换c1中第i-j之间的元素。 { unsigned int n=0; int a; n=strlen(c2); for(a=n;*(c1+j)!=‘\0‘;) //先把c1中第j元素以后的数字复制到c2后面。 *(c2 + a++) = *(c1 + j++); *(c2+a)=‘\0‘; for(;*c2 != ‘\0‘;) //用c2替换c1中第i元素往后的所有元素。 *(c1 + i++) = *(c2++); *(c1+i)=‘\0‘; }
第五个函数文件:
#include<stdio.h> #include<stdlib.h> #include<ctype.h> int brk(char *st) //计算括号内的算式的值。 { int m,n,d,b; //m左括号位置,n遍历整个st数组,d右括号位置,b用于上s2数组。 char *s2; double i; void repl(char *c1,char *c2,int i,int j); //调用repl函数使用s2计算结果 //替换st中相应位置的字符。 //void mathc(double *a,char *s); double calc(char *s); //计算字符串s的值。 s2=(char *)malloc(50); //为s2分配内存空间,并返回空间地址。 for(n=0;*(st+n)!=‘\0‘;n++) //遍历st数组。 if(*(st+n)==‘)‘) //首先查找")"。重要!在多重括号 //中查找")"才能有效的找到每组括号。 { d=n; //把"("的位置保存在d中。 if(*(st+d+1)!=‘\0‘&&isdigit(*(st+d+1))) //st的下一位是个数字则 //输出错误并返回。 { printf("Error 1: ();\n"); return 0; } while(n>0&&*(st + --n)!=‘(‘) //从")"的位置n往回查找"("。 ; if(*(st+n)!=‘(‘) //while语句执行完成,此时n==0; //但是*(st+n)不是"(",则意味着没有匹配的 //"(",输出错误。 { printf("Error 2: ();\n"); return 0; } m=n; //找到"("的话,把n的值保存到m中。 if(m>0 && isdigit(*(st+m-1))) //m位置的上一位不能是数字。 { printf("Error 3: ();\n"); return 0; } if((d-m)==1) //如果"()"为空,输出错误。 { printf("Error 4: ();\n"); return 0; } for(b=0;*(st + ++n)!=‘)‘;b++) //把括号中的内容复制到s2中。 *(s2+b) = *(st + n); *(s2+b)=‘\0‘; i=calc(s2); //计算s2的值,并返回double i。 sprintf(s2,"%g",i); //把i转换成字符串保存至s2中。 //printf("s2 %s\n",s2); repl(st,s2,m,n+1); //使用s2替换st中的括号。 printf("step %s\n",st); //输出替换后的st。 n=-1; //执行下一次循环。 continue; } }
可执行程序下载地址:http://pan.baidu.com/s/1jGiUaYM 。
写的不好,大神勿喷,欢迎指正。
欢迎转载,但是版权所有。
时间: 2024-10-19 00:14:31