/*
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

posted on 2007-01-05 12:51  mbskys  阅读(2240)  评论(0)    收藏  举报