支持括号、分数计算的四则运算计算器

用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\n",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("\nCompute函数出现不可能运算符 %c\n",((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\n");
 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

 

转载于:https://www.cnblogs.com/zackcoder/p/3246384.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
为了应付作业而编的,一个新手,请大家多多指教。/** * Title: Calculator * Description: * Copyright: Copyright (c) 2004 * Company: CUIT * Calculator.java * Created on 2004年10月13日, 下午2:35 * @author jacktom * @version 1.0*/import java.awt.*;import java.awt.event.*;import javax.swing.*;public class Calculator extends JFrame implements ActionListener{ Operator oper; String a,result; int type; boolean flag1=false; boolean flag2=false; boolean judge=true; int count=0; JTextField text; JPanel jpanel[]; JPanel jpanel1; JButton jbutton[]; String name[]={"0",".","-/+","+","=","1","2","3","-",")","4","5","6","*","(","7","8","9","/","CE"}; //Construct the JFrame public Calculator() { oper=new Operator(); setSize(250,300); setVisible(true); //Overridden so we can exit when window is closed this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { dispose(); System.exit(0); } }); Container con=getContentPane(); con.setLayout(new GridLayout(5,5)); text=new JTextField(12); text.setHorizontalAlignment(JTextField.RIGHT); jpanel1=new JPanel(); jpanel1.setLayout(new GridLayout(1,1)); jpanel1.add(text); jpanel=new JPanel[4]; for(int i=0;i<4;i++) { jpanel[i]=new JPanel(); jpanel[i].setLayout(new GridLayout(1,5)); } jbutton=new JButton[name.length]; //add button to panel for(int j=0;j=0;i--) { con.add(jpanel[i]); } } public void actionPerformed(ActionEvent e) { for(int i=0;i<10;i++) { if(e.getActionCommand().equals(String.valueOf(i))) if(flag1==false) { text.setText(String.valueOf(i)); flag1=true; } else { text.setText(text.getText()+i); } } if(e.getActionCommand().equals(".")) if(flag2==false&&count==0) { text.setText(text.getText()+"."); count++; flag1=true; } if(e.getActionCommand().equals("+")||e.getActionCommand().equals("-")||e.getActionCommand().equals("*")||e.getActionCommand().equals("/")) { if(judge) { a=text.getText(); oper.EvaluateExpression(a); } else judge=true; flag1=false; flag2=false; count=0; if(e.getActionCommand().equals("+")) { a="+"; oper.EvaluateExpression(a); } if(e.getActionCommand().equals("-")) { a="-"; oper.EvaluateExpression(a); } if(e.getActionCommand().equals("*")) { a="*"; oper.EvaluateExpression(a); } if(e.getActionCommand().equals("/")) { a="/"; oper.EvaluateExpression(a); } } if(e.getActionCommand().equals("=")) { if(judge) { a=text.getText(); oper.EvaluateExpression(a); } else judge=true; oper.EvaluateExpression("#"); text.setText(""); text.setText(String.valueOf(oper.CalculateResult())); flag1=false; flag2=false; count=0; } if(e.getSource()==jbutton[2]) { text.setText("-"+text.getText()); } if(e.getActionCommand().equals(")")) { a=text.getText(); oper.EvaluateExpression(a); oper.EvaluateExpression(")"); judge=false; } if(e.getActionCommand().equals("CE")) { text.setText(""); judge=true; count=0; flag1=false; flag2=false; oper=new Operator(); } if(e.getActionCommand().equals("(")) { oper.EvaluateExpression("("); } } /** * Main method * * @param args String[] */ public static void main(String args[]) { Calculator Cmain=new Calculator(); Cmain.pack(); }}/** * Operator.java * Description:用栈实现计算 * Created on 2004年10月13日, 下午3:35 * @author jacktom*/public class Operator{ StackY optr; //存放操作符 StackY opnd;//存放操作数 Puzhu p; boolean Mark; Operator() { p=new Puzhu(); optr=new StackY(); opnd=new StackY(); optr.push("#"); } public void EvaluateExpression(String s) { boolean mark=true; if(s=="+"||s=="-"||s=="*"||s=="/"||s=="("||s==")"||s=="#") { while(mark) { switch(p.Precede(optr.peek(),s)) { case -1: optr.push(s); mark=false; break; case 0: optr.pop(); mark=false; break; case 1: String theta=optr.pop(); String a =opnd.pop(); String b =opnd.pop(); if(a.indexOf(".",0)==-1&&b.indexOf(".",0)==-1) Mark=true; else Mark=false; double c=Double.valueOf(a).doubleValue(); double d=Double.valueOf(b).doubleValue(); double e=p.Operate(c,theta,d); String f=String.valueOf(e); if(theta=="/") Mark=false; if(Mark) opnd.push(f.substring(0,f.indexOf(".",0))); else opnd.push(f); break; } } } else opnd.push(s); } public String CalculateResult() { //double result=Double.valueOf(opnd.peek()).doubleValue(); return opnd.peek(); }}/** * Description:判断操作符的优先级并计算结果 * Created on 2004年10月13日, 下午4:00 * @author jacktom*/class Puzhu{ public Puzhu() {} public int Precede(String optr1,String optr2) { String[] A={"+","-","*","/","(",")","#"}; int[][] B={ {1,1,-1,-1,-1,1,1}, {1,1,-1,-1,-1,1,1}, {1,1,1,1,-1,1,1}, {1,1,1,1,-1,1,1}, {-1,-1,-1,-1,-1,0,2}, {1,1,1,1,2,1,1}, {-1,-1,-1,-1,-1,2,0}, }; int i=0,j=0,k; while(i<7) { if(A[i]==optr1) { break; } i++; } while(j<7) { if(A[j]==optr2) { break; } j++; } k=B[i][j]; return k; } public double Operate(double a,String oper,double b) { double c=0; if(oper=="+") c=a+b; if(oper=="-") c=b-a; if(oper=="*") c=a*b; if(oper=="/") c=b/a; return c; }}/** * StackY.java * Description:堆栈的基本操作实现 * Created on 2004年10月13日, 下午3:05 * @author jacktom*/public class StackY { private int maxSize; // size of stack array private String[] stackArray; private int top; // top of stack public StackY(int s) // constructor { maxSize = s; // set array size stackArray = new String[maxSize]; // create array top = -1; // no items yet }public StackY() // constructor { maxSize = 20; // set array size stackArray = new String[maxSize]; // create array top = -1; // no items yet } public void push(String j) // put item on top of stack { top++; stackArray[top] = j; // increment top, insert item } public String pop() // take item from top of stack { return stackArray[top--]; // access item, decrement top } public String peek() // peek at top of stack { return stackArray[top]; } public boolean isEmpty() // true if stack is empty { return (top == 0); } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值