📄 calc.c
字号:
/*
http://[2001:4860:c003::84]/search?q=cache:FSQVqd7pmq4J:www.yuanma.org/data/2007/0308/article_2390.htm+calc.c+%E8%AE%A1%E7%AE%97%E5%99%A8&hl=zh-CN&newwindow=1&strip=1
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])));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -