运行结果演示
基本思路
基本结构
键盘数据读入
运算实现原理
为了实现复杂的四则运算,首先需要考虑的是算数符号以及括号的优先级。具体实现流程如下:
- 如果是数字,则压入操作数栈中
- 如果是运算符,则有两种情况:
①如果运算符栈为空,则将其压入运算符栈中
②如果不为空,则比较其与运算符栈中的优先级,如果大于则压入栈中,否则从操作数栈中取出两个数进行相应计算 - 如果为* ) * ,取出操作数栈中两个数与运算符栈中运算符计算,结果压入操作数栈中。直至遇到* )*
- 将剩余操作数与运算符进行运算,直至操作数栈为空
实现准备
为了实现运算,需要准备简单的栈结构及其基本操作:
/*
简易栈实现
*/
int stackNum[255] = { 0 };
int stackNumTopIndex = -1;
char stackChar[255] = {};
int stackCharTopIndex = -1;
void pushNumStack(int num) {
stackNum[++stackNumTopIndex] = num;
}
void pushCharStack(char op)
{
stackChar[++stackCharTopIndex] = op;
}
bool isEmptyOfNumStack()
{
return stackNumTopIndex == -1;
}
bool isEmptyOfCharStack()
{
return stackCharTopIndex == -1;
}
int popNumStack() {
if (isEmptyOfNumStack()) {
return -1;
}
return stackNum[stackNumTopIndex--];
}
char popCharStack()
{
if (isEmptyOfCharStack()) {
return '!';
}
return stackChar[stackCharTopIndex--];
}
int peekNumStack()
{
return stackNum[stackNumTopIndex];
}
int peekCharStack()
{
return stackChar[stackCharTopIndex];
}
接着,实现对数据的一些基本功能函数文章来源:https://www.toymoban.com/news/detail-409710.html
/*
* 数据处理
*/
//获取算数符号优先级
int getPriority(char op)
{
int level = 0;
switch (op)
{
case '(':
level = 1;
break;
case '+':
case '-':
level = 2;
break;
case '*':
case '/':
level = 3;
break;
default:
break;
}
return level;
}
//是否是算数运算符
bool isOperator(char op)
{
if ( op== '+' || op == '-' || op == '*' || op == '/') {
return true;
}
else {
return false;
}
}
//进行相应计算
int Calculate(int lNum, char op, int rNum)
{
int result = 0;
switch (op)
{
case '+':
result = lNum + rNum;
break;
case '-':
result = lNum - rNum;
break;
case '*':
result = lNum * rNum;
break;
case '/':
if (rNum != 0) {
result = lNum / rNum;
}
break;
default:
break;
}
return result;
}
表达式运算代码
int getNum(string str) {
int result = 0;
int lNum, rNum;
int num = 0;
char op;
for (int i = 0; i < str.length();) {
if (isdigit(str[i])) {
//读入之后字符,判断是否为数字
num = 0;
while (isdigit(str[i])) {
num = num * 10 + (str[i] - '0');
i++;
}
pushNumStack(num);
}
else if (str[i] == '(') {
pushCharStack(str[i++]);
}
else if (isOperator(str[i])) { //运算符
//符号栈为空,将运算符压入栈中
if (isEmptyOfCharStack()) {
pushCharStack(str[i++]);
}
else {
while (!isEmptyOfCharStack()) {
//优先级低于或等于进行计算,得数压入数据栈中
if (getPriority(str[i]) <= getPriority(peekCharStack())) {
rNum = popNumStack();
lNum = popNumStack();
op = popCharStack();
pushNumStack(Calculate(lNum,op,rNum));
}else {
break;
}
}
pushCharStack(str[i++]);
}
}
else if (str[i] == ')') {
while (peekCharStack() != '(') {
op = popCharStack(); //取出栈顶操作符
int rNum = popNumStack();
int lNum = popNumStack();
result = 0;
result = Calculate(lNum, op, rNum);
pushNumStack(result);
}
popCharStack(); //弹出(
i++;
}
}
while (!isEmptyOfCharStack())
{
op = popCharStack();
int rNum = popNumStack();
int lNum = popNumStack();
result = 0;
result = Calculate(lNum, op, rNum);
pushNumStack(result);
}
return popNumStack();
}
完整代码
//引入键盘处理库 --> 第三方库
#include <Keypad.h>
/*
简易栈实现
*/
int stackNum[255] = { 0 };
int stackNumTopIndex = -1;
char stackChar[255] = {};
int stackCharTopIndex = -1;
void pushNumStack(int num) {
stackNum[++stackNumTopIndex] = num;
}
void pushCharStack(char op)
{
stackChar[++stackCharTopIndex] = op;
}
bool isEmptyOfNumStack()
{
return stackNumTopIndex == -1;
}
bool isEmptyOfCharStack()
{
return stackCharTopIndex == -1;
}
int popNumStack() {
if (isEmptyOfNumStack()) {
return -1;
}
return stackNum[stackNumTopIndex--];
}
char popCharStack()
{
if (isEmptyOfCharStack()) {
return '!';
}
return stackChar[stackCharTopIndex--];
}
int peekNumStack()
{
return stackNum[stackNumTopIndex];
}
int peekCharStack()
{
return stackChar[stackCharTopIndex];
}
/*
* 数据处理
*/
//获取算数符号优先级
int getPriority(char op)
{
int level = 0;
switch (op)
{
case '(':
level = 1;
break;
case '+':
case '-':
level = 2;
break;
case '*':
case '/':
level = 3;
break;
default:
break;
}
return level;
}
//是否是算数运算符
bool isOperator(char op)
{
if ( op== '+' || op == '-' || op == '*' || op == '/') {
return true;
}
else {
return false;
}
}
//进行相应计算
int Calculate(int lNum, char op, int rNum)
{
int result = 0;
switch (op)
{
case '+':
result = lNum + rNum;
break;
case '-':
result = lNum - rNum;
break;
case '*':
result = lNum * rNum;
break;
case '/':
if (rNum != 0) {
result = lNum / rNum;
}
break;
default:
break;
}
return result;
}
//字符串数字拼接
/*
拆分表达式并计算
*/
int getNum(String str) {
int result = 0;
int lNum, rNum;
int num = 0;
char op;
for (int i = 0; i < str.length();) {
if (isdigit(str[i])) {
//读入之后字符,判断是否为数字
num = 0;
while (isdigit(str[i])) {
num = num * 10 + (str[i] - '0');
i++;
}
pushNumStack(num);
}
else if (str[i] == '(') {
pushCharStack(str[i++]);
}
else if (isOperator(str[i])) { //运算符
//符号栈为空,将运算符压入栈中
if (isEmptyOfCharStack()) {
pushCharStack(str[i++]);
}
else {
while (!isEmptyOfCharStack()) {
//优先级低于或等于进行计算,得数压入数据栈中
if (getPriority(str[i]) <= getPriority(peekCharStack())) {
rNum = popNumStack();
lNum = popNumStack();
op = popCharStack();
pushNumStack(Calculate(lNum,op,rNum));
}else {
break;
}
}
pushCharStack(str[i++]);
}
}
else if (str[i] == ')') {
while (peekCharStack() != '(') {
op = popCharStack(); //取出栈顶操作符
int rNum = popNumStack();
int lNum = popNumStack();
result = 0;
result = Calculate(lNum, op, rNum);
pushNumStack(result);
}
popCharStack(); //弹出(
i++;
}
}
while (!isEmptyOfCharStack())
{
op = popCharStack();
int rNum = popNumStack();
int lNum = popNumStack();
result = 0;
result = Calculate(lNum, op, rNum);
pushNumStack(result);
}
return popNumStack();
}
//读取用户输入值
String getExpression(){
String res = "";
//读取串口监视器中表达式
while(true){
int in = Serial.read();
if(in != -1){
if(in == '='){
break;
}else{
res = res +(char)in;
}
}
}
return res;
}
//矩阵键盘设置
const byte rows = 4; //four rows
const byte cols = 4; //three columns
char keys[rows][cols] = {
{'1','2','3','+'},
{'4','5','6','-'},
{'7','8','9','*'},
{'D','0','=','/'}
};
byte rowPins[rows] = {9, 8, 7, 6}; //connect to the row pinouts of the keypad
byte colPins[cols] = {5, 4, 3, 2}; //connect to the column pinouts of the keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, rows, cols );
String getExpressionFromKeyBoard(){
String res = "";
while(true){
char key = keypad.getKey(); //获取当前输入字符
if(key && key != '=' && key != 'D'){
res += key;
Serial.print("当前输入表达式:");
Serial.println(res);
}else if(key && key == '='){
break;
}else if(key && key == 'D'){
res = res.substring(0,res.length()-1);
Serial.print("当前输入表达式:");
Serial.println(res);
}
}
Serial.println();
return res;
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
String expression = getExpressionFromKeyBoard();
Serial.print("当前表达式:");
Serial.println(expression);
Serial.print("运算结果为:");
int res = getNum(expression);
Serial.println(res);
}
总结
此代码仅仅对于算数计算做出了详细解释,对于Arduino与矩阵之间的连接电路以及按键读取未做出详细解释。
其相应的接线方式可参照代码中对应接口进行连接。同时,键盘键位有限,不能将本程序完全演示完毕(可包含括号运算,支持复杂算术运算)文章来源地址https://www.toymoban.com/news/detail-409710.html
到了这里,关于Arduino利用键盘矩阵实现计算器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!