栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

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

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

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

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

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

while()
 if()
 
 else if ()
 
 
 
 else if ()
 
 else
 

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

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

#include 
#include 
#include 

#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);
  else
   printf ("error: zero divisorn");
  break;
  case '%':
  op2 = pop();
  if (op2 != 0.0)
   push (fmod(pop(), op2));
  else
   printf ("error: zero divisorn");
  break;
  case '?': //打印栈顶元素
  op2 = pop();
  printf ("t%.8gn", op2);
  push (op2);
  break;
  case '=': //保存数值
  pop();
  if (var >= 'A' && var <= 'Z')
   variable[var - 'A'] = pop();
  else
   printf ("error: no variable namen");
  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%.8gn", v);
  break;
  default:
  if (type >= 'A' && type <= 'Z')
   push(variable[type - 'A']);
  else if (type == '@') //输入的字符@表示最近一次结果值 
   push(v);
  else
   printf ("error: unknown command %sn", s);
  break;
 }
 var = type; 
 }
 return 0;
}



#define MAXVAL 100

int sp = 0; //标识栈顶
double val[MAXVAL];

void push(double f)
{
 if (sp < MAXVAL)
 val[sp++] = f;
 else
 printf ("error: stack full, can't push %gn", f);
}

double pop(void)
{
 if (sp > 0)
 return val[--sp];
 else
 {
 printf ("error: statck emptyn");
 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));
 }
 else
 printf ("error: %s not supportedn", s);
}



#include 

int getch(void);
void ungetch(int);

int getop(char s[])
{
 int i, c;
 while ((s[0] = c = getch()) == ' ' || c == 't') //过滤开头的空白字符
 ;
 s[1] = '';

 i = 0;

 if (islower(c)) //判断是否为小写字母,也即读取由小写字母组成的字符串
 {
 while (islower(s[++i] = c = getch()))
  ;
 s[i] = '';

 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] = '';

 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 charactersn");
 else
 buf[bufp++] = c;
}

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

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

关于计算器的精彩文章请查看《计算器专题》 ,更多精彩等你来发现!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/61980.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号