这两天在看一个C语言写的计算器程序,做了不少的功夫,跟着作者一步步的进行完善,了解了许多细节性的东西,在此自己做个总结,加深自己对程序的印象,也算是梳理。

在该计算器程序,能进行加减乘除、sin、cos、exp等操作,同时能进行数值保存功能。而该计算器使用逆波兰表示法。即所有运算符都跟在操作数的后面,比如下列表达式:
(1 - 2) * (4 + 5)采用逆波兰表示法表示为:1 2 - 4 5 + *
逆波兰表达法中不需要圆括号,只要知道每个运算符需要几个操作数就不会引起歧义。

计算器程序实现很简单,具体原理如下:

while(/* 下一个运算符或操作数不是文件结束指示符 */)if(/* 是数 */)/* 将该数压入到栈中 */else if (/* 是运算符 */)/* 弹出所需数目的操作数 *//* 执行运算 *//* 将结果压入到栈中 */else if (/* 是换行符 */)/* 弹出并打印栈顶的值 */else/* 出错 */

在程序设计中,使用模块化思想,getop函数来进行读入,该函数返回一个标识,用来标识读入的是什么类型。主循环体中根据该标识执行相应的动作。

以下是该程序: (我将所有函数和变量放在同一文件)

#include <stdlib.h>
#include <stdio.h>
#include <string.h>#define MAXOP 100
#define NUMBER '0'   //标识读入的是数字
#define NAME 'n'     //标识读入的是字符串(函数名或非法字符串)
#define ALPHA 26
int getop(char []);
void push (double);  //压栈
double pop(void);    //出栈
void clear(void);    //清空栈
void mathfnc(char []);   //执行相应的数学函数sin、cos、exp等int main(void)
{int type;int i, var = 0;double op1, op2,v;char s[MAXOP];double variable[ALPHA];for (i = 0; i < ALPHA; i++)    //初始化用于保存数值的变量数组variable[i] = 0.0;while ((type = getop(s)) != EOF)    //读取输入{switch (type){case NUMBER:push (atof(s));break;case NAME:mathfnc(s);break;case '+':push (pop() + pop());break;case '*':push (pop() * pop());break;case '-':op2 = pop();push (pop() - op2);break;case '/':op2 = pop();if (op2 != 0.0)push (pop() / op2);elseprintf ("error: zero divisor\n");break;case '%':op2 = pop();if (op2 != 0.0)push (fmod(pop(), op2));elseprintf ("error: zero divisor\n");break;case '?':    //打印栈顶元素op2 = pop();printf ("\t%.8g\n", op2);push (op2);break;case '=':   //保存数值pop();if (var >= 'A' && var <= 'Z')variable[var - 'A'] = pop();elseprintf ("error: no variable name\n");break;case 'c':clear();break;case 'd':   //复制栈顶元素op2 = pop();push(op2);push(op2);break;case 's':   //交换栈元素op1 = pop();op2 = pop();push(op1);push(op2);case '\n':v = pop();   //v保存最后的一次结果printf ("\t%.8g\n", v);break;default:if (type >= 'A' && type <= 'Z')push(variable[type - 'A']);else if (type == '@')   //输入的字符@表示最近一次结果值 push(v);elseprintf ("error: unknown command %s\n", s);break;}var = type;  }return 0;
}/* ----------------------------------------------------------- */#define MAXVAL 100int sp = 0;     //标识栈顶
double val[MAXVAL];void push(double f)
{if (sp < MAXVAL)val[sp++] = f;elseprintf ("error: stack full, can't push %g\n", f);
}double pop(void)
{if (sp > 0)return val[--sp];else{printf ("error: statck empty\n");return 0.0;}
}void clear(void)
{sp = 0;
}void mathfnc (char s[])
{double op2;if (strcmp (s, "sin") == 0)push(sin(pop()));else if(strcmp (s, "cos") == 0)push(cos(pop()));else if(strcmp (s, "exp") == 0)push(exp(pop()));else if(strcmp (s, "pow") == 0){op2 = pop();push (pow(pop(), op2));}elseprintf ("error: %s not supported\n", s);
}/* ----------------------------------------------------------- */#include <ctype.h>int getch(void);
void ungetch(int);int getop(char s[])
{int i, c;while ((s[0] = c = getch()) == ' ' || c == '\t')  //过滤开头的空白字符;s[1] = '\0';i = 0;if (islower(c))   //判断是否为小写字母,也即读取由小写字母组成的字符串{while (islower(s[++i] = c = getch()));s[i] = '\0';if (c != EOF)ungetch(c);if (strlen (s) > 1)return NAME;else return c;}if (!isdigit(c) && c != '.' && c != '-')return c;if (c == '-')     //用于判断是负数还是减操作          { if (isdigit(c = getch()) || c == '.')  s[++i] = c;else{if (c != EOF)ungetch(c);return '-';}}if (isdigit(c))      //收集整数部分while (isdigit(s[++i] = c = getch()));if (c == '.')    //收集小数部分while (isdigit(s[++i] = c = getch()));s[i] = '\0';if (c != EOF)ungetch(c);return NUMBER;
}/* ----------------------------------------------------------- */
/** 引用以下两个函数是因为:程序不能确定它已经读入的输入是否足够 ** 除非超前多读入一些输入,在本程序中,读入一些字符合成一个数字 ** 所以在看到第一个非数字字符之前,已经读入的数的完整性是不能确定的* 由于程序要超前读入一个字符,这样就导致最后又一个字符不属于当前所要读入的数 */#define BUFSIZE 100
char buf[BUFSIZE];
int bufp = 0;int getch(void)
{return (bufp > 0) ? buf[--bufp] : getchar();
}void ungetch (int c)
{if (bufp >= BUFSIZE)printf ("ungetch: too many characters\n");elsebuf[bufp++] = c;
}

该程序虽然简单,但是还是存在一些小小的问题,比如没有数据时进行pop的话,会打印栈中无数据同时返回数值0.0,在循环体中许多执行操作会将该数值保存到栈中,之后打印该值,用户体验度比较差。程序设计方面,模块化设计使得该程序容易增加功能而不影响其他模块,比如增加一些数学函数处理,在mathfnc函数中去添加,或增加一些运算符操作,可以在主循环体中增加。

总之,这次学习还是颇有收获。

C语言编写的简单计算器程序相关推荐

  1. C语言题:简单计算器程序

    题目: 编写一个简单计算器程序,输入格式为:data1 op data2.其中data1和data2是参加运算的两个数,op为运算符,它的取值只能是+.-.*./..要求必须使用switch-case ...

  2. JAVA编写的简单计算器程序

    系列文章目录 文章目录 系列文章目录 前言 一.JAVA编写的简单计算器程序 前言 链接:https://pan.baidu.com/s/1oPJRIbwxcXgewZ_KZaWzTg 提取码:egy ...

  3. c语言课程设计计算器程序分析,c语言课程设计简单计算器程序..docx

    课程设计名称:C语言课程设计 课程设计题目: 简单计算器程序 TOC \o "1-5" \h \z \o "Current Document" 第1章需求分析1 ...

  4. c语言课程设计计算器软件,C语言课程设计简单计算器程序.docx

    课程设计名称: C 语言课程设计课程设计题目: 简单计算器程序 目录 第1章 需求分析 0 设计要求 0 任务 0 第2章 总体设计 1 TOC \o "1-5" \h \z \o ...

  5. php编写一个简单计算器程序,PHP 简单计算器代码实现

    /* * 简单计算器 */ error_reporting(E_ALL & ~E_NOTICE); if(isset($_POST['sub'])){ $a = $_POST['num1']; ...

  6. 用C语言编写一个“简单”的程序答题系统

    上个星期我们老师给我们布置一道他认为很简单的题,其实就想考考我们,要我们写一个简单的答题系统.开始一看只有一道题我直呼:"仰天大笑出门去,我辈岂是蓬蒿人" 以为老师放我一马,结果点 ...

  7. php编写一个简单计算器程序,PHP做一个简单的计算器

    本文为大家讲解通过分支循环知识及PHP的表单处理一个简单的计算器 首先看下效果 通过网页显示计算器样式 在网页样式中可以看出,有两个输入框Num1.Num2和一个下拉框Type 还有一个提交按钮 在输 ...

  8. C语言实现简单计算器程序

    简单计算器程序 编写一个简单计算器程序,输入格式为:data1 op data2.其中data1和data2是参加运算的两个数,op为运算符,它的取值只能是+.-.*./..要求必须使用switch- ...

  9. java入门篇(一)如何编写一个简单的程序

    最近准备花费很长一段时间写一些关于Java的从入门到进阶再到项目开发的教程,希望对初学Java的朋友们有所帮助,更快的融入Java的学习之中. 主要内容包括JavaSE.JavaEE的基础知识以及如何 ...

最新文章

  1. java.lang.ClassNotFoundException: org/apache/xerces/parsers/SAXParser
  2. 什么是URL?协议头、路径和端口是什么意思?
  3. Visual Studio 2017 15.5预览版添加对F# Core及Standard的支持
  4. 大数据互联网架构阶段 数据库三范式与反范式
  5. Restful HMAC认证
  6. docker多个容器一起打包_docker如何将容器打包成镜像
  7. 可禁用计算机服务,win10哪些服务可以禁用 服务哪些可以禁止启动
  8. Ferguson游戏
  9. BZOJ3930-莫比乌斯反演+杜教筛
  10. loss低但精确度低_低光照图像增强网络-RetinexNet(model.py解析【2】)
  11. python从入门到实践答案第四章_python从入门到实践课后习题第四章
  12. Linux打包压缩解压缩tar、gzip、bzip2
  13. [转载] java接口中方法的默认访问修饰符为public
  14. Q106:Linux系统下安装编译PBRT-V3
  15. mybatis比mysql安全吗_MyBatis 和 SQL 注入的恩恩怨怨
  16. 利用python如何刷访问量
  17. mysql中默认值_和comment_MySQL字段默认值踩坑记录
  18. puts()函数详解
  19. 2022仿写b站首页
  20. 【BW系列】SAP 讲讲BW/4 HANA和BW on HANA的区别

热门文章

  1. 前端js如何检测网络状况
  2. c语言goout函数,Go Back N C语言实现(无ACK)
  3. JavaScript判断浏览器Flash Player信息
  4. 思科推NCS4200家族 与Ciena竞争Verizon城域订单
  5. Java 培训班出来之后的面试经历,很难!!
  6. 需要开源免费商城系统的看过来,不看后悔!
  7. 【C++札记】标准模板库string
  8. 关于网站模板的下载地址
  9. 腾信微信公众号初步开发应用
  10. HTML5案例|如何可视化制作六一儿童节前端页面