寫了一個計算器程序,想分享給大家;同時寫到最後感覺有點凌亂,希望各位幫忙給優化下,共同提高。這個計算器可以計算輸入的字符串,字符串中可以含括號,可以是小數,也可以包含負數。此程序被拆分在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 。
寫的不好,大神勿噴,歡迎指正。
歡迎轉載,但是版權所有。