基于C语言实现计算器功能 - 可直接用

基于C语言的计算器

本计算器支持整型及double类型的加减乘除运算,源码可以直接移植到嵌入式平台或者windows开发环境运行,本文章详细介绍底层实现逻辑,GUI交互部分不予介绍。

一.功能介绍

  1. 计算器功能最基本的运算包括加减乘除四则运算,而为了更好的交互,本功能基于链表栈实现,首先介绍下链表栈的操作:
    (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;
}

windows控制台运行效果windows控制台运行效果

带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;
}
  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

博创客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值