简单逻辑实现一个计算器,没有用到树的知识
来源:互联网 发布:淘宝发货快递公司填错 编辑:程序博客网 时间:2024/05/18 01:35
/*
这几天想整理一下自己所学,就想写一些简单的东西,就想到实现一个简单的计算器
2. 整个表达式的长度不超过256
3. 不考虑异常输入,保证每个输入都是合法的
4. 操作符只包含()*/+-
5. 优先级,()最高,*/次之,+-最低
最开始的思路:
1. 区分操作数operand与操作符operator;
2. 每个操作符都会有一个左操作数与右操作数
3. 相邻的操作符之间会有一个优先级,通过比较可以取出其中一个操作符先计算,然后将计算出的结果作为一个新的操作数
4. 替换(),遍历的时候先去掉(),即如果遇到(,则遍历字符串直到),然后将这些内容取出,作为一个整体计算出结果,作为一个新的操作数
按照开始的思路的话,可以声明2个数组,一个用来存放操作数,一个用来存放操作符,这里数组大小也是个问题;
A)开始遍历
-->>a.如果是数字,存储到一个临时数组,继续遍历,直到遇到一个非数字为止,然后将给临时数组转换为整数,存放进操作数数组
-->>b.如果是操作符
-->>c.不是(,第一次肯定先存储到操作符数组,如果操作符数组非空的话,则在存储前先与上一个操作符比较,
如果优先级比上一个高(*/ > +-),则继续读取,如果低(+- < */),则先取出上一个操作符,同时从操作数数组中取出
2个操作数,生成一个新操作数存入操作数数组,并将这个操作符存入操作符数组;
-->>d.且是(,则继续遍历,直到),将读取到的字符串放到一个临时数组,然后计算该字符串的结果作为一个新操作数
存入到操作数数组
B)一直遍历,最后可以发现剩下的操作符数组中,都是前面的操作符优先级小于后面的操作符,此时我们就可以倒序计算结果
好吧,这时发现如果有嵌套()的话,上面的思路d就不适用了。
考虑到()是成对就近匹配的,即最近的一个()是一对,再想一下,即)跟离它最近的一个(是一对,好吧,精确匹配的话,遇到(的时候,我们可以先存储起来,直到遇到),然后依次取出直到遇到第一个(,然后计算替换成一个新操作数存储起来;
下面贴出的是具体实现代码,可以发现使用stack替换成array,数组的存储、取出的操作对应stack的push、pop;
这里不是说stack比数组好用,而是为了回忆一下stack的用法与实现;
这里的stack也非常简单,类型都是固定了,int,char,如果通用的话,可能就会用到void *;
*/#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NUM 256
#define OPD_MAX_LEN 10
#ifdef __DEBUG
#define DBG_PRINT printf
#else
#define DBG_PRINT(fmt, ...)
#endif
typedef struct _optStack
{
char opt[MAX_NUM];
int top;
} optStack;
typedef struct _opdStack
{
int opd[MAX_NUM];
int top;
} opdStack;
optStack optSt;
opdStack opdSt;
void initOptSt()
{
optSt.top = -1;
}
void initOpdSt()
{
opdSt.top = -1;
}
int isOptEmpty()
{
if (-1 == optSt.top)
{
return 1;
}
return 0;
}
char getLastOpt()
{
DBG_PRINT("--->>%d optSt.top:%d\n", __LINE__, optSt.top);
return optSt.opt[optSt.top];
}
int getLastOpd()
{
return opdSt.opd[opdSt.top];
}
int isOpdEmpty()
{
if (-1 == opdSt.top)
{
return 1;
}
return 0;
}
void pushOpt(char c)
{
optSt.top++;
optSt.opt[optSt.top] = c;
}
char popOpt()
{
char op = optSt.opt[optSt.top];
optSt.top--;
return op;
}
void pushOpd(int opd)
{
opdSt.top++;
opdSt.opd[opdSt.top] = opd;
}
int popOpd()
{
int opd = opdSt.opd[opdSt.top];
opdSt.top--;
return opd;
}
int getOptLen()
{
DBG_PRINT("--->>>%d optSt.top:%d\n", __LINE__, optSt.top);
return (optSt.top + 1);
}
int isDigit(char c)
{
if ((c >= '0') && (c <= '9'))
{
return 1;
}
return 0;
}
int isOpt(char c)
{
if ((c == '+') || (c == '-') || (c == '*') || (c == '/') ||
(c == '(') || (c == ')'))
{
return 1;
}
return 0;
}
int calc(int leftOpd, int rightOpd, char opt)
{
int ret = 0;
switch (opt)
{
case '+':
ret = leftOpd + rightOpd;
break;
case '-':
ret = leftOpd - rightOpd;
break;
case '*':
ret = leftOpd * rightOpd;
break;
case '/':
ret = leftOpd / rightOpd;
break;
default:
break;
}
return ret;
}
char comparePriority(char pre, char next)
{
switch (pre)
{
case '+':
case '-':
if ((next == '+') || (next == '-'))
{
return '>';
}
else if ((next == '*') || (next == '/'))
{
return '<';
}
else if (next == '(')
{
return '<';
}
else if (next == ')')
{
return '>';
}
else
{
return '>';
}
break;
case '*':
case '/':
if ((next == '+') || (next == '-'))
{
return '>';
}
else if ((next == '*') || (next == '/'))
{
return '>';
}
else if (next == '(')
{
return '<';
}
else if (next == ')')
{
return '>';
}
else
{
return '>';
}
break;
case '(':
if ((next == '+') || (next == '-'))
{
return '<';
}
else if ((next == '*') || (next == '/'))
{
return '<';
}
else if (next == '(')
{
return '<';
}
else if (next == ')')
{
return '=';
}
else
{
return '>';
}
break;
case ')':
if ((next == '+') || (next == '-'))
{
return '<';
}
else if ((next == '*') || (next == '/'))
{
return '<';
}
else if (next == ')')
{
return '=';
}
else
{
return '>';
}
break;
default:
return '>';
break;
}
}
int transCharArrToInt(char arr[], int len)
{
int i = 0;
int num = 0;
for (; i < len; i++)
{
int j = 0;
int digit = arr[i] - '0';
for (j = 1; j < len - i; j++)
{
digit = digit * 10;
}
num += digit;
}
return num;
}
void trimParenthese()
{
while (getLastOpt() != '(')
{
char nextOpt = popOpt();
DBG_PRINT("---->>>%d nextOpd:%c\n", __LINE__, nextOpt);
if (getLastOpt() == '(')
{
int rightOpd = popOpd();
int leftOpd = popOpd();
int newOpd = calc(leftOpd, rightOpd, nextOpt);
DBG_PRINT("--->>>>%d newOpd:%d\n", __LINE__, newOpd);
pushOpd(newOpd);
}
else
{
char preOpt = getLastOpt();
if (comparePriority(preOpt, nextOpt) == '<')
{
int rightOpd = popOpd();
int leftOpd = popOpd();
int newOpd = calc(leftOpd, rightOpd, nextOpt);
DBG_PRINT("--->>>%d newOpd:%d\n", __LINE__, newOpd);
pushOpd(newOpd);
}
else if (comparePriority(preOpt, nextOpt) == '>')
{
}
}
}
popOpt();
}
int calculator(const char * inputStr)
{
char *tmpPtr;
char curChar;
char opdArr[OPD_MAX_LEN + 1];
int index = 0;
tmpPtr = inputStr;
memset(opdArr, 0, OPD_MAX_LEN + 1);
curChar = *tmpPtr;
while (curChar != '\0')
{
DBG_PRINT("-->>> %d curChar:%c\n", __LINE__, curChar);
if (isDigit(curChar))
{
opdArr[index] = curChar;
index++;
if (*(tmpPtr + 1) == '\0')
{
int opd = transCharArrToInt(opdArr, index);
pushOpd(opd);
DBG_PRINT("-->>%d last opd:%d\n", __LINE__, opd);
}
}
else
{
if (index != 0)
{
int opd = transCharArrToInt(opdArr, index);
pushOpd(opd);
DBG_PRINT("--->%d opd:%d\n", __LINE__, opd);
memset(opdArr, 0, index);
index = 0;
}
if (isOpt(curChar))
{
DBG_PRINT("--->>>%d curChar:%c isOptEmpty:%d\n", __LINE__, curChar, isOptEmpty());
if (isOptEmpty())
{
DBG_PRINT("-->%d pushOpt curChar:%c\n", __LINE__, curChar);
pushOpt(curChar);
}
else
{
char preOpt = getLastOpt();
DBG_PRINT("--->>%d preOpt:%c\n", __LINE__, preOpt);
if (curChar == ')')
{
trimParenthese();
}
else
{
if (!isOptEmpty())
{
if (comparePriority(preOpt, curChar) == '>')
{
int rightOpd = popOpd();
int leftOpd = popOpd();
char opt = popOpt();
int newOpd = calc(leftOpd, rightOpd, opt);
DBG_PRINT("--->>>%d newOpd:%d\n", __LINE__, newOpd);
pushOpd(newOpd);
pushOpt(curChar);
}
else
{
pushOpt(curChar);
DBG_PRINT("---> %d pushOpt curChar:%c\n", __LINE__, curChar);
}
}
}
}
}
}
tmpPtr++;
curChar = *tmpPtr;
}
while (!isOptEmpty() && getOptLen() > 1)
{
char topOpt = popOpt();
if (topOpt == ')')
{
trimParenthese();
}
char preOpt = getLastOpt();
if (comparePriority(preOpt, topOpt) == '<')
{
DBG_PRINT("--->>%d preOpt:%c topOpt:%c\n", __LINE__, preOpt, topOpt);
int rightOpd = popOpd();
int leftOpd = popOpd();
int newOpd = calc(leftOpd, rightOpd, topOpt);
DBG_PRINT("--->>>%d newOpd:%d\n", __LINE__, newOpd);
pushOpd(newOpd);
}
else if (comparePriority(preOpt, topOpt) == '>')
{
int opd = popOpd();
int rightOpd = popOpd();
int leftOpd = popOpd();
int newOpd = calc(leftOpd, rightOpd, topOpt);
newOpd = calc(newOpd, opd, preOpt);
popOpt();
pushOpd(newOpd);
DBG_PRINT("--->>%d preOpt:%c, topOpt:%c\n", __LINE__, preOpt, topOpt);
}
else if (comparePriority(preOpt, topOpt) == '=')
{
DBG_PRINT("--->>%d preOpt:%c, topOpt:%c\n", __LINE__, preOpt, topOpt);
popOpt();
}
}
if (getOptLen() == 1)
{
int rightOpd = popOpd();
int leftOpd = popOpd();
char topOpt = popOpt();
int newOpd = calc(leftOpd, rightOpd, topOpt);
pushOpd(newOpd);
return newOpd;
}
else
{
return getLastOpd();
}
}
int main()
{
initOptSt();
initOpdSt();
char str[]="3+4*5";
char str2[] = "3*(5-4)";
char str3[] = "(12+3)*6";
char str4[] = "12-3*3-2";
char str5[] = "12+3-9";
char str6[] = "12/3-5";
char str7[] = "12-6/3";
char str8[] = "12-6/3*2";
char str9[] = "(12-9*3)+2";
char str10[] = "(12+3)*6+(12/2-2)/2";
int a = 0;
a = calculator(str10);
printf("-->>>a=%d\n", a);
return 0;
}
0 0
- 简单逻辑实现一个计算器,没有用到树的知识
- 用二叉树、栈的知识实现一个简单计算器
- 计算器用到的知识
- 实现一个简单的计算器
- 一个简单的计算器界面实现
- 一个简单的Java计算器实现
- 一个能够实现简单功能的计算器
- C语言实现一个简单的计算器
- jsp实现一个简单的计算器
- 用JSP实现一个简单的计算器
- MFC实现一个简单的计算器
- QT实现一个简单的计算器
- QT实现一个简单的计算器
- HTML&&JavaScript实现一个简单的计算器
- 类实现一个简单的日期计算器
- IOS 实现一个简单的计算器
- 基于Java实现的一个简单计算器
- 一个简单的计算器
- 数据结构之二叉树
- 【第十周 项目2-二叉树编历的递归算法】
- EditText四位自动空格
- springmvc接收一个类多个对象数据(提交整个表格数据)
- 第9周项目2 对称矩阵压缩存储的实现与应用(1)
- 简单逻辑实现一个计算器,没有用到树的知识
- 合并排序算法-c++
- 容器适配器
- U3D同时播放2个声音
- 小白学习Q/GDW 1376.1-2013
- Ubuntu远程连接MySQL(connection refused)解决方法
- 第9周项目3-稀疏矩阵的三元组表示的实现及应用(2)
- 过滤非回文数(python)
- 第十周项目2二叉树遍历的递归算法