四则运算计算器 C 语言完美版源码
2007-03-08 14:21
302 查看
以下是我刚开始学习 C 语言时实训的作品,感觉还不错。
有什么意见和建议,请联系我:
Email:HeTaoOS#Gmail.com
QQ:28681290
有什么意见和建议,请联系我:
Email:HeTaoOS#Gmail.com
QQ:28681290
/* Calc.c By Null 生成于 200607032000 编号:9 四则运算计算器 一、程序功能简介 可以计算整数四则运算,例如:7+5*(3+4) 二、课程设计要求 (1)按要求在提供的框架程序源程序的基础上对程序进行修改、补充,并调试通过。 (2)修改主程序结构,使程序可以反复运算,直到选择退出为止。 (3)增加文件的输入输出功能,是计算过的式子和结果可以根据需要设置命令存储到文件中,同时也可以直接从文件中输入四则运算的式子,运算后,结果输出到原文件中。 (4)扩充程序功能,使程序适合实型数运算。 (5)增加程序的判断功能,当有非法的输入时(如字母等),给出提示信息并退出运算。 (6)扩充程序功能,使程序可以进行关系表达式(>=,>,<=,<,==等)的运算,运算结果为 TRUE 或 FALSE 。 在 VC++6 环境下编译 已经完美实现上述功能 注: 包含 Debug 的语句 如:if (Debug) printf(""); 都并封装成 Ope 可以忽略, 这些显示是编写工程中需要观察的信息,如果要打开,请在主菜单下输入大写的 'D'。 Log: 20060703 开始分析框架程序,并规划程序结构 20060704 计算的核心部分基本完成,ration() 20060705 编写 Menu_Sel() Do_Press() strChk() Do_File() FileCHK() Nexus() 整体功能和界面基本完成 20060706 强化 strChk(),增加 Debug 模式,修正符号优先级问题。 20060707 郁闷,在英化程序 -_-/// ...在 Do_File() 增加输出文件另存功能... 20060708 .... 20060709 .... 20060710 强化 strChk(),增加结果整形识别,增加 '!=' 处理,文件名非法字符校验。 最后更新 20060710 */ /* =============================================== */ /* 头文件声明 */ #include <stdio.h> /* In Out printf().. */ #include <math.h> /* pow(M,n) 开 M^n */ #include <string.h> /* strcpy... */ #include <stdlib.h> /* atof... */ #include <conio.h> /* getch()... */ #define Max 256 /* 表达式长度定义,可以在这里调节 */ /* =============================================== */ /* 函数声明 */ /* 计算字符串(不带括号的),计算的核心部分*/ char *Calculate_f(char *chpString); /* 主操作过程,输入式子串,返回 double 型结果 */ double Operation(char *chpString); /* Source1、Source2 加起来到 Destination 中*/ char *AddStrings_f(char *chpDestination, char *chpSource1, char *chpSource2); /* 寻找 char_to_find 在 Source 中的位置,后移一位 */ int FindChar(char *chpSource, char chCharToFind); /* 获取字符串的长度 */ int Len_f(char *chpSource); /* 将 Source 左边 Length 个字符放在 Destination 中*/ char *Left_f(char *chpSource, char *chpDestination, int nLength); /* 将 Source 右边 Length 个字符放在 Destination 中*/ char *Right_f(char *chpSource, char *chpDestination, int nLength) ; /* 将 Source 中从 Start 开始 Length 长度的字符串截下来放在 Destination 中*/ char *Midstr_f(char *chpSource, char *chpDestination, int nStart, int nLength); /* 在字符串中删除一个字符 del '+' */ void DelChar(char *chpString,int sPos); /* 在字符串中插入一个字符 */ int InsChar(char *chpString,int sPos,char sChar); /* 替换字符串中的某个字符 */ void StrReplace(char *chpString,char strOld ,char strNew); /* 将实数值变为字符串*/ char *Str_f(double nValue, char *chpDestination); /* 计算字符串的值,返回实数值 */ double Val_f(char *chpSource) ; /* =============================================== */ /* 主菜单... */ int Menu_Sel(); /* 手工输入表达式求值 */ int Do_Press(); /* 文件导入表达式求值 */ int Do_File(); /* 文件检查 0 重新输入,1 继续 */ int FileChk(char *FN); /* 式子的合法性检查 0 含有非法字符,1 正常 2 关系运算 */ int StrChk(char *chpSource); /* 关系运算 */ int Nexus(char strIn[]); /* 显示关于 */ void Show_About(); /* =============================================== */ /* 全局变量声明 */ int Debug=0; /* 调试信息显示开关 0 不显示,1 显示 */ char *TF_Info[3]={"FALSE","TURE","Error"}; /* 关系运算信息 */ /* 将 Source 左边 Length 个字符放在 Destination 中*/ char *Left_f(char *chpSource, char *chpDestination, int nLength) { *(chpDestination+ --nLength+1)=0; /* 设置目标字符串最后一个为 NULL*/ while (nLength>=0) /* 直到目标字符串的最后一个 */ { *(chpDestination+nLength)=*(chpSource+nLength--); } return chpDestination; } /* 将 Source 中从 Start 开始 Length 长度的字符串截下来放在 Destination 中 */ char *Midstr_f(char *chpSource, char *chpDestination, int nStart, int nLength) { chpSource+=nStart-1; /* 设置源起点 */ *(chpDestination+--nLength+1)=0; /* 设置目标字符串最后一个为 NULL */ while (nLength>=0) /* 直到目标字符串的最后一个 */ { *(chpDestination+nLength)=*(chpSource+nLength--); } return chpDestination; } /* 将 Source 右边 Length 个字符放在 Destination 中 */ char *Right_f(char *chpSource, char *chpDestination, int nLength) { while (*chpSource != 0) { chpSource++; } /* 将源指针移到最后 */ chpSource-=nLength; /* 将源指针跳到开始复制点 */ *(chpDestination+--nLength+1)=0; /* 设置目标字符串最后一个为 NULL */ while (nLength>=0) /* 直到目标字符串的最后一个 */ { *(chpDestination+nLength)=*(chpSource+nLength--); } return chpDestination; } /* 在字符串中删除一个字符 del '+' */ void DelChar(char *chpString,int sPos) { char sBuf[Max]; int nCount; strcpy(sBuf,chpString); for(nCount=sPos;sBuf[nCount];nCount++) { sBuf[nCount]=sBuf[nCount+1]; } strcpy(chpString,sBuf); } /* 在字符串中插入一个字符 */ int InsChar(char *chpString,int sPos,char sChar) { char sBuf[Max]; int iLen; int nCount; strcpy(sBuf,chpString); iLen=strlen(sBuf); if(iLen<Max) { sBuf[iLen+1]='/0'; for(nCount=iLen;nCount>=sPos;nCount--) { sBuf[nCount+1]=sBuf[nCount]; } sBuf[sPos]=sChar; strcpy(chpString,sBuf); } else return 0; return 1; } /* 替换字符串中的某个字符 '#' to '-' */ void StrReplace(char *chpString,char strOld ,char strNew) { char sBuf[Max]; int nCount=0; strcpy(sBuf,chpString); while(sBuf[nCount]) { if (sBuf[nCount]==strOld) sBuf[nCount]=strNew; nCount++; } strcpy(chpString,sBuf); } /* 寻找 char_to_find 在 Source 中的位置,后移一位*/ int FindChar(char *chpSource, char chCharToFind) { int nPos=0; while(*(chpSource+nPos)!=0) /* 直到目标字符串的最后一个 */ { if (chCharToFind == *(chpSource+nPos++)) /* 比较.. */ { return nPos; /* 返回第一个出现点,加一 */ } } return 0; } /* 获取字符串的长度 */ int Len_f(char *chpSource) { int nRetval=0; /* 初始化长度 */ while (*(chpSource+nRetval++)!=0){} /* 移动指针到 Null */ return --nRetval; } /* 将实数值变为字符串*/ char *Str_f(double nValue, char *chpDestination) { char strTmp[Max]; gcvt(nValue,sizeof(double)+1,strTmp); /* 实数值转字符串 */ if(strTmp[0]=='-') /* 将 '-' 负号 转译为 '#' */ { strTmp[0]='#'; } strcpy(chpDestination,strTmp); if(Debug) printf("...Conversion Double to String:%f - >%s/n",nValue,chpDestination); return chpDestination; } /* Source1、Source2 加起来到 Destination 中*/ char *AddStrings_f(char *chpDestination, char *chpSource1, char *chpSource2) { char *chpTempdest=chpDestination; while(*chpSource1!=0) /* 先把 chpSource1 放入 chpDestination */ { *(chpTempdest++)=*(chpSource1++); } while(*chpSource2!=0) /* 在 chpDestination 后继续写入 chpSource2 */ { *(chpTempdest++)=*(chpSource2++); } *chpTempdest=0; /* 指针位置归零 */ return chpDestination; } /* 计算字符串的值,返回实数值 */ double Val_f(char *chpSource) { double nResult=0.; char strTmp[Max]; strcpy(strTmp,chpSource); if(strTmp[0]=='#') /* 将 '#' 转译为 '-' 负号 */ { strTmp[0]='-'; } nResult=atof(strTmp); /* 字符串转为实数 */ if(Debug) printf("...Conversion String to Double:%s -> %s -> %f/n",chpSource,strTmp,nResult); return nResult; } /* 计算字符串(不带括号的),计算的核心部分*/ char *Calculate_f(char *chpString) { char szBuf1[Max], szBuf2[Max], szBuf3[Max], szBuf4[Max], szBuf5[Max]; /* buffers for string handlers */ char sOps[2][4]={"^*+","^/-"}; /* 呵呵,符号优先级问题已经解决 */ double nLeftnr; /* 操作符左边的结果 */ double nRightnr; /* 操作符右边的结果 */ double nResult; /* 表达式的结果 */ int nOppos; /* 操作符的位置+1 */ int nOppos2; int nOp=0; /* 用哪一个同级的操作符 */ int nCount; /* 长度计数,就是两个操作符间的内容的长度 */ int nPosInOpstr; /* 操作符索引 */ if(Debug) printf("/n...Starting Calculate, The Parameter is:%s/n", chpString ); for (nPosInOpstr=0; nPosInOpstr<3; nPosInOpstr++) /* 同级关系运算符问题,有待解决 */ { /* szOpstr 中操作符的顺序就是优先级顺序 */ while (FindChar(chpString,sOps[0][nPosInOpstr])!=0||FindChar(chpString,sOps[1][nPosInOpstr])!=0) /* 寻找五种符号,当找不到就退出*/ { /* 提取左边的操作数计算*/ nOppos=FindChar(chpString,sOps[0][nPosInOpstr]); /* 行 0 找到操作符的位置,+1 */ nOppos2=FindChar(chpString,sOps[1][nPosInOpstr]); /* 行 1 找到操作符的位置,+1 */ if(Debug) printf("...Operator Priority Level:nOppos=%d nOppos2=%d nOp=",nOppos,nOppos2); if(nOppos==0) /* 取靠前的,0 是个问题,跳过... */ { nOp=1; nOppos=nOppos2; } else if(nOppos2==0) { nOp=0; } else if(nOppos>nOppos2) { nOp=1; nOppos=nOppos2; } else nOp=0; if(Debug) printf("%d/n",nOp); for (nCount=nOppos-2; nCount>=0; nCount--) /* 向左边查找操作符 */ { if ((*(chpString+nCount)=='+')||(*(chpString+nCount)=='/')||(*(chpString+nCount)=='-')||(*(chpString+nCount)=='*')||(*(chpString+nCount)=='^')) { if ((nCount>1)&&((*(chpString+nCount-1)=='e')||(*(chpString+nCount-1)=='E')||(*(chpString+nCount-1)=='^'))) continue; /* 注意 1e-1 等,'-' 并不是单独的操作符 */ nLeftnr=Val_f(Midstr_f(chpString,&szBuf1[0], nCount+2, nOppos-nCount-2)); /* 符号左边的字符串变为数值*/ nCount=-1; } else if (nCount==0) /* 如果从头开始复制... */ { nLeftnr=Val_f(Left_f(chpString,&szBuf1[0],nOppos-1)); } } if(Debug) printf("...Left Operand:%f/n",nLeftnr); /* 提取右边的操作数计算*/ for (nCount=nOppos;nCount<Len_f(chpString);nCount++) { if ((*(chpString+nCount)=='+')||(*(chpString+nCount)=='/')||(*(chpString+nCount)=='-')||(*(chpString+nCount)=='*')||(*(chpString+nCount)=='^')) { if ((*(chpString+nCount-1)=='e')||(*(chpString+nCount-1)=='E')||(*(chpString+nCount-1)=='^')) continue; /* 注意 1e-1 等,'-' 并不是单独的操作符 */ nRightnr=Val_f(Midstr_f(chpString,&szBuf2[0],nOppos+1,nCount-nOppos)); /* 符号右边的字符串变为数值*/ nCount=Len_f(chpString); } else if (nCount==Len_f(chpString)-1) { nRightnr=Val_f(Right_f(chpString,&szBuf2[0],Len_f(chpString)-nOppos)); } } if(Debug) printf("...Right Operand:%f/n",nRightnr); /* 计算 */ if (sOps[nOp][nPosInOpstr]=='+') /* 加 */ { nResult=nLeftnr+nRightnr; } else if (sOps[nOp][nPosInOpstr]=='-') /* 减 */ { nResult=nLeftnr-nRightnr; } else if (sOps[nOp][nPosInOpstr]=='/') /* 除 */ { nResult=nLeftnr/nRightnr; } else if (sOps[nOp][nPosInOpstr]=='*') /* 乘 */ { nResult=nLeftnr*nRightnr; } else if (sOps[nOp][nPosInOpstr]=='^') /* 次方/开方 */ { nResult=pow(nLeftnr,nRightnr);} /* 组建新的字符串 */ /* 格式AddStrings_f(目标,源1,源2) */ AddStrings_f(&szBuf3[0], Left_f(chpString,&szBuf4[0],nOppos-Len_f(&szBuf1[0])-1), Str_f(nResult,&szBuf5[0])); AddStrings_f(chpString, &szBuf3[0],Right_f(chpString,&szBuf5[0],Len_f(chpString)-nOppos-Len_f(&szBuf2[0]))); if(Debug) printf( "...Scaning:%c,Find:%f%c%f/n...Calculate to a New String:%s/n/n", sOps[nOp][nPosInOpstr], nLeftnr,sOps[nOp][nPosInOpstr], nRightnr,chpString ); } } if(Debug) printf( "...Finish Calculate, The Result is: %s/n/n", chpString); return chpString; } /* 主操作过程,输入式子串,返回 double 型结果,起着移除括号的重任 */ double Operation(char *chpString) { char szStrn[Max],szBuf1[Max],szBuf2[Max],szBuf3[Max],szBuf4[Max]; int nCount, nLastOpen; strcpy(szStrn,chpString); if(Debug) printf( "/n...Starting Bracket Removal Loop.../n"); while(FindChar(&szStrn[0],'(')) { for (nCount=0; nCount<=Len_f(&szStrn[0]); nCount++) /* 不断地查找配对的括号... */ { if (szStrn[nCount]=='(') /* 起始括号 */ { nLastOpen=nCount; /* 最近一个'(' ,是指最接近 ')' 的那个,使之配对*/ } if (szStrn[nCount]==')') /* 如果最近有一个配对的括号,就进入计算 */ { /* 将括号内的字符串打印出来 */ if(Debug) printf("...In %s Find %s, Calling Calculate Unit.../n",szStrn,Midstr_f(&szStrn[0],&szBuf1[0],nLastOpen+2,nCount-nLastOpen-1)); /* 将括号中的结果计算出来,连同括号左边的字符串形成新的字符串放入缓冲区,再与括号右边的字符串形成新的字符串 */ /* 复合形式...有点难看懂.. 和 Calculate_f 中的基本一样 */ AddStrings_f(&szStrn[0],AddStrings_f(&szBuf1[0],Left_f(&szStrn[0],&szBuf3[0],nLastOpen), Calculate_f(Midstr_f(&szStrn[0],&szBuf4[0],nLastOpen+2,nCount-nLastOpen-1))), Right_f(&szStrn[0],&szBuf2[0],Len_f(&szStrn[0])-nCount-1)); if(Debug) printf("...New String: %s/n", szStrn); nCount=Len_f(&szStrn[0])+1; /* 移动当前指向... */ } } } if(Debug) printf("...Brackets Removed, Final String is:%s, Calculating.../n", szStrn); /* 计算剩余的式子 */ Calculate_f(&szStrn[0]); if (szStrn[0] == 0) { szStrn[0]='0'; szStrn[1]=0; } if(Debug) printf("...Finish Expression Calculate./n"); return Val_f(szStrn); /* 返回计算结果 */ } /* 式子的合法性检查 0 含有非法字符,1 正常 2 关系运算 */ int StrChk(char *chpSource) { char strIn[Max]; /* 源 */ char strTmp; /* 单个字符 */ int nCount=0; int LB=0,RB=0; /* 括号计数变量 */ int nNexus=0; int iLen; strcpy(strIn,chpSource); iLen=strlen(strIn); /* 开头符号合法性检查 */ strTmp=strIn[0]; if(strTmp=='+') /* 移除多余的 '+' */ { DelChar(strIn,0); iLen--; } if(strTmp=='*'||strTmp=='/'||strTmp=='e'||strTmp=='E'||strTmp=='^'||strTmp==')'||strTmp=='='||strTmp=='>'||strTmp=='<') { printf("In %s Head Find Illegal Char:%c,",strIn,strTmp); /* 其实可以去掉非法字符在判断的... */ return 0; } /* 返回错误信息 */ /* 结尾符号合法性检查 */ strTmp=strIn[strlen(strIn)-1]; if((strTmp>='0'&&strTmp<='9')||strTmp==')'); /* 注意,有个分号的 */ else { printf("In %s End Find Illegal Char:%c,",strIn,strTmp); /* 其实可以去掉非法字符在判断的... */ return 0; } for(nCount=0;strIn[nCount];nCount++) /* 检查是否有非法字符 */ { strTmp=strIn[nCount]; if((strTmp>='0'&&strTmp<='9'||strTmp=='+'||strTmp=='-'||strTmp=='*'||strTmp=='/'||strTmp=='.'||strTmp=='e'||strTmp=='E'|| strTmp=='^'||strTmp=='('||strTmp==')'||strTmp=='='||strTmp=='>'||strTmp=='<'||strTmp=='#'||strTmp=='!')) { /* 展示可能出现的字符 */ if(strTmp=='='||strTmp=='>'||strTmp=='<'||strTmp=='!') { /* 检查关系操作符 */ if(strTmp!='!') /* != 检查,这样不利于以后的拓展 */ { nNexus=1; /* Pass */ } else { if (strIn[nCount+1]!='=') { printf("In %s Find /'!/',But The Next Char NOT /'=/',",strIn); return 0; } else if (strIn[nCount-1]=='='||strIn[nCount-1]=='>'||strIn[nCount-1]=='<') { printf("In %s Find /'!/',But The Previous Char IS /'%c/',",strIn,strIn[nCount-1]); return 0; } } } continue; } printf("In %s Find Illegal Char:%c,",strIn,strTmp); /* 其实可以去掉非法字符在判断的... */ return 0; /* 返回错误信息 */ } /* 表达式的修复处理 */ for(nCount=0;strIn[nCount];nCount++) { strTmp=strIn[nCount]; /* 括号修复 */ if(strTmp=='('||strTmp==')') { if (strTmp=='(') LB++; else RB++; if(LB<RB) { InsChar(strIn,0,'('); LB++; nCount++; iLen++; if(Debug) printf("...Add a Left Bracket./n"); } } } LB=0; RB=0; /* 复位很重要,或者重新定义 */ for(nCount=0;strIn[nCount];nCount++) { strTmp=strIn[nCount]; /* 括号计数 */ if(strTmp=='(') LB++; if(strTmp==')') RB++; } if (LB!=RB) /* 判断括号的对称性 */ { if(abs(LB-RB)<Max-iLen) /* 添加括号前,判断是否会越界 */ { if(LB>RB) /* 右括号配对 */ { for(nCount=0;nCount<LB-RB;nCount++) { InsChar(strIn,iLen,')'); /* 在最右边插入 ')' */ iLen++; } if(Debug) printf("...The Result of Right Bracket Partnership:%s/n",strIn); } else if(LB<RB) /* 左括号配对 */ { for(nCount=0;nCount<RB-LB;nCount++) { InsChar(strIn,0,'('); /* 在最左边插入 '(' */ } if(Debug) printf("...The Result of Left Bracket Partnership:%s/n",strIn); } } else { printf("Bracket NOT Partnership:%s/n",strIn); return 0; } } /* 补上 '(' 前的 '*' 以及处理后一个非法字符*/ for(nCount=1;strIn[nCount];nCount++) { if (strIn[nCount]=='(') { strTmp=strIn[nCount+1]; /* 取后一个字符 */ if(strTmp=='*'||strTmp=='/'||strTmp=='e'||strTmp=='E'||strTmp=='^'||strTmp=='<'||strTmp=='>'||strTmp=='='||strTmp==')') { printf("Find Err Operator In:%s,",strIn); return 0; } strTmp=strIn[nCount-1]; /* 取前一个字符 */ if(strTmp>='0'&&strTmp<='9'||strTmp==')') { InsChar(strIn,nCount,'*'); nCount++; if(Debug) printf("...The Result of Plus Operator /'*/':%s/n",strIn); } } } /* 补上 ')' 后的 '*' */ for(nCount=1;strIn[nCount];nCount++) { if (strIn[nCount]==')') { strTmp=strIn[nCount-1]; /* 取前一个字符 */ if(strTmp=='*'||strTmp=='/'||strTmp=='e'||strTmp=='E'||strTmp=='^'||strTmp=='<'||strTmp=='>'||strTmp=='='||strTmp=='(') { printf("Find Err Operator In:%s,",strIn); return 0; } strTmp=strIn[nCount+1]; /* 取后一个字符 */ if(strTmp>='0'&&strTmp<='9'||strTmp=='(') { InsChar(strIn,nCount,'*'); nCount++; if(Debug) printf("...The Result of Add Operator /'*/':%s/n",strIn); } } } /* 移除多余的 '+' */ for(nCount=1;strIn[nCount];nCount++) { if (strIn[nCount]=='+') { strTmp=strIn[nCount-1]; /* 取前一个字符,如果是下列字符,这判正号 */ if(strTmp=='+'||strTmp=='-'||strTmp=='*'||strTmp=='/'||strTmp=='e'||strTmp=='E'||strTmp=='^'||strTmp=='('||strTmp=='<'||strTmp=='>'||strTmp=='=') { DelChar(strIn,nCount); iLen--; if(Debug) printf("...The Result of Conversion Add /'+/' to /'0/':%s/n",strIn); strTmp=strIn[nCount+1]; /* 取后一个字符,过滤三重字符 -Plus*/ if(strTmp=='+'||strTmp=='-'||strTmp=='*'||strTmp=='/'||strTmp=='e'||strTmp=='E'||strTmp=='^'||strTmp=='('||strTmp=='<'||strTmp=='>'||strTmp=='=') { printf("Have Overmany Operator In:%s,",strIn); return 0; } } } } /* 将 '-' 负号替换为 '#' */ if(strIn[0]=='-') strIn[0]='#'; for(nCount=1;strIn[nCount];nCount++) { if (strIn[nCount]=='-') { strTmp=strIn[nCount-1]; /* 取前一个字符,如果是下列字符,这判负号 */ if(strTmp=='+'||strTmp=='-'||strTmp=='*'||strTmp=='/'||strTmp=='e'||strTmp=='E'||strTmp=='^'||strTmp=='('||strTmp=='<'||strTmp=='>'||strTmp=='=') { strIn[nCount]='#'; if(Debug) printf("...The Result of Conversion Minus /'-/' to /'#/':%s/n",strIn); strTmp=strIn[nCount+1]; /* 取后一个字符,过滤三重字符 -Plus*/ if(strTmp=='+'||strTmp=='-'||strTmp=='*'||strTmp=='/'||strTmp=='e'||strTmp=='E'||strTmp=='^'||strTmp=='('||strTmp=='<'||strTmp=='>'||strTmp=='=') { printf("Have Overmany Operator In:%s,",strIn); return 0; } } } } /* 重叠符号检查 */ for(nCount=1;strIn[nCount];nCount++) { strTmp=strIn[nCount]; if (strTmp=='+'||strTmp=='-'||strTmp=='*'||strTmp=='/'||strTmp=='^') { strTmp=strIn[nCount+1]; /* 取前一个字符,如果是下列字符,这判负号 */ if(strTmp=='+'||strTmp=='-'||strTmp=='*'||strTmp=='/'||strTmp=='^') { printf("Find Double Operator %c and %c,",strIn[nCount],strTmp); return 0; } } } strcpy(chpSource,strIn); return 1+nNexus; /* 通过合法检查 */ } /* 传说中的主函数 */ int main(int argc, char *argv[]) { Debug=0; /* Debug 调试开关 */ if (argc>1) /* 调试信息显示开关 */ { Debug=!strcmp("/debug",argv[1]); /* 设置调试开关参数为 /debug */ if(Debug) { system("cls"); printf("/n/t/t/t/t == NOTE ==/n"); printf("/t/t * Debugging Information Has Opened */n"); printf("/t * These Messages Primarily to the Process of Debugging Phase */n"); printf("/t* This Information Reflects the Detailed Process of Calculating */n"); printf("/t/t/t/t * NULL */n"); printf("/n"); } } for(;;) { switch (Menu_Sel()) /* 返回选择的项目序号 */ { case 0: case -21:case 'E'-'0': case 'e'-'0': case 'X'-'0': case 'x'-'0': /* 退出 */ printf("/n/n/t/t Thank You Use ^_^ .../n"); getch(); return 0; case 1: case 'P'-'0': case 'p'-'0': /* 手工输入 */ Do_Press(); break; case 2: case 'L'-'0': case 'l'-'0': /* 导入文件 */ Do_File(); break; case 3: case 'C'-'0': case 'c'-'0': /* 清屏 */ system("cls"); break; case 4: case 'A'-'0': case 'a'-'0': /* 显示关于 */ Show_About(); break; case 20: /* 调试信息显示控制开关,隐藏的 */ if(Debug) /* 由大写的字母 'D' */ { printf("/n/n/t************ Debugging Information Are Closed ************/n/n"); Debug=0; } else { printf("/n/n/t************ Debugging Information Has Opened ************/n/n"); Debug=1; } } } } /* 显示关于 */ void Show_About() { system("cls"); printf("/n/t/t/t Expression Calculator V0.2/n"); printf("/n/tFunctional Profiles:/n"); printf("/t1.Support Real-Mathematical Operations,ect.:7+5(3^-1+4)*(1+9.44/n"); printf("/t2.Support Relations Operations,ect.:4+8.45>=3456.1234+233^-2.94/n"); printf("/t3.Support Save the Expression and Results to File/n"); printf("/t4.Support Load Expression for Calculate From File/n"); printf("/t5.Support Humanization Guide Mode/n"); printf("/t----------------------------------------------------/n"); printf("/n/tProgrammer:He Tao ID:0505030321 Nickname:Null/n"); printf("/n/tFor Further Suggestions and Comments, Please Contact/n"); printf("/tEmail:HeTaoOS@Gmail.com QQ:28681290/n"); printf("/tWelcome to Visit/n"); printf("/thttp://HeTaoOS.GooglePages.com/n"); printf("/thttp://Blog.VeryCD.com/hetaoos/n"); printf("/t----------------------------------------------------/n"); getch(); } /* 显示主菜单... */ int Menu_Sel() { char Sel; int MaxItem=4; printf("/n/t/t Expression Calculator/n"); printf("/t/t ===================================/n"); printf("/t/t | 1.[P]ress an Expression |/n"); printf("/t/t | 2.[L]oad Expression From File |/n"); printf("/t/t | ----------------------------- |/n"); printf("/t/t | 3.[C]lear Screen |/n"); printf("/t/t | 4.[A]bout ME |/n"); printf("/t/t | 0.[E]xit |/n"); printf("/t/t ===================================/n"); printf("/t/t Press a Key to Continue(0-%d):",MaxItem); for (;;) { Sel=getch(); if ((Sel<'0'||Sel>MaxItem+'0')&&Sel!='D'&&Sel!='P'&&Sel!='p'&&Sel!='L'&&Sel!='l'&&Sel!='C'&&Sel!='c'&& Sel!='A'&&Sel!='a'&&Sel!='E'&&Sel!='e'&&Sel!='X'&&Sel!='x'&&Sel!=27) { /* 输入范围检查 */ printf("/n/t/t Press Error! Please Retry(0-%d):",MaxItem); } else break; } return Sel-'0'; } /* 手工输入表达式求值 */ int Do_Press() { char sel; int WF=0; /* 文件写入开关 */ char FN[256]; /* 文件名 */ char strExp[Max]; /* 要计算的表达式 */ double strRes; /* 计算结果 */ int TF=0; /* 真假判断 */ int strChk_Re=0; FILE *fp; printf("/nWhether Save The Expression and Result to File(Y/N)?"); scanf("%s",&sel); /* 保存到文件 */ if(sel=='Y'||sel=='y') { WF=1; for(;;) { printf("Press a File Name for Save Log(Press /'`/' to Exit):"); scanf("%s",FN); if(FN[0]=='`') /* 设置取消陷阱 */ { WF=0; printf("/nYou Cancelled Save Log Operation!/n"); break; } if (FileChk(FN)) /* 文件检查 */ { fp=fopen(FN,"a"); break; } } } for(;;) { printf("Please Press an Expression(Press a /'`/' to Exit):/n"); scanf("%s",strExp); if(strExp[0]=='`') break; /* 设置取消陷阱 */ strChk_Re=StrChk(strExp); if(strChk_Re==0) /* 错误退出 */ { printf("NO Activate Calculation.../n"); } else if(strChk_Re==1) /* 表达式计算 */ { strRes=Operation(strExp); StrReplace(strExp,'#','-'); if((long int)strRes==strRes) /* 呵呵,去掉小数点 */ { if(Debug) printf("...Conversion Double to Long Int./n"); printf("/n%s=%ld/n",strExp,(long int)strRes); if(WF) fprintf(fp,"%s=%ld/n",strExp,(long int)strRes); } else { printf("/n%s=%f/n",strExp,strRes); if(WF) fprintf(fp,"%s=%f/n",strExp,strRes); } } else /* 表达式关系判断 */ { TF=Nexus(strExp); /* 调用判断函数判断 */ StrReplace(strExp,'#','-'); printf("/n%s --> %s/n",strExp,TF_Info[TF]); if(WF) fprintf(fp,"%s --> %s/n",strExp,TF_Info[TF]); } getch(); } if(WF) fclose(fp); return 0; } /* 文件导入表达式求值 */ int Do_File() { char iFN[256]; /* 输入文件名 */ char oFN[256]; /* 临时文件名 */ FILE *ifp,*ofp; double strRes; /* 计算结果 */ char strExp[Max]; /* 读取的字符串,也就是要计算的字符串 */ int TF=0; /* TRUE FALSE Error 索引*/ int OutOther=0; /* 输出到其它文件开关 */ int strChk_Re; for(;;) { printf("/nPlease Press a File Name to Open(Press a /'`/' to Exit):/n"); /* 输入要打开的文件名 */ scanf("%s",iFN); if(iFN[0]=='`') return 0; ifp=fopen(iFN,"r"); if(ifp==0) /* 文件存在检查 */ { printf("File %s NOT Exist or Open Error!/n",iFN); } else break; } for(;;) { printf("/nPlease Press a File Name To Save(Press a /'`/' to Save to %s):/n",iFN); /* 输入要打开的文件名 */ scanf("%s",oFN); if(oFN[0]=='`') { strcpy(oFN,iFN); /* 临时文件名,以及打开它 */ strcat(oFN,".null"); ofp=fopen(oFN,"w"); OutOther=0; break; } else { if (FileChk(oFN)) { ofp=fopen(oFN,"a"); OutOther=1; break; } } } while(feof(ifp)==0) /* 如果没有读到文件尾 */ { fscanf(ifp,"%s/n",strExp); /* 逐行读取文件内容 */ strChk_Re=StrChk(strExp); if(strChk_Re==0) /* 合法性检查 */ { printf("Fall Across Illegal Char.../n"); fprintf(ofp,"%s Include Illegal Char, Can't Calculate!/n",strExp); } else if(strChk_Re==1) /* 表达式计算 */ { strRes=Operation(strExp); /* 计算 */ StrReplace(strExp,'#','-'); if((long int)strRes==strRes) /* 呵呵,去掉小数点及其后的 '0' */ { if(Debug) printf("...Conversion Double to Long Int./n"); printf("/n%s=%ld/n",strExp,(long int)strRes); fprintf(ofp,"%s=%ld/n",strExp,(long int)strRes); } else { printf("/n%s=%f/n",strExp,strRes); /* 屏幕打印 */ fprintf(ofp,"%s=%f/n",strExp,strRes); /* 打印输出到文件 */ } } else /* 表达式关系判断 */ { TF=Nexus(strExp); StrReplace(strExp,'#','-'); printf("/n%s --> %s/n",strExp,TF_Info[TF]); fprintf(ofp,"%s --> %s/n",strExp,TF_Info[TF]); } } fclose(ifp); /* 关闭文件 */ fclose(ofp); if(OutOther) { printf("/nFile %s Operation Completed and The Result Save to %s.../n",iFN,oFN); } else { remove(iFN); /* 删除文件 */ rename(oFN,iFN); /* 重命名文件 int rename(const char *oldname, const char *newname); */ printf("/nFile %s Operation Completed.../n",iFN); } getch(); return 0; } /* 文件检查 0 重新输入,1 继续 */ int FileChk(char FN[]) { FILE *fp; char sel; int nCount=0; for(;FN[nCount];nCount++) /* 文件名合法检查 '/' 不好过滤...*/ { if(FN[nCount]=='/'||FN[nCount]==':'||FN[nCount]=='*'||FN[nCount]=='?'||FN[nCount]=='/"'||FN[nCount]=='<'||FN[nCount]=='>'||FN[nCount]=='|') { printf("File Name %s Include Illegal Char /'%c/',Please Press a New One!/n",FN,FN[nCount]); return 0; } } fp=fopen(FN,"r"); if(fp==0) /* 文件存在检查 */ { fp=fopen(FN,"w"); /* 创建文件 */ if(fp==0) /* 创建检查 */ { printf("File %s Create Failure!/n",FN); return 0; /* 不可修复错误 */ } fclose(fp); return 1; /* 成功提示 */ } fclose(fp); printf("File %s Already Exist,Rewrite or Cancel or Append(Y/N/A)?",FN); /* 文件存在了... */ scanf("%s",&sel); if(sel=='Y'||sel=='y') /* 覆盖 */ { fp=fopen(FN,"w"); /* 覆盖检查 */ if(fp==0) { printf("File %s Rewrite Failure!/n",FN); return 0; } fclose(fp); return 1; } else if(sel=='A'||sel=='a') /* 允许追加 */ { return 1; } else /* 返回... */ { return 0; } } /* 关系运算 */ int Nexus(char strIn[]) { int nCount=0; /* 循环索引 '>'=1 '<'=2 '='=4 '!'=8 */ char strTmp; char strBuf[Max]; int iNexus=0; /* 符号代码 */ double strRes1; /* 分步结果 */ double strRes2; /* 符号代码 */ for(;strIn[nCount];nCount++) { strTmp=strIn[nCount]; if(strTmp=='>'||strTmp=='<'||strTmp=='='||strTmp=='!') { Left_f(strIn,strBuf,nCount); /* 提取字符串 */ if(StrChk(strBuf)!=1) /* 二次检查 */ { iNexus=0; break; } strRes1=Operation(strBuf); /* 存储结果 */ iNexus=0; /* 初始化符号代码 */ if(strTmp=='>') iNexus++; /* 符号代码调整 */ else if(strTmp=='<') iNexus+=2; else if(strTmp=='=') iNexus+=4; else iNexus+=8; strTmp=strIn[nCount+1]; /* 取下一个字符 */ if(strTmp=='>'||strTmp=='<'||strTmp=='=') { /* 符号代码调整 */ if(strTmp=='>') iNexus++; else if(strTmp=='<') iNexus+=2; else iNexus+=4; nCount++; /* 移动索引号 */ } Right_f(strIn,strBuf,strlen(strIn)-nCount-1); if(StrChk(strBuf)!=1) /* 二次检查 */ { iNexus=0; break; } strRes2=Operation(strBuf); break; } } switch(iNexus) /* 关系比较 */ { case 1: /* > */ if(strRes1>strRes2) return 1; else return 0; case 2: /* < */ if(strRes1<strRes2) return 1; else return 0; case 4: case 8: /* =,== */ if(strRes1==strRes2) return 1; else return 0; case 3: case 12: /* <> != */ if(strRes1!=strRes2) return 1; else return 0; case 5: /* >= */ if(strRes1>=strRes2) return 1; else return 0; case 6: /* <= */ if(strRes1<=strRes2) return 1; else return 0; default: /* 出错,唉,如果发现多组关系运算符就... */ return 2; } }
相关文章推荐
- java语言的科学与艺术-编程练习---简单的四则运算计算器
- 使用JS做简单的四则运算的计算器
- 第五次作业——计算器(增加一种读取四则运算表达式的方式)
- php实现一个简单的四则运算计算器
- 利用ANTLR4实现一个简单的四则运算计算器
- 一个简单的四则运算计算器
- 四则运算 C 语言
- 一个逆波兰表达式实现的四则混合运算计算器
- 【C/C++学院】(14)QT布局/四则运算计算器
- 四则运算计算器
- java:四则混合运算,模拟微软的计算器
- 第五次作业——计算器(增加一种读取四则运算表达式的方式)
- 【年少的风】GUI计算器--四则混合运算
- 支持四则运算的计算器的实现算法
- 【实践】js实现简易的四则运算计算器
- Android开发入门实例:四则混合运算计算器
- qt用设计器实现简单四则运算计算器
- 字符串四则运算(计算器)
- 一个非常酷的Js计算器(加减乘除,浮点,以及括号运算,四则混合运算)
- 正则表达式实现的加减乘除四则运算的计算器