C语⾔计算器详细教程(四则运算、⼩数、括号)
⽬录
前⾔
最近做嵌⼊式设备开发刚好需要⽤到对数据的公式处理,写了⼀个四则运算器,顺便分享给有需要各位
提⽰:以下为正⽂内容
⽬标功能
假设有如下参数:
float value  =5;
char* formula  =" 1 * 2 / 3 + 4 / x + 6 ";
实现将设备采集的数值替换公式中的字符 ’ x ’ ,并计算出结果。这⾥封装了两个⼯具函数来实现此需求,第⼀个公式⽤于将数值 value 代⼊公式中的字符 ’ x ',第⼆个公式⽤于计算四则运算式。
/*
*  功能:字符串的指定内容替换
*  参数:
*    str    ⽬标字符串
*    oldstr  被替换的字符串
*          newstr  替换的字符串
*/
char*Utils_Strrpc(char*str,char*oldstr,char*newstr);
/*
*  功能:四则运算
*  参数:
*    formula 运算公式
递归函数c语言规则
*    length 公式长度
*/
CALCULATERESULT utils_Calculate(char* formula,int length);
四则运算函数返回的结构体如下:
/*
*  内容:四则运算结果
*  ⽬标函数:
*    utils_Calculate
*/
typedef struct CALCULATERESULTSTRUCT {
int  err;// 格式错误码
float  value;// 运算值
} CALCULATERESULT;
不带括号的公式处理
我们先以不带括号的公式为例,有公式如下:
char* formula =" 1 * 2 / 3 + 4 / 5 + 6 ";
第⼀步,我们建⽴两个数组,分别存储数字和运算符:
digits  ={123456}
operators ={*/-/+}
四则运算第⼀个要处理的问题就是 “加减” 与 ”乘除“ 运算符的执⾏先后问题,我们来看下⾯两组式⼦:
_1  =" 1 + 2 * 3 ";
//  _2  =  " 1 + 0 ? 6 " ;
_2  =" 1 + 0 + 6 ";
_3  =" 1 - 6 / 2 ";
// _4  =  " 1 - 0 ? 3 " ;
_4  =" 1 - 0 - 3 ";
不难看出1和2、3和4两组式⼦的结果是相同的。所以在这⾥,我们解决问题的⽅法是:
将 ”乘除“ 运算符的左值变为0,将右值变为左右两值"乘除"运算的结果;
将 "乘除" 运算符变为左边第⼀个"加减"运算符,如为公式的第⼀个运算符,则为默认为'+';
紧接着⽰例公式,我们处理如下:
digits  {123456}
operators {*/-/+}
--------------------------------------------------------------
digits  {023456}
operators {?/-/+}
--------------------------------------------------------------
digits  {006456}
operators {??-/+}
--------------------------------------------------------------
digits  {0060206}
operators {??-?+}
--------------------------------------------------------------
digits  {0060206}
operators {??-?+}
-
-------------------------------------------------------------
digits  {0060206}
operators {++--+}
第⼆步,我们定义⼀个结果值 value,让结果值等于digits[ 0 ],并根据符号依次加减运算digits[ 1 ] 到 digits [ n ],最后value的值就是我们公式处理的结果值,紧接着⽰例公式,我们处理如下:
value  =  digits[0]
00
-----------------------------------------------------
value  operators[0] digits[1]
0+0=0
-----------------------------------------------------
value  operators[1] digits[2]
0+6=6
-----------------------------------------------------
value  operators[2] digits[3]
6-0=6
-----------------------------------------------------
value  operators[3] digits[4]
6-20=-20
-----------------------------------------------------
value  operators[4] digits[5]
-20+6=-16
带括号的公式处理
四则运算第⼆个需要处理的问题就是括号带来的运算优先级问题,这⾥我们使⽤递归的⽅式处理,有公式如下:
char*formula  =" 1 * ( 2 + ( 3 + 4 ) / 5 + 6 ) ";
因为有两层括号,实际程序执⾏时会执⾏两次递归。我们建⽴两个数组,分别存储数字和运算符,函数执⾏递归情况如下:
-----------------------------------------------------// 开始层函数的数组
digits  {1?}
operators {*}
-----------------------------------------------------// 第⼀层递归函数的数组
digits  {2?56}
operators {+/+}
-----------------------------------------------------// 第⼆层递归函数的数组
digits  {34}
operators {+}
-----------------------------------------------------
第⼆层递归函数按照 “不带括号的公式处理” 执⾏完后,返回的计算结果 ’ 7 ’ 替代第⼀层递归函数素组digits中 ’ ? ’ 位的值,得到如下:
-----------------------------------------------------// 第⼀层递归函数的数组
digits  {1?}
operators {*}
-----------------------------------------------------// 第⼆层递归函数的数组
digits  {2756}
operators {+/+}
同理,执⾏第三层函数,得到如下:
-----------------------------------------------------// 第⼀层递归函数的数组
digits  {19.4}
operators {*}
最后即可得出结果为10.4。
源码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define CALCULATE_ERR_REPEAT    -1  // 重复运算符
#define CALCULATE_ERR_SYMBOL    -2  // ⾮法字符
#define CALCULATE_ERR_NUMBER    -3  // 数字与运算符数量不对应
#define CALCULATE_ERR_BEYOND    -4  // 数字数量,运算符数量,数字长度超出预设值
#define CALCULATE_MAX_DIGITS    30  // 限制数字最⼤数量
#define CALCULATE_MAX_OPERATOR  30  // 限制运算符最⼤数量
#define CALCULATE_MAX_DIGIT    30  // 限制数字最⼤位数
/*
*  内容:运算结果
*  函数: utils_Calculate
*/
typedef struct CALCULATERESULTSTRUCT {
int err;
float value;
} CALCULATERESULT;
/*
*  功能:字符串指定内容替换
*  参数:
*    str    ⽬标字符串
*    oldstr  被替换的字符串
*          newstr  替换的字符串
*/
char*Utils_Strrpc(char*str,char*oldstr,char*newstr)
{
char bstr[strlen(str)];
memset(bstr,0,sizeof(bstr));
memset(bstr,0,sizeof(bstr));
int i;
for(i =0; i <strlen(str); i++){
if(!strncmp(str + i, oldstr,strlen(oldstr))){
strcat(bstr, newstr);
i +=strlen(oldstr)-1;
}else{
strncat(bstr, str + i,1);
}
}
strcpy(str, bstr);
return str;
}
/*
*  功能:实时数据四则运算处理
*  参数:
*    formula 运算公式
*    length 公式长度
*/
CALCULATERESULT Utils_Calculate(char* formula,int length)
{
CALCULATERESULT result ={0,0.0f};// 返回结构体
int idx;// 索引
int digitsNum =0;// 数字数量
float digits[CALCULATE_MAX_DIGITS];// 存储数据的数组memset(digits,'\0',sizeof(digits));
int optNum =0;// 运算符数量
char operator[CALCULATE_MAX_OPERATOR];// 存储运算符的数组memset(operator,'\0',sizeof(operator));
int digitNum =0;// 单个数字字符串
char digit[CALCULATE_MAX_DIGIT];// 存储单个数字字符串的数组memset(digit,'\0',sizeof(digit));
/* 提取数字和符号到数组 */
char*pointer = formula;
while(length--)
{
switch(*pointer){
case'+':
case'-':
case'*':
case'/':
if(0== digitNum &&'-'==*pointer){
digit[digitNum++]=*pointer;
}else{
if(-1== digitNum){
digitNum =0;
goto NEXT;
goto NEXT;
}
if(0== digitNum){
< = CALCULATE_ERR_REPEAT;
goto END;
}
if(CALCULATE_MAX_DIGITS == digitsNum -1){
< =-4;
goto END;
}
digits[digitsNum++]=atof(digit);
memset(digit,'\0',sizeof(digit));
digitNum =0;
NEXT:
operator[optNum++]=*pointer;
}
break;
case'(':
{
char*pointer_son;
int ExistEnd =0;
pointer_son =++pointer;
while(length--){
if('('==*pointer){
ExistEnd--;
}
if(')'==*pointer){
ExistEnd++;
}
if(1== ExistEnd){
break;
}
pointer++;
}
/* 括号内的字符串执⾏递归 */
CALCULATERESULT result_son =Utils_Calculate(pointer_son, pointer - pointer_son);
if(0> ){
< = ;
goto END;
}
digits[digitsNum++]= result_son.value;
memset(digit,'\0',sizeof(digit));
digitNum =-1;
}
break;
case'0':
case'1':
case'2':
case'3':
case'4':
case'5':

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。