用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

寫的不好,大神勿噴,歡迎指正。

歡迎轉載,但是版權所有。







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章