原题出处
对应LeetCode的227题,链接:https://leetcode-cn.com/problems/basic-calculator-ii/submissions/
题目描述
* 题目:实现一个科学计算器完成基本的计算功能
* 输入描述:加减乘除的输入数据
* 输出描述:计算结果
* 示例:输入:-1*6 输出:-6
实现思路
总体思路:将字符串解析后,遇到运算符号+-*/则进行出入栈操作,遇到数字则进行转换;
细节处理:遇到*和/两种运算,优先级高于+和-,因此遇到*和/之后将前后两个数字一并读取,并将计算后的结果入栈;
容易出错的用例:
i、运算的计算式过长,数字过多,栈空间不足,容易溢出;
ii、输入的表达式没有运算符时处理;
题目延伸
运算的数字超大,超过int或long long的表达范围时,应当以处理字符串的形式进行。具体以人计算的过程参考实现。
代码实现(包含常出错测试用例)
/* 包含经常出错的测试用例 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define STACK_SIZE_MAX 512
#ifndef INT_MAX
#define INT_MAX 2147483647
#endif
#define SYM_PLUS 1 /* 加 */
#define SYM_MINUS 2 /* 减 */
#define SYM_MULTI 3 /* 乘 */
#define SYM_ADDI 4 /* 除 */
/* 堆栈基本数据结构 */
typedef struct stackDB
{
int stack[STACK_SIZE_MAX];
int top;
}StackDB_T;
int calcAllStack(StackDB_T* src)
{
int res = 0;
int index = 0;
while (index < src->top) {
res += src->stack[index];
index++;
}
return res;
}
/* 入栈 */
void stackPush(StackDB_T* src, int num)
{
if (src == NULL) {
return ;
}
/* 如果堆栈溢出,则压缩 */
if (src->top == STACK_SIZE_MAX - 1) {
int tmp = calcAllStack(src);
memset(src, 0,sizeof(StackDB_T));
src->stack[src->top] = tmp;
src->top++;
}
src->stack[src->top] = num;
src->top++;
}
/* 出栈 */
int stackPop(StackDB_T* src)
{
if (src == NULL) {
return -1;
}
int tmp = 0;
if(src->top == 0) {
tmp = src->stack[0];
src->stack[0] = 0;
return tmp;
}
tmp = src->stack[src->top - 1];
src->stack[src->top - 1] = 0;
src->top--;
return tmp;
}
int getNextNum(char* src, int* retValue)
{
int tmp = 0; /* 将字符串转为数字的结果存放变量 */
int numCount = 0; /* 记录数字的长度 */
if (*src == '*' || *src == '/') {
src++;
}
while (*src == ' ') {
src++;
numCount++;
}
while(*src <= '9' && *src >= '0') {
tmp = tmp * 10 + (*src - '0');
src++;
numCount++;
}
*retValue = tmp;
return numCount;
}
/* 计算器 */
int calculate(char * s){
char *pSStart = s;
int res = 0;
char symFlag = 0; /* 符号标识 */
StackDB_T calcStack;
int frontNum, backNum, jump;
unsigned long long convTmp;
memset(&calcStack, 0, sizeof(calcStack));
while (*pSStart != '\0') {
switch(*pSStart) {
case ' ':
break;
case '*':
frontNum = stackPop(&calcStack); /* 把前面的数字出栈 */
jump = getNextNum(pSStart, &backNum); /* 获取后面的数字并跳过对应长度 */
stackPush(&calcStack, frontNum * backNum); /* 将乘法计算结果入栈 */
pSStart += jump ; /* 跳过后面一个数字 */
break;
case '/':
frontNum = stackPop(&calcStack); /* 把前面的数字出栈 */
jump = getNextNum(pSStart, &backNum); /* 获取后面的数字并跳过对应长度 */
stackPush(&calcStack, frontNum / backNum); /* 将乘法计算结果入栈 */
pSStart += jump ; /* 跳过后面一个数字 */
break;
case '-':
symFlag = SYM_MINUS;
break;
case '+':
symFlag = SYM_PLUS;
break;
default:
convTmp = 0;
while (*pSStart <= '9' && *pSStart >= '0') {
convTmp = convTmp * 10 + *pSStart - '0';
pSStart++;
}
pSStart--; /* 如果前面处理到数字,则需要后退一个等待前面的完成 */
if (symFlag == SYM_MINUS) {
convTmp = -convTmp;
}
stackPush(&calcStack, convTmp);
break;
}
pSStart++;
}
res = calcAllStack(&calcStack);
return res;
}
/****************************************** 以下是测试用例 *******************************************/
int test_1()
{
char buf[32]="3+2*2";
printf("----------------------Test Case 1--------------------------\n");
printf("[input]:%s\n", buf);
int res = calculate(buf);
if (res == 7) {
printf("[INFO]:Test Case 1 Passed!\n");
return 0;
}
printf("[Error]:test Case 1 Failed!\n[Out]:%d [Exp]:7\n",res);
return -1;
}
int test_2()
{
char buf[]="3/2";
printf("----------------------Test Case 2--------------------------\n");
printf("[input]:%s\n", buf);
int res = calculate(buf);
if (res == 1) {
printf("[INFO]:Test Case 2 Passed!\n");
return 0;
}
printf("[Error]:test Case 2 Failed!\n[Out]:%d [Exp]:1\n",res);
return -1;
}
int test_3()
{
char buf[]=" 3+5 / 2 ";
printf("----------------------Test Case 3--------------------------\n");
printf("[input]:%s\n", buf);
int res = calculate(buf);
if (res == 5) {
printf("[INFO]:Test Case 3 Passed!\n");
return 0;
}
printf("[Error]:test Case 3 Failed!\n[Out]:%d [Exp]:5\n",res);
return -1;
}
int test_4()
{
char buf[]="-2* 3/1 +5 / 2 -32 + 1";
int exp = -35;
printf("----------------------Test Case %s--------------------------\n",__FUNCTION__);
printf("[input]:%s\n", buf);
int res = calculate(buf);
if (res == exp) {
printf("[INFO]:Test Case %s Passed!\n",__FUNCTION__);
return 0;
}
printf("[Error]:test Case %s Failed!\n[Out]:%d [Exp]:%d\n",__FUNCTION__, res, exp);
return -1;
}
int test_5()
{
char buf[]="-100* 32/1 +50000 / 20000 - 36522 + 101212";
int exp = 61492;
printf("----------------------Test Case %s--------------------------\n",__FUNCTION__);
printf("[input]:%s\n", buf);
int res = calculate(buf);
if (res == exp) {
printf("[INFO]:Test Case %s Passed!\n",__FUNCTION__);
return 0;
}
printf("[Error]:test Case %s Failed!\n[Out]:%d [Exp]:%d\n",__FUNCTION__, res, exp);
return -1;
}
int test_6()
{
char buf[]="31235/32 + 12332 / 2*2-3211";
int exp = 10097;
printf("----------------------Test Case %s--------------------------\n",__FUNCTION__);
printf("[input]:%s\n", buf);
int res = calculate(buf);
if (res == exp) {
printf("[INFO]:Test Case %s Passed!\n",__FUNCTION__);
return 0;
}
printf("[Error]:test Case %s Failed!\n[Out]:%d [Exp]:%d\n",__FUNCTION__, res, exp);
return -1;
}
int test_7()
{
char buf[]="2147483647";
int exp = 2147483647;
printf("----------------------Test Case %s--------------------------\n",__FUNCTION__);
printf("[input]:%s\n", buf);
int res = calculate(buf);
if (res == exp) {
printf("[INFO]:Test Case %s Passed!\n",__FUNCTION__);
return 0;
}
printf("[Error]:test Case %s Failed!\n[Out]:%d [Exp]:%d\n",__FUNCTION__, res, exp);
return -1;
}
int test_8()
{
char buf[]="0";
int exp = 0;
printf("----------------------Test Case %s--------------------------\n",__FUNCTION__);
printf("[input]:%s\n", buf);
int res = calculate(buf);
if (res == exp) {
printf("[INFO]:Test Case %s P

本文详细介绍了如何使用栈数据结构实现一个科学计算器,完成基本的加减乘除运算功能。文章探讨了算法实现思路,包括如何处理优先级较高的乘除运算,以及避免栈溢出等问题。同时,提供了丰富的测试用例,确保计算器功能正确性和稳定性。
最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



