| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 5931 人关注过本帖, 2 人收藏
标题:算术表达式计算器
取消只看楼主 加入收藏
seaisland
Rank: 1
等 级:新手上路
帖 子:15
专家分:0
注 册:2007-11-27
收藏(2)
 问题点数:0 回复次数:1 
算术表达式计算器
算术表达式计算器

       这是用C语言写的一个计算器,功能有点简单,只能对算术表达式进行计算! 源程序在VC++6.0下编译通过.           有兴趣的网友,可以下载测试一下.

       设计的主要思路是:在只将表达式扫描一遍的条件下,运用一个能提取出一个数据项和一个符号项的函数,通过循环调用这个函数,并利用栈操作函数,实现对表达式的计算.对括号匹配的处理是用一个计数器变量,出现左括号加1,出现右括号减1,值为0说明括号匹配.

       在给出源程序之前,先介绍一下,几个比较重要的函数.

       函数 getexp
       这个函数的原型是:int getexp(double *data,char *); 它能够提取出表达式中的数据项和符号项,对这个函数的调用,至少能提取出一个符号项, 根据提取的项不同,其返回值从1到8有个;返回负数表示在提取的过程中有错误;对负数的处理是;除了第一项的负数外,其它的负数必须用括号括起来;        

       函数 PopData , PushData , PopOprt ,PushOprt
       这四个函数分别实现数据入栈\出栈,操作符入栈\出栈;

       函数 calculat
       原型是: int calculat(double data1,char oprt,double data2);能对两个数据根据oprt 进行计算,计算出现错误返回负数,否则返回正数;

       函数 checkgram
       原型是:int checkgram(int fsitua,int lsitua);配合getexp的返回值使用,对表达式进行语法检查;

       函数 priority
       原型是:int priority(char cal1,char cal2);比较操作符的优先级,为了保持一致性,把'\0'和括号也看作操作符;

       函数 char_to_double
       原型:double char_to_double(char DigitString[],int markpot,int markend);将字符串转变成双精度数;


       下面是源
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#define MAX_DATA_BIT 100
#define YES 1
#define NO 0
#define POINT_UNEXIST -15
#define MAXSIZE 100
int EXP_INIT=YES;
int BRACKET_COUNT=0;

//标识运算符,不包括括号
int iscalchar(char c);
//标识空白字符,不包括换行符
int is_space(char c);
//标识表达式第一个合法字符
int isFIRSTallow(char c);
//标识表达式的合法字符
int isallow(char c);
//函数,将字符串转换成双精度数
double char_to_double(char DigitString[],int markpot,int markend);
//得到表达式的首项,并检查字符是否合法
int getexp(double *data,char *oprt);
typedef struct
{
    char oprt_stack[MAXSIZE];
    double data_stack[MAXSIZE];
    char oprt_in,oprt_out,*oprt_curp;
    double data_in,data_out,*data_curp;
}stack;
/*   一组栈操作函数        */
/*操作成功返回1,失败返回0  */
int PopData(stack *p);
int PushData(stack *p);
int PopOprt(stack *p);
int PushOprt(stack *p);
void clear(stack *p);
//语法检查函数,返回2表示表达式结束
int checkgram(int fsitua,int lsitua);
//功能函数,比较两个运算符的优先级
int priority(char cal1,char cal2);
//错误处理函数,丢弃出错后所有字符,并打印出错信息
void error(int state);
//计算函数,有发现简单逻辑错误的功能
int calculat(double data1,char oprt,double data2,double *result);
stack STK;
void main()
{
    int FState,LState,GramState,CalcuState;
    double result,TempData;
    char TempOprt;
    STK.data_curp=STK.data_stack;
    STK.oprt_curp=STK.oprt_stack;
   
    while(1){
        
        clear(&STK);
        EXP_INIT=YES;
        BRACKET_COUNT=0;
        LState=100;
        GramState=1;
        CalcuState=1;
        printf("input express> ");
        
        do{
            
            FState=LState;
            if((LState=getexp(&STK.data_in,&STK.oprt_in))<0){
                error(LState);
                break;
            }
            if((GramState=checkgram(FState,LState))<0){
                error(GramState);
                break;
            }
            
            //-------------对表达式的计算------------------------------------------------------
            if(LState==1||LState==2||LState==3||LState==4)
                PushData(&STK);
            if(LState==2||(LState==6&&(FState==3||FState==7))){
                TempOprt=STK.oprt_in;
                STK.oprt_in='*';
            }
            while(priority(*(STK.oprt_curp),STK.oprt_in)>0
                && *STK.oprt_curp!='(' && STK.oprt_curp!=STK.oprt_stack){
                PopData(&STK);
                TempData=STK.data_out;
                PopData(&STK);
                PopOprt(&STK);
                CalcuState=calculat(STK.data_out,STK.oprt_out,TempData,&result);
                if(CalcuState<0) break;
                STK.data_in=result;
                PushData(&STK);
               
            }
            if(*STK.oprt_curp=='(' && (LState==3||LState==7)) PopOprt(&STK);
            if(!(LState==3||LState==4||LState==7||LState==8)) PushOprt(&STK);
            if(LState==2||(LState==6&&(FState==3||FState==7))){
                STK.oprt_in=TempOprt;
                PushOprt(&STK);
            }
            
            if(CalcuState<0){
                error(CalcuState);
                break;
            }
        }while (LState!=4&&LState!=8);

        if((LState==4||LState==8)&&BRACKET_COUNT!=0) error(-8);
        
        if((LState==4||LState==8) && BRACKET_COUNT==0 && GramState>0 && CalcuState>0 && FState+LState!=108)
            printf("the result is: %f\n",STK.data_in);
               
        putchar('\n');
        if(STK.oprt_in!='\n') while(getchar()!='\n');
        STK.oprt_in='\0';
    }
}

int isoprt( char c)
{
    if (c=='+'||c=='-'||c=='*'||c=='/'||c=='^')
        return 1;
    else
        return 0;
}
int is_space(char c)
{
    if (c==' '||c=='\t'||c=='\v')
        return 1;
    else
        return 0;
}
int isFIRSTallow(char c)
{
    if (c=='.'||c=='-'||c=='('||isdigit(c))
        return 1;
    else
        return 0;
}
int isallowed(char c)
{
    if (c=='.'||isoprt(c)||c=='('||isdigit(c)||c==')')
        return 1;
    else
        return 0;
}
double char_to_double(char data[],int markpot,int markend)
{
    int i;
    double sumz=0,sumf=0;
    if (data[0]!='-'){
        for (i=0;i<markpot;++i)
            sumz=sumz*10+(data[i]-'0');
        for (i=markend-1;i>markpot;--i)
            sumf=sumf*0.1+(data[i]-'0');
        return sumz+sumf*0.1;
    }
    else
        {
        for (i=1;i<markpot;++i)
            sumz=sumz*10+(data[i]-'0');
        for (i=markend-1;i>markpot;--i)
            sumf=sumf*0.1+(data[i]-'0');
        return -(sumz+sumf*0.1);
    }
}

int getexp (double *data,char *oprt)
{
    int c,i=0,mrkpot=POINT_UNEXIST;
    char temp[MAX_DATA_BIT];
    while (is_space(c=getchar()));
    if (c=='\n') {*oprt=c;return 8;}
    if (!isallowed(c)) return -1;
    if (EXP_INIT==YES) {
        if(!isFIRSTallow(c)) return -4;
        if(c=='('){++BRACKET_COUNT;*oprt=c;return 6;}
        else{
            temp[i]=c;
            if (c=='.') mrkpot=i;
            ++i;
        }
    }
    else {
        if (!isallowed(c)) return -1;
        if (c=='(') {
            ++BRACKET_COUNT;
            *oprt=c;
            EXP_INIT=YES;
            return 6;
        }
        if (c==')') {
            --BRACKET_COUNT;
            *oprt=c;
            return 7;
        }
        if (isoprt(c)) {
            *oprt=c;
            return 5;
        }
        else {
            temp[i]=c;
            if (c=='.') mrkpot=i;
            ++i;
        }
    }

    //期望等到一个完整的数据项************************
    while ((isdigit(c=getchar())||c=='.') && i<MAX_DATA_BIT){
        if (c=='.'&&mrkpot!=POINT_UNEXIST) return -2;
        else {
            temp[i]=c;
            if (c=='.') mrkpot=i;
            ++i;
        }
    }
    //**************************************************   

    if (i==1&&!isdigit(temp[0])||i==2&&!isdigit(temp[0])&&!isdigit(temp[1])) {*oprt=c;return -2;}
    if(i==MAX_DATA_BIT&&(isdigit(c)||c=='.')) {*oprt=c;return -3;}//返回值还需要进行字符常量化
    if (mrkpot==POINT_UNEXIST) mrkpot=i;
    *data=char_to_double (temp,mrkpot,i);
    EXP_INIT=NO;
    if (is_space(c)) while (is_space(c=getchar()));
    if (c=='\n') {*oprt=c;return 4;}
    if (!isoprt(c)&&c!='('&&c!=')') {*oprt=c;return -1;}
    *oprt=c;
    if (isoprt(c)) return 1;
    if (c=='(') {
        ++BRACKET_COUNT;
        EXP_INIT=YES;
        return 2;
    }
    else {
        --BRACKET_COUNT;
        return 3;
    }
}
int priority (char cal1,char cal2)
{
    if (cal1=='\0'||cal1=='('||cal2=='('||cal2=='^'||((cal2=='*'||cal2=='/')&&(cal1=='+'||cal1=='-')))
        return -1;
    else
        return 1;
}
void error (int state)
{
   
    if (state==-1)
        printf("表达式出现不合法字符!\n");
    else if(state==-2)
        printf("表达式有不合法数据项!\n");
    else if(state==-3)
        printf("表达式中数据太大了!\n");
    else if(state==-4)
        printf("表达式有语法错误!\n");  
    else if(state==-5)
        printf("表达式逻辑错误\n除数不能为0!\n");
    else if(state==-6)
        printf("表达式逻辑错误\n幂运算错误!\n");
    else if(state==-7)
        printf("栈操作失败,表达式可能太长!\n");
    else if(state==-8){
        printf("表达式的括号不匹配!");
    }
}
int calculat (double data1,char calchar,double data2,double *result)
{
    switch(calchar){
        case '+':*result=data1+data2;return 1;
        case '-':*result=data1-data2;return 1;
        case '*':*result=data1*data2;return 1;
        case '/':if (data2!=0.0) {*result=data1/data2;return 1;}
            else return -5;
        case '^':if (data2>0.0||data1!=0) {*result=pow(data1,data2);return 1;}
            else return -6; /*没有零的零次方*/
    }
}
int checkgram (int fsitua,int lsitua) //返回-20表示表达式结束
{        
    switch (fsitua)
    {
        case 1:case 5:if (lsitua==1||lsitua==2||lsitua==3||lsitua==4||lsitua==6) return 1;
               else return -4;
        case 2: case 6:if (lsitua==1||lsitua==2||lsitua==3||lsitua==6) return 1;
               else return -4;
        case 3: case 7:if (lsitua==5||lsitua==6||lsitua==7||lsitua==8) return 1;
               else return -4;
        default:return 1;
    }
}

int PopData(stack *p)
{
    if (p->data_curp == p->data_stack) return -1;
    else {
        p->data_out = *p->data_curp;
        *p->data_curp=0;
        p->data_curp--;
        return 1;
    }
}
int PushData(stack *p)
{
    if (p->data_curp==p->data_stack+MAXSIZE-1) return -1;
    else {
         p->data_curp++;
         *p->data_curp=p->data_in;
         return 1;
    }
}
int PopOprt(stack *p)
{
    if (p->oprt_curp == p->oprt_stack) return -1;
    else {
         p->oprt_out = *p->oprt_curp;
         *p->oprt_curp = '\0';
         p->oprt_curp --;
         return 1;
    }
}
   
int PushOprt(stack *p)
{
    if (p->oprt_curp == p->oprt_stack + MAXSIZE-1) return -1;
    else {
        p->oprt_curp ++;
        *p->oprt_curp = p->oprt_in;
        return 1;
    }
}
void clear(stack *p)
{
    while(p->data_curp != p->data_stack)
        *(p->data_curp--) = 0;
    while(p->oprt_curp != p->oprt_stack)
        *(p->oprt_curp--) = '\0';
}

Calculator Project.rar (68.99 KB) 在此处下载编译好的计算器源程序

搜索更多相关主题的帖子: 计算器 算术 表达 
2007-11-29 17:16
seaisland
Rank: 1
等 级:新手上路
帖 子:15
专家分:0
注 册:2007-11-27
收藏
得分:0 
希望与网友交流
写这个程序是为了煅练一下,学习编程就是要多实践!  我认为我对C的理解并不深刻,所以把这个程序贴出来,一是为了让大家帮忙测试一下这个程序,二是为了和对写计算器感兴趣的网友交流一下.

       下一步将扩充它的功能:
       使它能计算三角函数和对数函数;
       增加整数的求余;
       将结果输出作进一步处理,让它能区分浮点数和整数;

       实现这些功能,需要用到很多我还不熟悉的技术,所以想和网友们交流一下.我的邮箱是[email=cainsea@]cainsea@[/email] QQ:544643653

       在扩充程序功能的时候会更改整个程序的基本构架,不会用到getexp函数.大家可以看到,就是由于这个函数,整个程序都被限制了,不能把一元运算符结合性体现出来,因此,如果把三角函数看作是一元运算符,那么无论怎样扩充都不能对它进行计算.
2007-12-03 13:32
快速回复:算术表达式计算器
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.025017 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved