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 运算公式* 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 = { 1 2 3 4 5 6 } 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 { 1 2 3 4 5 6 }operators { * / - / + }
--------------------------------------------------------------digits { 0 2 3 4 5 6 }operators { ? / - / + }
--------------------------------------------------------------digits { 0 0 6 4 5 6 }operators { ? ? - / + }
--------------------------------------------------------------digits { 0 0 6 0 20 6 }operators { ? ? - ? + }
--------------------------------------------------------------digits { 0 0 6 0 20 6 }operators { ? ? - ? + }
--------------------------------------------------------------digits { 0 0 6 0 20 6 }operators { + + - - + }
第二步,我们定义一个结果值 value,让结果值等于digits[ 0 ],并根据符号依次加减运算digits[ 1 ] 到 digits [ n ],最后value的值就是我们公式处理的结果值,紧接着示例公式,我们处理如下:
value = digits[0]0 0
-----------------------------------------------------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 ? 5 6}operators { + / + }
----------------------------------------------------- // 第二层递归函数的数组digits { 3 4}operators { + }
-----------------------------------------------------
第二层递归函数按照 “不带括号的公式处理” 执行完后,返回的计算结果 ’ 7 ’ 替代第一层递归函数素组digits中 ’ ? ’ 位的值,得到如下:
----------------------------------------------------- // 第一层递归函数的数组digits { 1 ? }operators { * }
----------------------------------------------------- // 第二层递归函数的数组digits { 2 7 5 6}operators { + / + }
同理,执行第三层函数,得到如下:
----------------------------------------------------- // 第一层递归函数的数组digits { 1 9.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));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;}if (0 == digitNum) {result.err = CALCULATE_ERR_REPEAT;goto END; }if (CALCULATE_MAX_DIGITS == digitsNum - 1) {result.err = -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 > result_son.err) {result.err = result_son.err;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':case '6':case '7':case '8':case '9':case '.':digit[digitNum++] = *pointer;break;case ' ':case '\n':break;default:result.err = CALCULATE_ERR_SYMBOL;goto END; }if (0 == length && 0 < digitNum) {digits[digitsNum++] = atof(digit);memset(digit, '\0', sizeof(digit));digitNum = 0;}pointer ++;}if (digitsNum != optNum + 1) {result.err = CALCULATE_ERR_NUMBER;goto END;}/* 消除"乘除"运算符 */for (idx = 0; idx < optNum; idx ++) {if ('*' == operator[idx]) {digits[idx+1] = digits[idx] * digits[idx+1];digits[idx] = 0;operator[idx] = '?';}if ('/' == operator[idx]) {digits[idx+1] = digits[idx] / digits[idx+1];digits[idx] = 0;operator[idx] = '?';}}for (idx = 0; idx < optNum; idx ++) {if ('?' == operator[idx]) {if (0 == idx) {operator[idx] = '+';} else {operator[idx] = operator[idx-1];}}}/* 顺序执行"加减"运算 */result.value = digits[0];for (idx = 0; idx < optNum; idx ++) {if ('+' == operator[idx]) {result.value += digits[idx + 1];}if ('-' == operator[idx]) {result.value -= digits[idx + 1];} }END:return result;
}int main(int argc, char* argv[])
{char formula[1024];if (3 != argc) {printf("请输入正确的参数\n");return 0;}sprintf(formula, "%s", argv[2]);Utils_Strrpc(formula, "x", argv[1]);CALCULATERESULT resault = Utils_Calculate(formula, strlen(formula));printf("%g\n", resault.value);return 0;
}
测试
程序第一个参数为数值,第二个参数为公式,执行测试:
root@zth:~/newDigate# gcc test.c -o test
root@zth:~/newDigate# ./test 32.6 \(\(x-10.3\)*1.43+13.77\)*10.132
462.617
root@zth:~/newDigate#
C语言计算器详细教程(四则运算、小数、括号)相关推荐
- c语言利用栈实现四则运算(包括括号小数),DataStructure_1用栈实现四则运算(c语言)...
有一句计算机界中的至理名言: 程序=数据结构+算法 可见数据结构是多么地重要啊......呵呵 今天开始复习了一下数据结构 , 解决了以前的一个问题: 用栈这个数据结构实现四则运算 算法思想是借鉴了& ...
- jQueryEasyUI实现房贷计算器详细教程1--HTML部分
1.HTML文件的基本构成 我们从最基础的一段HTML代码开始编程: <!DOCTYPE html> <html><head><meta charset=&q ...
- C#实现多语言切换详细教程(附源码)
源代码下载地址: CSDN:点击下载 GitHub:点击下载 环境说明:Windows10,VS2017,.NET Framework4.0 详细步骤: 1.新建一个C#的.NET Framework ...
- jQueryEasyUI实现房贷计算器详细教程2--jQuery部分
1.从载入JavaScript开始 jQuery 是一个 JavaScript 库,极大地简化了 JavaScript 编程.这一部分介绍下载和载入jQuery. 源代码: <script sr ...
- VS code配置C语言,详细教程,初学者专用(附需要的插件)(win系统)
vscode配置C语言首先下载vscode,这里我就不多说了. 我们自己在使用vscode配置c语言后发现c语言根本就不能运行,是因为我们缺少一个配置c语言的插件需要我们自己下载,因为vscode不提 ...
- 我的Go+语言初体验——基于CentOS系统搭建Go+语言环境详细教程
文章目录
- 新手C语言开发详细教程
1. 下载资源包(编写软件是NotePad++, 编译工具是gcc) 代码编写软件网址:https://download.csdn.net/download/m0_52983689/87128595 ...
- oracle数据库sql培训,Oracle数据库SQL语言实战培训教程(全面、详细、案例、精讲)套餐...
风哥oracle数据库SQL语言实战培训教程(案例.精讲)套餐,DBA必备技能. 套餐介绍: 风哥Oracle数据库SQL语言实战培训教程(案例.精讲)套餐,DBA必备技能. 内容: SQL语言基础入 ...
- Python语言学习之数值、小数、空格那些事:python和数值、小数、空格的使用方法之详细攻略
Python语言学习之数值.小数.空格那些事:python和数值.小数.空格的使用方法之详细攻略 目录 Python与数值那些事 1.python保留两位小数/保留小数点位数 Python去掉空格的方 ...
- c4d语言包英文,Maxon Cinema 4D R23(C4D R23)中英文安装及设置详细教程(附下载)
中文包安装方法: 离线方法:打开下载好的语言包文件,在顶部菜单栏找到"Help>Manual Installation" 打开语言包的位置,选择要安装的.c4dupdate包 ...
最新文章
- Dubbo基础专题——第二章(Dubbo工程简单实践)
- 【剑指offer-Java版】30最小的K个数
- 立足优势,你的网站会更精彩
- java 银行存取款_用Java编写银行存钱取钱
- ffmpeg合并音频(转)
- 创建一个简单的ArcGIS Server ASP.NET网页
- COGS2421 简单的Treap
- On the Robustness of Semantic Segmentation Models to Adversarial Attacks论文解读
- Mac 苹果电脑创建一个新的管理员账号
- 电脑进入pe时蓝屏_进PE蓝屏的几个原因
- Liber 1. 《活着》:人生如逆旅,我亦是行人
- OpenGL:太阳、地球、月球模型模拟动画
- vue导出excel加一个进度条_Vue实现在前端导出Excel
- c语言放空一个数组,数组越界真可怕,莫名就闯到了别人家
- 制图操作案例:ArcGIS Pro鹰眼图快速制图
- python 条形图 负值_使用python matplotlib获取正负值的堆积条形图
- rdkit 分子性质描述符(Descriptors)
- 网关 Spring Cloud Gateway 监控 actuator
- select2.js实现拼音搜索支持
- 小程序合成海报图片,高度自适应