/*
Calc.c By Null 生成于 200607032000
编号:9
四则运算计算器
一、程序功能简介
可以计算整数四则运算,例如:7+5*(3+4)
二、课程设计要求
(1)按要求在提供的框架程序源程序的基础上对程序进行修改、补充,并调试通过。
(2)修改主程序结构,使程序可以反复运算,直到选择退出为止。
(3)增加文件的输入输出功能,是计算过的式子和结果可以根据需要设置命令存储到文件中,同时也可以直接从文件中输入四则运算的式子,运算后,结果输出到原文件中。
(4)扩充程序功能,使程序适合实型数运算。
(5)增加程序的判断功能,当有非法的输入时(如字母等),给出提示信息并退出运算。
(6)扩充程序功能,使程序可以进行关系表达式(>=,>,<=,<,==等)的运算,运算结果为 TRUE 或 FALSE 。
在 VC++6 环境下编译
已经完美实现上述功能
注:
包含 Debug 的语句 如:if (Debug) printf(""); 都可以忽略,
这些显示是编写工程中需要观察的信息,如果要打开,请在主菜单下输入大写的 'D'。
Log:
20060703 开始分析框架程序,并规划程序结构
20060704 计算的核心部分基本完成,并封装成 Operation()
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;
}
}
http://hi.baidu.com/hetaoos/blog/item/d186b209bd2ebd246b60fb83.html
浙公网安备 33010602011771号