用c语言编写的可以计算+-*/的计算器

写了一个计算器程序,想分享给大家;同时写到最后感觉有点凌乱,希望各位帮忙给优化下,共同提高。这个计算器可以计算输入的字符串,字符串中可以含括号,可以是小数,也可以包含负数。此程序被拆分在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

写的不好,大神勿喷,欢迎指正。

欢迎转载,但是版权所有。







本文出自 “阳光之吻” 博客,请务必保留此出处http://kissofsun.blog.51cto.com/9686609/1638044

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。