写了一个计算器程序,想分享给大家;同时写到最后感觉有点凌乱,希望各位帮忙给优化下,共同提高。这个计算器可以计算输入的字符串,字符串中可以含括号,可以是小数,也可以包含负数。此程序被拆分在5个文件中,我按文件一一罗列吧:
编写环境:VC++6.0。
第一个main函数所在文件:
#include
#include
#include
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
#include
#include
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
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
#include
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
#include
#include
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;
}
}
写的不好,大神勿喷,欢迎指正。
欢迎转载,但是版权所有。