zoukankan      html  css  js  c++  java
  • 支持括号、分数计算的四则运算计算器

    用C语言实现的带括号四则运算计算器,原理简单,即模拟笔算,将每个运算符标记等级,计算时按照等级由高到低进行计算。加减运算为0级,乘除运算为1级,每进入一层括号等级加2。使用两个链表分别储存运算符与数字。主程序调用之前实现的两个模块,一个是链表,另一个是分数计算。链表代码在下一篇文章,只贴出主程序和分数计算部分。

    主程序,检查算式是否合法的函数未实现

      1 #include "list.h"
      2 #include "sz.h"
      3 
      4 /*内部类型、常量、函数*/
      5 
      6 #define LEVEL_NUM 20    //支持的运算级数
      7 
      8 typedef struct
      9 {
     10     List *oper;    //存运算符的链表,data段类型为Op *
     11     List *num;    //存数字的链表,data段类型为Fract *
     12     int oper_num[LEVEL_NUM];    //存每一级的运算符个数
     13 }Pack;
     14 
     15 typedef struct
     16 {
     17     char oper;
     18     int level;
     19 }Op;    //运算符及对应的级别,加减0级,乘除1级,每进入一层括号运算符对应的级别加2
     20 
     21 
     22 static void Convert(char equation[],Pack *pack);
     23 static int str2int(char str[],int start,int end);
     24 static int GetSE(char str[],int s,int flag);
     25 static void Compute(Pack *pack,Fract *ans);
     26 
     27 
     28 int main(void)
     29 {
     30     char equation[100];
     31     Fract ans;
     32     while(1)
     33     {
     34         scanf("%s",equation);
     35         calc(equation,&ans);
     36         printf("%d/%d
    ",ans.numer,ans.deno);
     37     }
     38     return 0;
     39 }
     40 
     41 void calc(char equation[],Fract *ans)
     42 {
     43     Pack pack;
     44 
     45     //检查及完善equation,该函数未实现!!
     46 
     47     //转换并存入链表
     48     Convert(equation,&pack);
     49 
     50     //使用链表计算,并释放
     51     Compute(&pack,ans);
     52 
     53 }
     54 
     55 //特别说明
     56 //对于"(-数字"这种形式,会导致str2int的参数start>end,正好会转化成"(0-数字"的形式
     57 //因此没有用库函数
     58 void Convert(char equation[],Pack *pack)
     59 {
     60     int i,base,start;
     61 
     62     Op *op;
     63     Fract *num;
     64 
     65     //初始化
     66     pack->num=CreateList();
     67     pack->oper=CreateList();
     68     for(i=0;i<LEVEL_NUM;i++)
     69         pack->oper_num[i]=0;
     70 
     71     start=GetSE(equation,0,1);
     72     base=0;    //存级别的基,每进入一层括号基加2
     73     for(i=0;equation[i];i++)
     74         switch(equation[i])
     75         {
     76         case '+':case '-':case '*':case '/':
     77             //添加运算符
     78             op=(Op *)malloc(sizeof(Op));
     79             op->oper=equation[i];
     80             op->level=base+
     81                 ( (equation[i]=='+'||equation[i]=='-')?0:1);
     82             AddNode(pack->oper,op,pack->oper->n);    //插入到链表尾
     83             pack->oper_num[op->level]++;
     84             
     85             //添加数字
     86             num=(Fract *)malloc(sizeof(Fract));
     87             num->numer=str2int(equation,start,GetSE(equation,i-1,-1));
     88             num->deno=1;
     89             AddNode(pack->num,num,pack->num->n);
     90             start=GetSE(equation,i+1,1);    //为下一个数字准备
     91             break;
     92         case '(':
     93             base+=2;
     94             break;
     95         case ')':
     96             base-=2;
     97             break;
     98         default:    //数字字符
     99             break;
    100         }
    101 
    102     //运算符和数字成对出现,存入最后多出的数字
    103     num=(Fract *)malloc(sizeof(Fract));
    104     num->numer=str2int(equation,start,GetSE(equation,i-1,-1));
    105     num->deno=1;
    106     AddNode(pack->num,num,pack->num->n);
    107 }
    108 
    109 
    110 //将由start和end脚标确定的字符串转换为整数
    111 int str2int(char str[],int start,int end)
    112 {
    113     int i,s=0;
    114     for(i=start;i<=end;i++)
    115         s=s*10+str[i]-'0';
    116     return s;
    117 }
    118 
    119 
    120 //从s开始向前或向后找第一个数字字符的角标
    121 //flag为1向后,-1向前
    122 int GetSE(char str[],int s,int flag)
    123 {
    124     int i;
    125     for(i=s;i>=0 && str[i] && !isdigit(str[i]);i+=flag)
    126         ;
    127     return i;
    128 }
    129 
    130 void Compute(Pack *pack,Fract *ans)
    131 {
    132     //前一运算符,运算符
    133     //第一个数字,第二个数字    
    134     Node *pop,*op,*num,*nnum;    
    135     int i;
    136 
    137     //找到最高不为0的一级
    138     for(i=LEVEL_NUM-1;i>=0 && !pack->oper_num[i];i--)
    139         ;
    140 
    141     for(;i>=0;i--)    //由高到低级依次计算
    142         for(pop=pack->oper->head,op=pack->oper->head->next,num=pack->num->head->next;
    143         pack->oper_num[i] ;    )
    144             if( ((Op*)(op->data))->level==i )    //找到级别为i的运算符
    145             {
    146                 pack->oper_num[i]--;
    147                 switch( ((Op*)(op->data))->oper)
    148                 {
    149                 //计算,结果存入第一个数中
    150                 case '+':Plus(num->data,num->next->data);
    151                     break;
    152                 case '-':Minus(num->data,num->next->data);
    153                     break;
    154                 case '*':Multiply(num->data,num->next->data);
    155                     break;
    156                 case '/':Divide(num->data,num->next->data);
    157                     break;
    158                 default:    
    159                     printf("
    Compute函数出现不可能运算符 %c
    ",((Op*)(op->data))->oper);
    160                     exit(0);
    161                     break;
    162                 }
    163 
    164                 //删除计算完成的运算符、数字
    165                 pack->num->n--;
    166                 pack->oper->n--;
    167                 pop->next=op->next;
    168                 nnum=num->next;
    169                 num->next=nnum->next;
    170                 free(nnum->data);free(op->data);
    171                 free(nnum);free(op);
    172 
    173                 op=pop->next;    //恢复op的指向
    174             }
    175             else    //没找到时继续遍历链表
    176                 pop=op,op=op->next,num=num->next;
    177 
    178     //计算完成后,仅剩一个的数字为结果,运算符链表没内容,储存运算符级别的个数的数组各元素为0
    179     if(pack->num->n!=1 || pack->oper->n || pack->oper_num[0])
    180     {
    181         printf("Compute函数内变量异常,数字个数 %d,运算符个数 %d,0级个数 %d",
    182                             pack->num->n,pack->oper->n,pack->oper_num[0]);
    183         exit(0);
    184     }
    185     (*ans)=*(Fract *)pack->num->head->next->data;
    186     DestroyList(pack->num);
    187     DestroyList(pack->oper);
    188 }
    sz.c
     1 #ifndef SZ_H
     2 #define SZ_H
     3 
     4 //只有calc函数对外,可以去掉主函数来当做一个计算模块使用
     5 //只要在项目中添加sz、list、fract
     6 
     7 #include <ctype.h>
     8 #include "fract.h"
     9 
    10 void calc(char equation[],Fract *ans);
    11 
    12 #endif
    sz.h

    分数计算部分

      1 #include "fract.h"
      2 
      3 static int commom_divisor(int a,int b);    //最大公约数
      4 static int common_multiple(int a,int b);//最小公倍数
      5 static void reduce(int *num1,int *num2);    //约分
      6 
      7 
      8 void Plus(Fract *num1,Fract *num2)
      9 {
     10     int deno;//公分母
     11     
     12     if(num1->numer==0)    //排除0值计算
     13     {
     14         *num1=*num2;
     15         return;
     16     }
     17     else if(num2->numer==0) return;
     18 
     19     deno=common_multiple(num1->deno,num2->deno);
     20     num1->numer=deno/num1->deno*num1->numer+deno/num2->deno*num2->numer;
     21     num1->deno=deno;
     22 
     23 }
     24 
     25 void Minus(Fract *num1,Fract *num2)
     26 {
     27     num2->numer=-num2->numer;
     28     Plus(num1,num2);
     29 }
     30 
     31 void Multiply(Fract *num1,Fract *num2)
     32 {
     33     if(num1->numer==0)return;
     34     else if(num2->numer==0)
     35     {
     36         num1->numer=0;
     37         return;
     38     }
     39 
     40     reduce(&num1->deno,&num2->numer);
     41     reduce(&num1->numer,&num2->deno);
     42 
     43     num1->numer*=num2->numer;
     44     num1->deno*=num2->deno;
     45 
     46 }
     47 
     48 void Divide(Fract *num1,Fract *num2)
     49 {
     50     int temp;
     51     if(num2->numer==0)
     52     {
     53         printf("除数不能为0
    ");
     54         exit(0);
     55     }
     56     temp=num2->numer;
     57     num2->numer=num2->deno;
     58     num2->deno=temp;
     59     Multiply(num1,num2);
     60 }
     61 
     62 
     63 static void reduce(int *num1,int *num2)    //约分并保持原来的正负号
     64 {
     65     int temp,i;
     66     
     67     /*i为0表示都为正,i为1表示num1为正,2表示num2为正,3表示都为负*/
     68     if(*num1<0)
     69     {
     70         *num1=-*num1;
     71         if(*num2<0)
     72         {
     73             *num2=-*num2;
     74             i=3;
     75         }
     76         else i=2;
     77     }
     78     else
     79         if(*num2<0)
     80         {
     81             *num2=-*num2;
     82             i=1;
     83         }
     84         else i=0;
     85 
     86     temp=commom_divisor(*num1,*num2);
     87     *num1/=temp;
     88     *num2/=temp;
     89 
     90     switch(i)
     91     {
     92         case 0:break;
     93         case 1:*num2=-*num2;break;
     94         case 2:*num1=-*num1;break;
     95         case 3:*num1=-*num1;*num2=-*num2;break;
     96     }
     97 }
     98 
     99 
    100 static int commom_divisor(int a,int b)
    101 {
    102      int temp,r;
    103      
    104     if(a<b)
    105     {
    106         temp=a;
    107         a=b;
    108         b=temp;
    109     }
    110     
    111     while((r=a%b))
    112     {
    113         a=b;
    114         b=r;
    115      }
    116      
    117     return b;
    118 }
    119 
    120 static int common_multiple(int a,int b)
    121 {
    122     return a*b/commom_divisor(a,b);
    123 }
    fract.c
     1 #ifndef FRACT_H
     2 #define FRACT_H
     3 
     4 #include <stdio.h>
     5 #include <stdlib.h>
     6 
     7 //如果有负号则在分子上
     8 typedef struct
     9 {
    10     int numer;    //分子
    11     int deno;    //分母
    12 }Fract;
    13 
    14 //分数的四则运算,结果存在num1中
    15 void Plus(Fract *num1,Fract *num2);
    16 void Minus(Fract *num1,Fract *num2);
    17 void Multiply(Fract *num1,Fract *num2);
    18 void Divide(Fract *num1,Fract *num2);
    19 
    20 #endif
    fract.h

    控制台程序源代码 sz.7z

    借用如鹏的对话框模版,及上面的计算器部分,实现的图形计算器

    代码及程序 calc.7z

  • 相关阅读:
    Entity SQL 初入
    ObjectQuery查询及方法
    Entity Framework 的事务 DbTransaction
    Construct Binary Tree from Preorder and Inorder Traversal
    Reverse Linked List
    Best Time to Buy and Sell Stock
    Remove Duplicates from Sorted Array II
    Reverse Integer
    Implement Stack using Queues
    C++中const限定符的应用
  • 原文地址:https://www.cnblogs.com/zackcoder/p/3246384.html
Copyright © 2011-2022 走看看