有网友碰到这样的问题“设计一个四则运算的程序,从键盘输入计算式如:5*6-7+8/2= ,按从左到右计算输出”。小编为您整理了以下解决方案,希望对您有帮助:
解决方案1:
*//* =============================================== *//* 头文件声明 */#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=='=')