C语言计算器详细教程(四则运算、小数、括号)

您所在的位置:网站首页 计算器不算小数点怎么算 C语言计算器详细教程(四则运算、小数、括号)

C语言计算器详细教程(四则运算、小数、括号)

2023-12-10 17:18| 来源: 网络整理| 查看: 265

目录 前言目标功能不带括号的公式处理带括号的公式处理源码测试

前言

最近做嵌入式设备开发刚好需要用到对数据的公式处理,写了一个四则运算器,顺便分享给有需要各位

提示:以下为正文内容

目标功能

假设有如下参数:

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 #include #include #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 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 result.err = CALCULATE_ERR_NUMBER; goto END; } /* 消除"乘除"运算符 */ for (idx = 0; 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 if (0 == idx) { operator[idx] = '+'; } else { operator[idx] = operator[idx-1]; } } } /* 顺序执行"加减"运算 */ result.value = digits[0]; for (idx = 0; 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#


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3