声明:
我是小菜鸟,不会上传图片。下面的代码也仅仅可以计算出结果,运行效率可能一点也不高效。
为了能够早日转正,还是厚着脸皮发出来吧。
程序简介:
四则运算计算器,支持+、-、*、/运算,支持()、[]、{}。
无表达式合法性验证,所以请输入合法的表达式(例如,()中不能嵌套[]、{}。)
另外,不支持浮点数,但是很容易修改。
算法简介:
本程序的前身是一个仅支持+、-、*、/运算的计算器,之后可轻易添加括号支持。
首先介绍一下前身,以表达式 1+ 2*3*4为例:
这个表达式中有1、2、3、4这几个操作数;有+、*、*这几个运算符。并且可以断定
操作数的个数肯定是运算符个数加1。
算法中用到如下两个对应的数据结构:
typedef struct _VAL_ITEM {
int nValue;
BOOL bAval; // 是否有效
} VAL_ITEM, *PVAL_ITEM;
typedef struct _OPT_ITEM {
char cOpt;
BOOL bHasCal; // 是否计算
} OPT_ITEM, *POPT_ITEM;
1、扫描整个表达式,得到运算符个数,假设为N
2、分配N个OPT_ITEM,N+1个VAL_ITEM
3、重新扫描表达式,若是运算符,则依次放到OPT_ITEM结构中;
若是操作数,则依次放到VAL_ITEM结构中。bHasCal初始为FALSE,
bAval初始为TRUE。
下面开始就是真正地计算部分了,真正的计算次数也就是运算符个数,
如果该运算符已经计算过了,则将bHasCal设为TRUE。计算过程中还要
从VAL_ITEM取出两个操作数,计算结果保存到第一个操作数(这个保证
了数组中第一个VAL_ITEM结构中就是最终的计算结果),第二个操作数
的bAval设为FALSE。具体的怎么取操作数,其实就是向前遍历、向后遍
历,找到bAval为TRUE的结构即可。
4、计算*、/
5、计算+、-
扩展:添加()、[]、{}支持
在上面的基础上可以很轻松的添加对括号的支持。
例如: ((1+2)*2) + 1,
扫描‘(’,这里我们忽略空格,第1个字符即为‘(’,然后查找‘)’,
定位到第6个字符。然后在第1个和第6个之间再次查找‘(’,如果找到了
说明它们之间不匹配,否则匹配成功。
1、匹配成功时:
把之间的表达式拷贝出来,交给上面的函数计算。计算结果还要把刚刚的
整个表达式连同()给替换掉,也就是生成新的中间表达式,然后重新扫描。
2、匹配不成功:
向后继续扫描
如果找不到‘(’则直接计算即可。
对于[]、{}这里不再赘述,与上面相同。
完整代码:
// by lazy_cat
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <Windows.h>
#define IsOpt(c) (c == '+' || c == '-' || c == '*' || c == '/')
typedef struct _VAL_ITEM {
int nValue;
BOOL bAval; // 是否有效
} VAL_ITEM, *PVAL_ITEM;
typedef struct _OPT_ITEM {
char cOpt;
BOOL bHasCal; // 是否计算
} OPT_ITEM, *POPT_ITEM;
int GetValueIndex(PVAL_ITEM pValItem, int nOptIndex, int nMaxIndex, BOOL bIsLeft)
{
int nLeftIndex = nOptIndex, nRightIndex = nOptIndex + 1;
switch (bIsLeft)
{
case TRUE:
while (nLeftIndex >= 0) {
if (pValItem[nLeftIndex].bAval)
return nLeftIndex;
nLeftIndex--;
}
break;
case FALSE:
while (nRightIndex <= nMaxIndex) {
if (pValItem[nRightIndex].bAval) {
pValItem[nRightIndex].bAval = FALSE;
return nRightIndex;
}
nRightIndex++;
}
break;
}
return -1;
}
int CalWithOutBracket(char *szExp)
{
int nResult = 0;
int nOptCount = 0; // 运算符个数
for (int i = 0; TRUE; i++)
{
if (IsOpt(szExp[i]))
nOptCount++;
if (!szExp[i])
break;
}
POPT_ITEM pOptItem = (POPT_ITEM)malloc(sizeof(OPT_ITEM) * nOptCount);
PVAL_ITEM pValItem = (PVAL_ITEM)malloc(sizeof(VAL_ITEM) * (nOptCount + 1));
int nOptPos = 0, nValPos = 0;
char szNum[16] = { 0 };
int nDest = 0;
for (int i = 0; TRUE; i++)
{
if (szExp[i] >= '0' && szExp[i] <= '9')
szNum[nDest++] = szExp[i];
else
{
if (nDest)
{
pValItem[nValPos].nValue = atoi(szNum);
pValItem[nValPos].bAval = TRUE;
nValPos++;
nDest = 0;
RtlZeroMemory(szNum, sizeof(szNum));
}
if (IsOpt(szExp[i])) {
pOptItem[nOptPos].cOpt = szExp[i];
pOptItem[nOptPos].bHasCal = FALSE;
nOptPos++;
}
}
if (!szExp[i])
break;
}
for (int i = 0; i < nOptCount; i++)
{
if (pOptItem[i].cOpt == '*' || pOptItem[i].cOpt == '/')
{
int nLeftIndex = GetValueIndex(pValItem, i, nOptCount, TRUE);
int nRightIndex = GetValueIndex(pValItem, i, nOptCount, FALSE);
switch (pOptItem[i].cOpt)
{
case '*':
pValItem[nLeftIndex].nValue *= pValItem[nRightIndex].nValue;
break;
case '/':
pValItem[nLeftIndex].nValue /= pValItem[nRightIndex].nValue;
break;
}
pOptItem[i].bHasCal = TRUE;
}
}
for (int i = 0; i < nOptCount; i++)
{
if (!pOptItem[i].bHasCal)
{
int nLeftIndex = GetValueIndex(pValItem, i, nOptCount, TRUE);
int nRightIndex = GetValueIndex(pValItem, i, nOptCount, FALSE);
switch (pOptItem[i].cOpt)
{
case '+':
pValItem[nLeftIndex].nValue += pValItem[nRightIndex].nValue;
break;
case '-':
pValItem[nLeftIndex].nValue -= pValItem[nRightIndex].nValue;
break;
}
pOptItem[i].bHasCal = TRUE;
}
}
nResult = pValItem[0].nValue;
free(pOptItem);
free(pValItem);
return nResult;
}
void CalBracket(char *szExp, char cLeftBrc, char cRightBrc)
{
char *pStart = strchr(szExp, cLeftBrc);
while (pStart)
{
char *pEnd = strchr(pStart, cRightBrc);
char szPart[64];
RtlZeroMemory(szPart, sizeof(szPart));
strncpy(szPart, pStart + 1, pEnd - pStart - 1);
if (!strchr(szPart, cLeftBrc))
{
char szTmpExp[256] = { 0 }, szNum[16] = { 0 };
strncpy(szTmpExp, pStart + 1, pEnd - pStart - 1);
sprintf(szNum, "%d", CalWithOutBracket(szTmpExp));
RtlZeroMemory(szTmpExp, sizeof(szTmpExp));
strncpy(szTmpExp, szExp, pStart - szExp);
strcat(szTmpExp, szNum);
strcat(szTmpExp, pEnd + 1);
strcpy(szExp, szTmpExp);
pStart = strchr(szExp, cLeftBrc);
continue;
}
pStart = strchr(pStart + 1, cLeftBrc);
}
}
void main()
{
SetConsoleTitle(TEXT("lazy_cat"));
char szExp[256] = { 0 };
printf("输入要计算的表达式:");
scanf("%[^\n]s", szExp);
CalBracket(szExp, '(', ')');
CalBracket(szExp, '[', ']');
CalBracket(szExp, '{', '}');
printf("计算结果:%d\n", CalWithOutBracket(szExp));
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课