前言:
? 近期复习了数据结构与算法,于是刚好就写个小程序来巩固一下自己的记忆。知道大家很烦看长篇大论,因此简单的写了下。
功能描述:
- 实现基本数学运算 +、-、*、/
- 实现带括号()复杂混合运算
- 实现开方,幂次运算(不使用官方C标准库)
- 针对输入的表达式具有异常判断及提示功能
- 可实现从文本文件中读取多个运算表达式进行计算
实现效果:
因为本程序的主要目的是为了复习数据结构与算法,因此没有写的很复杂。下图为功能1、2、3、4的实现效果,成功实现。其中@代表开方运算,^代表幂方运算
提前准备一个文件,写入需要计算的表达式,如图下:
进行测试,测试结果如下:
同时将结果存于文本文件中:
实现原理:
程序主要包括计算模块、输入处理模块、显示模块、窗口句柄设置模块等。
采用主要的数据结构:栈、字符串
- 为了方便计算,需要将中缀表达式转为后缀表达式,转换过程利用了栈
主要代码:
void calculateExpression(myStrs* expression, double* resultBuf, unsigned int* errBuf)
{
for (int i = 0; i < expression->size; i++)
{
errBuf[i] = getValue(expression->data[i].str, &resultBuf[i]);
}
}
ERROR_TYPE getValue(const char* expression, double* result)
{
ERROR_TYPE error;
if ((error = checkOperator(expression)) != NONE_ERROR) {
return error;
}
myStrs infix;
myStrs posfix;
myDoubleStack doubleStack;
initmyDoubleStack(&doubleStack);
initMyStrs(&infix, DEFAULT_SIZE);
initMyStrs(&posfix, DEFAULT_SIZE);
separateString(expression, " ", &infix);
if ((error = infixToPosfix(&infix, &posfix)) != NONE_ERROR)
{
return error;
}
for (int i = 0; i < posfix.size; i++)
{
if (!isContainOperator(posfix.data[i].str))
{
double num = atof(posfix.data[i].str);
pushmyDoubleStack(&doubleStack, num);
}
else {
if (strstr(posfix.data[i].str, "@")) {
double a = popmyDoubleStack(&doubleStack);
pushmyDoubleStack(&doubleStack, sqrt(a));
}
else {
double a = popmyDoubleStack(&doubleStack);
double b = popmyDoubleStack(&doubleStack);
if (strstr(posfix.data[i].str, "+"))
{
pushmyDoubleStack(&doubleStack, b + a);
}
else if (strstr(posfix.data[i].str, "-")) {
pushmyDoubleStack(&doubleStack, b - a);
}
else if (strstr(posfix.data[i].str, "*")) {
pushmyDoubleStack(&doubleStack, b * a);
}
else if (strstr(posfix.data[i].str, "/")) {
if (a >= -DOUBLE_ZERO_NUM && a <= DOUBLE_ZERO_NUM)
{
return ERROR_DIVISOR_ZERO;
}
pushmyDoubleStack(&doubleStack, b / a);
}
else if (strstr(posfix.data[i].str, "^")) {
pushmyDoubleStack(&doubleStack, pow(b, a));
}
}
}
}
*result = topmyDoubleStack(&doubleStack);
destoryMyStrs(&infix);
destoryMyStrs(&posfix);
return NONE_ERROR;
}
ERROR_TYPE infixToPosfix(myStrs* infix, myStrs* posfix)
{
myCharStack charStack;
initmyCharStack(&charStack);
int index = 0;
char posfixBuf[MAX_BUF_LEN] = { 0 };
for (int i = 0; i < infix->size; i++)
{
char ch = infix->data[i].str[0];
if (!isContainOperator(infix->data[i].str))
{
if (isParentheses(infix->data[i].str))
{
if (ch == '(')
{
pushmyCharStack(&charStack, ch);
}
else {
while (!isEmptymyCharStack(&charStack) && topmyCharStack(&charStack) != '(')
{
char topChar = popmyCharStack(&charStack);
posfixBuf[index++] = topChar;
posfixBuf[index++] = ' ';
}
if (isEmptymyCharStack(&charStack)) return ERROR_FORMAT;
else popmyCharStack(&charStack);
}
}
else {
strcat(posfixBuf, infix->data[i].str);
index += strlen(infix->data[i].str);
posfixBuf[index++] = ' ';
}
}
else {
while (!isEmptymyCharStack(&charStack) && topmyCharStack(&charStack) != '(' && lessOrEqualTop(ch, topmyCharStack(&charStack)))
{
char topChar = popmyCharStack(&charStack);
posfixBuf[index++] = topChar;
posfixBuf[index++] = ' ';
}
pushmyCharStack(&charStack, ch);
}
}
while (!isEmptymyCharStack(&charStack))
{
char topChar = popmyCharStack(&charStack);
posfixBuf[index++] = topChar;
posfixBuf[index++] = ' ';
}
if (strstr(posfixBuf, "("))
{
return ERROR_FORMAT;
}
separateString(posfixBuf, " ", posfix);
return NONE_ERROR;
}
可进一步设计方向:
-
实现超大数的 +、-、*、/运算,例如:1821293854612893461023894562349817 * 2346189460234192384617361238946 = ? 需要考虑问题:
直接采用C语言原本的基本数据类型long long int 计算,溢出怎么半?改怎样解决?
采用字符串来存储数据
-
进一步完善交互界面设计 -
加入更多运算方式sin、cos 等 -
Qt设计界面
|