计算器实现
基于C语言的计算器
本计算器支持整型及double类型的加减乘除运算,源码可以直接移植到嵌入式平台或者windows开发环境运行,本文章详细介绍底层实现逻辑,GUI交互部分不予介绍。
一.功能介绍
- 计算器功能最基本的运算包括加减乘除四则运算,而为了更好的交互,本功能基于链表栈实现,首先介绍下链表栈的操作:
(1)数据入栈
(2)数据出栈
(3)返回栈顶元素
(4)返回栈大小
(5)栈判空
(6)栈清除、销毁
2.计算器功能计算逻辑
1.输入数字,数字压入数据栈
2.输入运算符,运算符压入运算符栈
3.输入等于’=',计算结果
3.文件列表
1.app_stack.c :主要是对链表栈的实现及相关的操作接口
2.app_stack.h:函数声明
3.Calculator.c:计算器逻辑实现,包括加,减,乘,除四则运算,同电脑计算器一样,支持连等
4.Calculator.h:函数声明,及相关结构体定义
链表操作—app_stack.c
/************************************************
* Create Data: 2022/03/30
* author:liwanfang
***************************************************/
#include "app_stack.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/****************************************************************
** Function name: void Init_LinkStack()
** Descriptions: 栈初始化
** input parameters: stack:需要进行操作的栈
** output parameters: 无
** Returned value: 无
** Created by: liwanfang
** Created Date: 2022/4/6
*****************************************************************/
LinkStack *Init_LinkStack() {
LinkStack *stack = (LinkStack *)malloc(sizeof(LinkStack));
stack->head.next = NULL;
stack->size = 0;
return stack;
}
/****************************************************************
** Function name: void Push_LinkStack()
** Descriptions: 入栈操作,弹出栈顶元素
** input parameters: stack:需要进行操作的栈
** output parameters: 无
** Returned value: 无
** Created by: liwanfang
** Created Date: 2022/4/6
*****************************************************************///
void Push_LinkStack(LinkStack *stack, LinkNode *data) {
if(stack == NULL){
return;
}
if(data == NULL){
return;
}
data->next = stack->head.next;
stack->head.next = data;
stack->size++;
}
/****************************************************************
** Function name: void Pop_LinkStack()
** Descriptions: 出栈操作,弹出栈顶元素
** input parameters: stack:需要进行操作的栈
** output parameters: 无
** Returned value: 无
** Created by: liwanfang
** Created Date: 2022/4/6
*****************************************************************/
void Pop_LinkStack(LinkStack *stack) {
if(stack == NULL){
return;
}
if(stack->size == 0){
return;
}
//第一个有效结点
LinkNode *pNext = stack->head.next;
stack->head.next = pNext->next;
stack->size--;
//free(pNext);
}
/****************************************************************
** Function name: void Pop_LinkStack()
** Descriptions: 返回栈顶元素
** input parameters: stack:需要进行操作的栈
** output parameters: 无
** Returned value: 无
** Created by: liwanfang
** Created Date: 2022/4/6
*****************************************************************/
LinkNode* Top_LinkStack(LinkStack *stack) {
if(stack == NULL){
return NULL;
}
if(stack->size == 0){
return NULL;
}
//返回头结点后面的第一个元素
return stack->head.next;
}
/****************************************************************
** Function name: void Pop_LinkStack()
** Descriptions: 返回栈元素的个数
** input parameters: stack:需要进行操作的栈
** output parameters: 无
** Returned value: 无
** Created by: liwanfang
** Created Date: 2022/4/6
*****************************************************************/
int Size_LinkStack(LinkStack *stack) {
if(stack == NULL){
return 0;
}
return stack->size;
}
int IsEmpty_LinkStack(LinkStack *stack)
{
if(stack->size <=0) return 1;
else return 0;
}
/****************************************************************
** Function name: void Pop_LinkStack()
** Descriptions: 清空栈
** input parameters: stack:需要进行操作的栈
** output parameters: 无
** Returned value: 无
** Created by: liwanfang
** Created Date: 2022/4/6
*****************************************************************/
void Clear_LinkStack(LinkStack *stack) {
if(stack == NULL){
return;
}
while(stack->head.next){
LinkNode *tp = stack->head.next;
stack->head.next = tp->next;
free(tp);
}
stack->head.next = NULL;
stack->size = 0;
}
/****************************************************************
** Function name: void Pop_LinkStack()
** Descriptions: 销毁栈
** input parameters: stack:需要进行操作的栈
** output parameters: 无
** Returned value: 无
** Created by: liwanfang
** Created Date: 2022/4/6
*****************************************************************/
//销毁
void FreeSpace_LinkStack(LinkStack *stack) {
if(stack == NULL) {
return;
}
free(stack);
}
链表操作—app_stack.h
#ifndef APP_STACK_H
#define APP_STACK_H
#include <stdlib.h>
#include <stdio.h>
//暂时按优先级排序
typedef enum
{
EMPTY,
POINT = '.',//点
EQUAL = '=',//等于
ADD = '+',//加
DEC = '-',//减
MUL = '*',//乘
DIV = '/',//除
// REM,//余
PLUS_MINUS,//正负
}Operator;
//链式栈的结点
typedef struct LINKNODE {
Operator oper; //操作符
double num; //数据
struct LINKNODE *next;
}LinkNode;
//链式栈
typedef struct LINKSTACK {
LinkNode head;
int size;
}LinkStack;
//初始化函数
LinkStack *Init_LinkStack();
//入栈
void Push_LinkStack(LinkStack *stack, LinkNode *data);
//出栈
void Pop_LinkStack(LinkStack *stack);
//返回栈顶元素
LinkNode* Top_LinkStack(LinkStack *stack);
//返回栈元素的个数
int Size_LinkStack(LinkStack *stack);
//判空
int IsEmpty_LinkStack(LinkStack *stack);
//清空栈
void Clear_LinkStack(LinkStack *stack);
//销毁
void FreeSpace_LinkStack(LinkStack *stack);
#endif // APPSTACK_H_INCLUDED
计算器操作— Calculator.c
/************************************************
* Create Data: 2022/03/30
* author:liwanfang
***************************************************/
#include "Calculator.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include "app_stack.h"
#include <math.h>
char Calculator_num[32] = {0};
uint8_t Calculator_num_length = 0;
//创建栈
LinkStack *Oper_s; //操作符栈
LinkStack *Num_s; //数据栈
//计算器相关参数结构体
Calculator_param cal_param_s;
//清除
void Cpu_ClearCalculatorBuf(void)
{
memset(Calculator_num, 0, sizeof(Calculator_num));
memset(&cal_param_s,0,sizeof(Calculator_param));
Calculator_num_length = 0;
//链表空间释放
Clear_LinkStack(Num_s);
Clear_LinkStack(Oper_s);
//数据栈和操作符栈释放.
// FreeSpace_LinkStack(Num_s);
// FreeSpace_LinkStack(Oper_s);
}
/****************************************************************
** Function name: void equal_deal()
** Descriptions: 等于运算符处理
** input parameters:
** output parameters: 无
** Returned value: 无
** Created by: liwanfang
** Created Date: 2022/4/6
*****************************************************************/
void equal_deal(void)
{
bool oper_is_empty = true;
LinkNode *t_num;
LinkNode *res;
cal_param_s.oper = EQUAL;
//将最后输入的数据和运算符压入栈
t_num = (LinkNode *)malloc(sizeof(LinkNode));
t_num->num = cal_param_s.num;
t_num->oper = EMPTY;
Push_LinkStack(Num_s,(LinkNode *)t_num);//将当前数据压入数据栈
//剩余数据处理
while(IsEmpty_LinkStack(Oper_s)==0)
{
LinkNode *num1,*num2,*num3;
LinkNode *t_oper1,*t_oper2;
//用于存储计算结果
res=(LinkNode *)malloc(sizeof(LinkNode));
num1 = (LinkNode *)Top_LinkStack(Num_s);//倒数第一个数
Pop_LinkStack(Num_s);
num2 = (LinkNode *)Top_LinkStack(Num_s);//倒数第二个数
Pop_LinkStack(Num_s);
t_oper1 = (LinkNode *)Top_LinkStack(Oper_s);//获取倒数第一个操作符
Pop_LinkStack(Oper_s);//操作符出栈
//为乘除,直接计算
if(t_oper1->oper == MUL || t_oper1->oper == DIV)
{
if(t_oper1->oper == MUL)
{
res->num = (num2->num) * (num1->num);
}
else if(t_oper1->oper == DIV)
{
res->num = (num2->num) / (num1->num);
}
Push_LinkStack(Num_s,res);//保存计算结果
free(num1);
free(num2);
free(t_oper1);
}
else if(t_oper1->oper == ADD || t_oper1->oper == DEC)
{
//如果操作符栈不为空
if(!IsEmpty_LinkStack(Oper_s))
{
t_oper2 = (LinkNode *)Top_LinkStack(Oper_s);//倒数第二个操作符
Pop_LinkStack(Oper_s);
num3 = (LinkNode *)Top_LinkStack(Num_s);//到数第三个数
Pop_LinkStack(Num_s);
//倒数第二个运算为/或*,则先进行乘除运算将计算结果压进去再将最后个数压进去.如1+2*3+5,得到1+6+5
if(t_oper2->oper == MUL || t_oper2->oper == DIV)
{
if(t_oper2->oper == MUL)
{
res->num = (num3->num) * (num2->num);
}
else if(t_oper2->oper == DIV)
{
res->num = (num3->num) / (num2->num);
}
Push_LinkStack(Num_s,res);//将计算结果压入数据栈
Push_LinkStack(Num_s,num1);//将最后个数压入数据栈
Push_LinkStack(Oper_s,t_oper1);//将倒数第一个操作符存起来
free(t_oper2);//计算完成后,释放内存
free(num2);
free(num3);
}
else if(t_oper2->oper == ADD || t_oper2->oper == DEC)
{
if(t_oper2->oper == ADD)
{
if(t_oper1->oper == ADD)
{
res->num = (num2->num) + (num1->num);//2+3+5 = 2+(3+5)
}
else if(t_oper1->oper == DEC)
{
res->num = (num2->num) - (num1->num);//2+3-5 = 2+(3-5)
}
}
else if(t_oper2->oper == DEC)
{
if(t_oper1->oper == ADD)
{
res->num = (num2->num) - (num1->num);//2-3+5 = 2-(3-5)
}
else if(t_oper1->oper == DEC)
{
res->num = (num2->num) + (num1->num);//2-3-5 = 2-(3+5)
}
}
Push_LinkStack(Oper_s,t_oper2);//保存t_oper2
Push_LinkStack(Num_s,num3);//保存num3
Push_LinkStack(Num_s,res);//保存计算结果
free(num1);//释放内存
free(num2);
free(t_oper1);
}
}
else //操作符已取完
{
if(t_oper1->oper == ADD)
{
res->num = (num2->num) + (num1->num);
}else if(t_oper1->oper == DEC)
{
res->num = (num2->num) - (num1->num);
}
Push_LinkStack(Num_s,res);//保存计算结果
free(t_oper1);
free(num1);
free(num2);
}
}
}
//到这已计算完成,计算结果保存再res中
res = Top_LinkStack(Num_s);
Pop_LinkStack(Num_s);//最后个计算结果出栈
memset(Calculator_num,0,Calculator_num_length);//清空
if(numIsInteger(res->num)){//计算结果为整数
sprintf(Calculator_num,"%lld",(int64_t)res->num);//强转为整形输出
Calculator_num_length = strlen(Calculator_num);
}else{//计算结果为小数
sprintf(Calculator_num,"%g",res->num);
Calculator_num_length = strlen(Calculator_num);
//计数小数位数
cal_param_s.point_count = decimal_count(Calculator_num,Calculator_num_length);//strstr(Calculator_num,".");//
}
if( cal_param_s.point_count > 0)
{
cal_param_s.point_flag = 1;
}else{
cal_param_s.point_count = 0;
cal_param_s.point_flag = 0;
}
cal_param_s.num = res->num;
free(res);
}
//小数点
void point_deal(void)
{
cal_param_s.oper = POINT;
}
/****************************************************************
** Function name: void num_deal()
** Descriptions: 数字输入处理
** input parameters: oper:运算符
point_count:小数位数
num:当前的数值
n:用户输入的数值(0-9)
** output parameters: 无
** Returned value: 无
** Created by: liwanfang
** Created Date: 2022/4/6
*****************************************************************/
void num_deal(int n)
{
//"+/-"功能键,出值异常
if(cal_param_s.point_flag){
cal_param_s.point_count++;
if(cal_param_s.num >= 0){
cal_param_s.num = (cal_param_s.num) + n*1.0/pow(10,cal_param_s.point_count);
}else{
cal_param_s.num = (cal_param_s.num) - n*1.0/pow(10,cal_param_s.point_count);//-5.5 5
}
}else{
cal_param_s.point_count = 0;
if(cal_param_s.num >= 0){
cal_param_s.num = (cal_param_s.num) * 10 + n;
}else{
cal_param_s.num = (cal_param_s.num) * 10 - n;
}
}
}
/****************************************************************
** Function name: void plus_minus_deal()
** Descriptions: +/-运算符处理
** input parameters:
** output parameters: 无
** Returned value: 无
** Created by: liwanfang
** Created Date: 2022/4/6
*****************************************************************/
void plus_minus_deal(void)
{
//输入的第一个数字
if(((IsEmpty_LinkStack(Num_s) && IsEmpty_LinkStack(Oper_s)) || cal_param_s.oper == EQUAL))
{
cal_param_s.num = -(cal_param_s.num);
}
cal_param_s.oper = EMPTY;
if(numIsInteger(cal_param_s.num)){//计算结果为整数
sprintf(Calculator_num,"%lld",(int64_t)cal_param_s.num);
}else{//计算结果为小数
sprintf(Calculator_num,"%g",cal_param_s.num);
}
Calculator_num_length = strlen(Calculator_num);
}
/****************************************************************
** Function name: void Operation_deal()
** Descriptions: 加减乘除运算符处理
** input parameters:
** output parameters: 无
** Returned value: 无
** Created by: liwanfang
** Created Date: 2022/4/6
*****************************************************************/
void Operation_deal(char ch)
{
cal_param_s.oper = ch;
LinkNode *t_num = (LinkNode*)malloc(sizeof(LinkNode));
LinkNode *t_oper = (LinkNode*)malloc(sizeof(LinkNode));
t_num->num = cal_param_s.num;
t_num->oper = EMPTY;
t_oper->oper = ch;
t_oper->num = 0;
Push_LinkStack(Oper_s,(LinkNode *)t_oper);
Push_LinkStack(Num_s,(LinkNode *)t_num);
cal_param_s.num = 0; //数字清零
}
/****************************************************************
** Function name: delete_Invalid_zero
** Descriptions: 小数点后无效0清除
** input parameters: buf:
** output parameters: 无
** Returned value: 无
** Created by: liwanfang
** Created Date: 2022/4/6
*****************************************************************/
bool delete_Invalid_zero(char *buf,int len)
{
//计算小数位数
for(int i=len-1;i>=0;i--){
if(buf[i]=='0'){
buf[i]='\0';
}else if(buf[i] == '.'){
buf[i]='\0';
return 0; //整数
}else{
return 1;
}
}
return 1;
}
//计算小数个数
int decimal_count(char *buf,int len)
{
int i = 0;
for(i = 0; i < len; i ++)
{
if(buf[i] == '.') break;
}
return (i == len)? 0 : (len - i - 1);
}
//BACKSPACE
/****************************************************************
** Function name: void backspace_deal()
** Descriptions: 清除最后个数字或操作符
** input parameters: buf:
** output parameters: 无
** Returned value: 无
** Created by: liwanfang
** Created Date: 2022/4/6
*****************************************************************/
void backspace_deal(void)
{
char buf[32];
if(cal_param_s.point_count == 0 && (cal_param_s.point_flag)){ //如果当前清除的为小数点,这不作处理直接返回
cal_param_s.point_flag = 0;
cal_param_s.point_count = 0;
return;
}
if(cal_param_s.num == 0 && !IsEmpty_LinkStack(Num_s)){ //如果当前num为0,取出数据
//操作符出栈
LinkNode *oper_t = Top_LinkStack(Oper_s);
Pop_LinkStack(Oper_s);
free(oper_t);
//李万方 20220820 解决连等结果错误问题
cal_param_s.oper = Top_LinkStack(Oper_s)->oper;
//取出数据
LinkNode *num_t = Top_LinkStack(Num_s);
cal_param_s.num = num_t -> num;
Pop_LinkStack(Num_s);
free(num_t);
//得到当前立即数是否为小数
sprintf(buf,"%g",cal_param_s.num);
cal_param_s.point_count = decimal_count(buf,strlen(buf));
if(cal_param_s.point_count > 0)
{
cal_param_s.point_flag = 1;
}else{
cal_param_s.point_count = 0; //整数
cal_param_s.point_flag = 0;
}
//如0.05,清除一位后为0.0,小数点位数大于0,还需进入判断进行处理
}else if(cal_param_s.num != 0 || cal_param_s.point_count>0){
if(cal_param_s.point_count > 0)
{
//取整除10再转换为小数,解决数据溢出导致计算结果出错问题
cal_param_s.num = (((int64_t)(cal_param_s.num * pow(10,cal_param_s.point_count)))/10)*1.0 / pow(10,cal_param_s.point_count-1);
cal_param_s.point_count --;//小数位数减一
cal_param_s.point_flag = 1;
}else{
//当前数为整数,直接除10
//解决数据溢出导致计算结果出错问题
cal_param_s.num = ((int64_t) cal_param_s.num) / 10;
}
}
//23+ 当前已清除完一个操作数,即num == 0,再清除将删除下一个操作符
if(cal_param_s.num == 0 && !IsEmpty_LinkStack(Oper_s))
{
cal_param_s.oper = Top_LinkStack(Oper_s) -> oper;
cal_param_s.lastIsOper = 1;//下次输入不能输入操作符
cal_param_s.num_flag = 0;
}
}
/****************************************************************
** Function name: void clear_deal()
** Descriptions: 清除
** input parameters: buf:
** output parameters: 无
** Returned value: 无
** Created by: liwanfang
** Created Date: 2022/4/6
*****************************************************************/
void clear_deal(void)
{
while(Oper_s->head.next){
LinkNode *t = Oper_s->head.next;
Oper_s->head.next = t->next;
free(t);
}
while(Oper_s->head.next){
LinkNode *t = Num_s->head.next;
Num_s->head.next = t->next;
free(t);
}
}
void Scientific_Counting(void)
{
Calculator_num_length = strlen(Calculator_num);
//科学计数法显示
for(uint8_t index = 0; index < Calculator_num_length; index ++)
{
//正数次方,直接将+替换为e
if(Calculator_num[index] == '+')
{
Calculator_num[index] = 'e';
break;
}else if(Calculator_num[index] == '-')//负数次方,在负号-前插入e,如1.256485-6 -> 1.256485e-6
{
Calculator_num_length ++;
for(uint8_t index1 = Calculator_num_length-1; index1 >= index; index1 --)
{
Calculator_num[index1] = Calculator_num[index1-1];
}
Calculator_num[index] = 'e';
break;
}
}
}
//判断当前数为小数还是整数
//返回值 1:整数 0:小数
bool numIsInteger(double num)
{
return num == (int64_t)num;
}
/****************************************************************
** Function name: void Calculate(void)
** Descriptions: 计算
** input parameters: ch: 输入字符
** output parameters: 无
** Returned value: 无
** Created by: liwanfang
** Created Date: 2022/5/24
*****************************************************************/
void Calculate(char ch)
{
if(Calculator_num_length == 14 && ch != 'C' && ch != 'B' && ch != '=') return;
if(ch >= '0' && ch <= '9'){ //数字
//如果上次为等于,将清空数据缓冲区
if(cal_param_s.oper == EQUAL)
{
Cpu_ClearCalculatorBuf();
}
//上次为错误操作,输入数字后,将缓冲区清除
if(Calculator_num_length == 3 && strcmp(Calculator_num,"***") == 0){
Cpu_ClearCalculatorBuf();
}else if(((cal_param_s.last_input_ch == '0') || (Calculator_num[0] == '0' && Calculator_num_length == 1))
&& cal_param_s.num == 0 && ch != '0' && cal_param_s.point_flag == 0)
{
Calculator_num_length --;
}
if(cal_param_s.last_input_ch == '0' && cal_param_s.num == 0 && ch == '0' && !cal_param_s.point_flag)
{
return;
}
Calculator_num[Calculator_num_length] = ch;
cal_param_s.num_flag = true;
cal_param_s.click_flag = 1;
cal_param_s.lastIsOper = 0; //消除操作符输入标志
num_deal(ch-'0');
}else if(ch == '+' || ch == '-' || ch == '*' || ch=='/'){ //运算符
cal_param_s.point_flag = 0;
cal_param_s.point_count = 0;
//防止输入数字+运算符后,再将其清除后可以直接输入运算符
//例:输入"1+" ->连续按两次backspace 将 "1+"删掉后可直接输入操作符
if(IsEmpty_LinkStack(Num_s) && IsEmpty_LinkStack(Oper_s) && cal_param_s.num == 0 && Calculator_num_length == 0) return;
//1.上次输入为小数点,本次输入为运算符,则将小数点替换为操作符
//2.上次输入为操作符,则改变操作符
if(cal_param_s.lastIsOper == 1 && ch != cal_param_s.oper && Calculator_num[Calculator_num_length-1] != '.')
{
Calculator_num_length --;
cal_param_s.click_flag = 1;
//将操作符替换为本次输入的操作符
Calculator_num[Calculator_num_length] = ch;
cal_param_s.lastIsOper = 1;
LinkNode *t_oper = Top_LinkStack(Oper_s);
Pop_LinkStack(Oper_s);
t_oper->oper = ch;
cal_param_s.oper = ch;
Push_LinkStack(Oper_s,t_oper);
}
if(Calculator_num[Calculator_num_length-1] == '.'){
Calculator_num_length --;
cal_param_s.click_flag = 1;
Calculator_num[Calculator_num_length] = ch;
cal_param_s.lastIsOper = 1;
Operation_deal(ch);//运算处理
}else if((cal_param_s.lastIsOper != 1 && cal_param_s.num_flag)) //上次输入不为操作符
{
cal_param_s.num_flag = false;
cal_param_s.click_flag = 1;
Calculator_num[Calculator_num_length] = ch;
cal_param_s.lastIsOper = 1;
Operation_deal(ch);//运算处理
}
}else if(ch == '='){
Operator t_p = cal_param_s.oper;
cal_param_s.point_flag = 0;
//因为缺少cal_param_s.oper != POINT条件,导致输入小数点cal_param_s.last_oper的值更新为POINT
if((t_p == ADD || t_p == DEC || t_p == MUL || t_p == DIV) && cal_param_s.lastIsOper != 1){
cal_param_s.last_num = cal_param_s.num; //保存最后一次输入的操作数
cal_param_s.last_oper = cal_param_s.oper;//保存最后一次输入的操作符
}
//得到运算结果再次按等于,未重复进行上次的计算
if(cal_param_s.lastIsOper != 1){//上一次不为操作符才能等于,再次点击等号,重复上次的计算
cal_param_s.num_flag = true;
cal_param_s.calculate_flag = 1;//标记进行了一次计算
if(cal_param_s.oper == EQUAL){ //上一次为等于,用last_num进行此次运算【连续等于,执行上一次的操作】
if(cal_param_s.last_oper == ADD){//加
cal_param_s.num += cal_param_s.last_num;
}else if(cal_param_s.last_oper == DEC){//减
cal_param_s.num -= cal_param_s.last_num;
}else if(cal_param_s.last_oper == MUL){//乘
cal_param_s.num *= cal_param_s.last_num;
}else if(cal_param_s.last_oper == DIV && cal_param_s.last_num != 0){//除
cal_param_s.num /= cal_param_s.last_num;
}
if(numIsInteger(cal_param_s.num)){//计算结果为整数
sprintf(Calculator_num,"%lld",(int64_t)cal_param_s.num);
Calculator_num_length = strlen(Calculator_num);
}else{//计算结果为小数
sprintf(Calculator_num,"%g",cal_param_s.num);
Calculator_num_length = strlen(Calculator_num);
//计数小数位数
cal_param_s.point_count = decimal_count(Calculator_num,Calculator_num_length);
}
if(cal_param_s.point_count > 0)
{
cal_param_s.point_flag = 1;
}else{
cal_param_s.point_count = 0;
cal_param_s.point_flag = 0;
}
}else{
equal_deal();
}
}
}else if(ch == '.'){
if(cal_param_s.oper == EQUAL || Calculator_num_length == 0)
{
Cpu_ClearCalculatorBuf();
Calculator_num[Calculator_num_length] = '0';
Calculator_num_length ++;
cal_param_s.num_flag = false;
cal_param_s.lastIsOper = 1;
cal_param_s.click_flag = 1;
cal_param_s.point_flag = 1; //标记当前输入了小数点
cal_param_s.point_count = 0;
Calculator_num[Calculator_num_length] = ch;
}else if(cal_param_s.lastIsOper != 1 && cal_param_s.num_flag && !cal_param_s.point_flag && Calculator_num_length > 0){//上一次为操作符,不进入
cal_param_s.num_flag = false;
cal_param_s.lastIsOper = 1;
cal_param_s.click_flag = 1;
cal_param_s.point_flag = 1; //标记当前输入了小数点
cal_param_s.point_count = 0;
Calculator_num[Calculator_num_length] = ch;
}
}else if(ch == 'C'){//
cal_param_s.lastIsOper = 0;
cal_param_s.num = 0;
cal_param_s.oper = EMPTY;
Cpu_ClearCalculatorBuf();
clear_deal();
}else if(ch == 'B'){//清楚最后一个数字或运算符
char buf_ch = Calculator_num[Calculator_num_length-1];
//如果当前数据为上次计算结果,则阻止对计算结果进行编辑,直接将缓冲区清空
if((cal_param_s.oper == EQUAL) || (cal_param_s.calculate_flag && IsEmpty_LinkStack(Num_s))) {
Cpu_ClearCalculatorBuf();
return;
}
if(Calculator_num[Calculator_num_length-1] != '.')
{
cal_param_s.lastIsOper = 0;
cal_param_s.num_flag = 1;
}
Calculator_num[Calculator_num_length-1] = '\0';
Calculator_num_length--;
backspace_deal();
}else if(ch == 'F')//正负处理
{
if(IsEmpty_LinkStack(Oper_s) && IsEmpty_LinkStack(Num_s) && cal_param_s.num != 0)
{
cal_param_s.lastIsOper = 0;
plus_minus_deal(); //正负处理
}
}
cal_param_s.last_input_ch = ch;
if(cal_param_s.click_flag == 1)
{
if(Calculator_num_length < 14)
{
Calculator_num_length ++;
}
cal_param_s.click_flag = 0;
}
}
计算器操作 — Calculator.h
#ifndef CALCULATOR__H
#define CALCULATOR__H
#include <stdlib.h>
#include <stdio.h>
#include "app_stack.h"
#include "stdint.h"
#include <stdbool.h>
typedef struct{
char last_input_ch; //上一次输入字符
bool lastIsOper; //上一次输入是否为为操作符
bool point_flag; //标记是否按下小数点 0:未按下小数点
bool num_flag; //输入数字标记
bool click_flag; //按下键盘标记
bool calculate_flag; //标记是否进行过计算
uint8_t point_count; //小数点后位数
Operator oper; //当前运算符
Operator last_oper; //上一个运算符
double num; //当前数值
double last_num; //上一个操作数
}Calculator_param;
extern LinkStack *Oper_s; //操作符栈
extern LinkStack *Num_s; //数据栈
extern char Calculator_num[32]; //显示数据缓冲区
extern uint8_t Calculator_num_length; //显示数据缓冲区长度
extern Calculator_param cal_param_s;; //计算器参数结构体
void Cpu_ClearCalculatorBuf(void);
void Operation_deal(char ch);
void equal_deal(void);
void point_deal(void);
void num_deal(int ch);
void plus_minus_deal(void);
void backspace_deal(void);
void clear_deal(void);
bool delete_Invalid_zero(char *buf,int len);
int decimal_count(char *buf,int len);
void Calculate(char ch);
bool numIsInteger(double num);
#endif
简单移植应用–基于windowns控制台运行
#include <stdio.h>
#include <stdlib.h>
#include "Calculator.h"
int main(int argc, char *argv[])
{
//数据栈和操作符栈的初始化
if(Num_s == NULL)
{
Num_s = Init_LinkStack(); //数据栈
}
if(Oper_s == NULL)
{
Oper_s = Init_LinkStack(); //操作符栈
}
while(1)
{
char ch = 0;
scanf("%c",&ch);
Calculate(ch);//每输入一个字符,调用此函数进行处理
if(ch == '=')
{
printf("%s\n",Calculator_num);
}
}
return 0;
}
带UI交互的代码移植 – 嵌入式平台
int main(void)
{
/*
嵌入式平台相关初始化
*/
static char ch;
//计算器键盘,将映射到嵌入式平台的LCD屏
char key_b[][5]={
{'*', '7', '8', '9', '+'},
{'/', '4', '5', '6', '-'},
{'F', '1', '2', '3', '='},
{'C', 'C', '0', '.', '.'},
};
//只有在开机后第一次进入计算器才对两个栈进行初始化,为其分配内存
if(Num_s == NULL)
{
Num_s = Init_LinkStack(); //数据栈
}
if(Oper_s == NULL)
{
Oper_s = Init_LinkStack(); //操作符栈
}
while(1)
{
ch = 0;
ch = GUI_GetNum();//此函数接口自己实现,返回输入的字符即可,如在屏幕上点击2,就返回'2'
if(ch != 0)
{
//计算
Calculate(ch);
}
//这里加一个退出操作,如按按键退出
if(按键按下)
{
break;
}
GUI_ShowString(Calculator_num);//输入的所有字符缓存在全局Calculator_num数组中,这里调用字符串显示函数显示即可
}
Cpu_ClearCalculatorBuf();//运行完成后需要清除缓冲区
return 0;
}