zaas 发表于 2011-2-22 19:32

代码非常烂的四则运算计算器(windows SDK 版)

本帖最后由 zaas 于 2011-2-23 15:29 编辑

有兴趣的逆一下,看看到底有多烂。。。

修了下bug,
加了点东东,写成WIndows SDK版的,欢迎测试:





前两天写了个四则运算计算器,设计思路简单说的话,无非相当于设置一个堆栈,根据加减乘除括号的优先级,每次取出算式的一部分,在栈里计算结果,然后转换为字符串再填回去。用到的都是已经学过的知识。

这种方法有一定缺陷,字符串返回的时候sprintf(),返回的精度达不到double了,(当然如果增加对指数的判断会好很多:D ),算式越长越复杂,误差会越大,但精度控制在小数点后两位应该没有问题。

不过代码很烂。仅仅使用malloc设置了堆,代码写的乱七八糟。昨晚思考了一下,觉得改用struct 会比较清晰明了,因此先把框架搭出来了,发出来算作一种思路。

等将来学的更深入一点之后,可能会有更好的思路和方法?

立此存照。//main.cpp
#include "main.h"

void main()
{   
    CalStr cal;   
    InitCal( & cal);            //初始化字符串
    if(!Calculator( & cal))      //计算,不成功则退出
    {
      return;
    };
    Output( & cal);            //输出
}//main.h
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct CalStr
{
    char original;                //输入的字符串
    char replace;                //待替换的括号内字符串
    char childstr;                //括号内字符串
    char childreplace;            //待替换的单一算式
    interror;                        //出错的旗标
}CalStr;

void      InitCal(CalStr *cal);                //初始化
int       Calculator(CalStr *cal);      //计算
void      Output(CalStr *cal);                //输出


void      Input(CalStr *cal);                //输入
void      CheckInput(CalStr *cal);            //输入检查

int       GetChildStr(CalStr *cal);      //取得括号内子串
int       CalChildStr(CalStr *cal);      //计算子串
void      ReplaceStr(CalStr *cal,double result);//用计算结果替换原串中的子串

int       GetSymbol(CalStr *cal);      //获取运算符
double    GetFrontStr(CalStr *cal,int flag);    //运算符前边的数字串
double    GetBehindStr(CalStr *cal,int flag);    //运算符后边的数字串
double    CalDouble(double x,double y);      //计算结果

int       CheckLength (char * Str);    //长度检测,防溢出//run.cpp
#include "main.h"

void InitCal(CalStr *cal)
{
    do
    {
      Input(cal);
      CheckInput(cal);
    } while (cal->error);            //输入有误,重新输入

}

int Calculator(CalStr *cal)
{
    int flag;
    double result;
    do
    {
      flag=GetChildStr(cal);    //取得括号内子串
      result=CalChildStr(cal);
      if (cal->error)            //计算失败退出
      {
            return 0;
      }
      ReplaceStr(cal,result);    //替换原串
    } while (flag);                //还有括号,继续
   
    return 1;   
}

void Output(CalStr *cal)
{
    ;
}

///////////////////////////////////
void Input(CalStr *cal)
{

}

void CheckInput(CalStr *cal)
{
    cal->error=0;
}

///////////////////////////////////
intGetChildStr(CalStr *cal)
{
    return 0;
}

int CalChildStr(CalStr *cal)
{
    int flag;
    double x,y,result;
    do
    {
      flag=GetSymbol(cal);
      x=GetFrontStr(cal,flag);
      y=GetBehindStr(cal,flag);
      if (cal->error)                //长度溢出,退出
      {
            return 0;
      }
      result=CalDouble(x,y);
      if (cal->error)                //除零错误,退出
      {
            return 0;
      }
      ReplaceStr(cal,result);      //替换单一算式
    }    while(!flag)                //所有单一算式计算完成结束
}

void ReplaceStr(CalStr *cal,double result)
{
    ;                            //此处计算结果转回字符串并替换需替换的部分
}

///////////////////////////////////
int GetSymbol(CalStr *cal)
{
    return 0;                        //加减乘除的优先级判定
}

double GetFrontStr(CalStr *cal,int flag)
{
    return 0;
}

double GetBehindStr(CalStr *cal,int flag)
{
    return 0;
}

double CalDouble(double x,double y)
{
    return 0;
}

///////////////////////////////////
int CheckLength (char * Str)
{
    return 0;
}

插曲` 发表于 2011-2-22 20:05

{:1_934:}不是很了解 干什么用的, 沙发下~

datochan 发表于 2011-2-23 08:36

如果LZ给出源代码,再加上一定的讲解,那不是更好:loveliness:。
我还可以给LZ加精华~

datochan 发表于 2011-2-23 08:49

我刚才又想了下。感觉不是很妥当:LZ没有给出源代码……

一是感觉LZ的帖子不值我给的评分,又摸不透LZ发这个帖子的用意在哪里。
我觉得LZ的帖子发在原创板块或者按照LZ所说,为了让大家逆下,那可以放在逆向板块……

希望LZ在一个星期之内能够补上源码,我会保留此评分,如果能再附上一定的讲解,我会给LZ加精华。
倘若LZ在一个星期内不由对帖子做任何改动,我会将帖子移动到相应板块中,并对评分做一定的减少。
希望LZ理解。{:1_903:}

zaas 发表于 2011-2-23 15:27

本帖最后由 zaas 于 2011-2-23 15:27 编辑

bester 发表于 2011-2-23 08:49 static/image/common/back.gif
我刚才又想了下。感觉不是很妥当:LZ没有给出源代码……

一是感觉LZ的帖子不值我给的评分,又摸不透LZ发 ...
hoho。。。。发个框架吧,推翻重写的框架。新代码还没填上。

binliao 发表于 2011-2-23 16:21

思路不错.

赤目狂人 发表于 2011-3-10 16:37

回头好好看看
页: [1]
查看完整版本: 代码非常烂的四则运算计算器(windows SDK 版)