简易则混合运算

就不用帖全部代码了把,核心代码都在了

CCALC_NBL::CCALC_NBL(void)
{
}

CCALC_NBL::~CCALC_NBL(void)
{
}
//计算四则混合运算  
//str 运算式  len:字符串长度 result:结果
bool CCALC_NBL::GetCalcResult(const char * str, int Len, double * result)
{
    char calc_str[STRMAX] = { 0 };
    if (InitStr(str, Len, calc_str))
        return Calc(calc_str, Len, result);
    return false;
}

//初始化字符串 合法性检测去空格
bool CCALC_NBL::InitStr(const char * str, int Len, char * result)
{
    int index_str = 0, index_res = 0;
    //Stack<char> eax;
    for (; index_str < Len; index_str++)
    {
        char temp = str[index_str];
        if (temp <= '9' && temp >= '0' || temp >= '(' && temp <= '+' || temp >= '-' && temp <= '/')//判断是否是合法字符串
            result[index_res++] = temp;
        else if (temp == 0)//判断是否结束
            break;
        else if (temp != ' ')//如果是空格跳过不是空格报错
            return false;
    }
    result[index_res] = 0;
    return true;
}

//根据后辍表达式计算结果
bool CCALC_NBL::Calc(const char * str, int Len, double * result)
{
    char str_calc[STRMAX] = { 0 };
    char str_t[STRMAX] = { 0 };
    Stack<double> eax;
    int index = 0;
	//将中辍表达式转换成后辍表达式
    if (InitCalcStr(str, Len, str_calc, ' '))
    {
		//遍历后辍表达式
        while (str_calc[index] && index < Len)
        {
			//获取一个元素
            int step = GetOne_calc(str_calc + index, Len - index, str_t, ' ');
            if (step == 0)
                return false;
            index += step + 1;
			//如果是数字
            if (GetType(str_t[0]) == NUMBER)
            {
                double n;
				//转成double 入栈 也可以自己写数组算法,支持大数
                if (StrToDouble(str_t, step, &n))
                    if (!eax.IsFull())
                        eax.PUSH(n);
                    else
                        return false;
                else
                    return false;
            }
            else
            {
                double n1, n2, n3 = 0.0;
				//不是数字要栈最上面两个元素参与运算
                if (!eax.IsEmpty())
                    n2 = eax.POP();
                else
                    return false;

                if (!eax.IsEmpty())
                    n1 = eax.POP();
                else
                    return false;
				//根据元素 做运算
                switch (str_t[0])
                {
                case '+':
                    n3 = n1 + n2;
                    break;
                case '-':
                    n3 = n1 - n2;
                    break;
                case '*':
                    n3 = n1 * n2;
                    break;
                case '/':
                    n3 = n1 / n2;
                    break;
                default:
                    return false;
                    break;
                }
				//结果入栈
                if (!eax.IsFull())
                    eax.PUSH(n3);
                else
                    return false;
            }

        }
		//返回结果
        if (!eax.IsEmpty())
            *result = eax.POP();
        else
            *result = 0.0;
        return true;
    }
    return false;
}

//123 + 4  转成 123 4 +之后调用 同GetOne
int CCALC_NBL::GetOne_calc(const char * str, int Len, char * result, char fenge)
{
	//后搓表达式用分隔符分开,很好获取
    int index;
    for (index = 0; str[index] != fenge && index < Len; index++)
        result[index] = str[index];
    result[index] = 0;
    return index;
}

//把中辍表达式转成后辍表达式
bool CCALC_NBL::InitCalcStr(const char * str, int Len, char * result, char fenge)
{
    int index = 0, index2 = 0;
    char res[STRMAX] = { 0 };

    Stack<char> eax;//创建栈
    while (str[index] && index < Len)//遍历整个字符串
    {
		//获取一个元素
        int step = GetOne(str + index, Len - index, res);
        if (step == 0)
            return false;//获取失败就返回假
        index += step;//下标更新
        int type = GetType(res[0]);//获取当前元素的类型
        if (type == NUMBER)//如果是个数字就直接作为后辍表达式的一部分
        {
            int i;
            for (i = 0; i < step; i++)
                result[index2 + i] = res[i];
            index2 += i;
			//应为会有连续两个数字所以需要用分隔符分开
            result[index2++] = fenge;
        }
        else
        {
            if (eax.IsEmpty())//如果当前栈为空
            {
                if (res[0] == ')')//并且直接出现 ) 说明不合法
                    return false;
                else
                    eax.PUSH(res[0]);//入栈
            }
            else//栈不为空
            {
                if (res[0] == ')')//是 )
                {
                    char topch;
					//依次出栈直到遇到 ( 或者栈为空
                    while (!eax.IsEmpty() && (topch = eax.POP()) != '(')
                    {
                        result[index2++] = topch;
                        result[index2++] = fenge;
                    }
					//如果没有 ( 说明不合法
                    if (topch != '(')
                        return false;
                }
                else//不是 )
                {
					//如果栈顶元素不是括号 并且 当前元素不是 (
                    if (GetType(eax.GetTop()) != KUOHAO && res[0] != '(')
                    {
						//那就要判断当前元素和栈顶元素的优先级,如果当前元素的优先级小于栈顶元素的优先级,就要先做出栈操作。
                        if (GetType(res[0]) >= GetType(eax.GetTop()))
							//依次出栈作为后辍表达式的一部分,直到站为空或者栈顶元素的优先级大于栈顶元素的优先级。
                            while (!eax.IsEmpty() && GetType(eax.GetTop()) <= GetType(res[0]))
                            {
                                result[index2++] = eax.POP();
                                result[index2++] = fenge;
                            }
                    }
					//如果是(直接入栈 不是(做完以上操作之后也要入栈
                    eax.PUSH(res[0]);
                }
            }
        }
    }
	//最后依次出栈作为后辍表达式的一部分
    while (!eax.IsEmpty())
    {
        result[index2++] = eax.POP();
        result[index2++] = fenge;
    }
    result[index2] = 0;
    return true;
}

//123 + 4 ,result 第一次是123 第二次是 + 第三次是4 返回result长度
int CCALC_NBL::GetOne(const char * str, int Len, char * result)
{
    int index = 0;
    do
    {
        result[index] = str[index];
        index++;
        if ((GetType(str[0]) == ADDSUB || GetType(str[0]) == MULDIV) && 
			(GetType(str[index]) == ADDSUB || GetType(str[index]) == MULDIV
			 || GetType(str[index]) == KUOHAO))
            return false;
    } while (GetType(str[index]) == GetType(str[0]) && GetType(str[0]) == NUMBER && index < Len);
	//首先 除了数字要读多个字符外其他都只要读一次。每一次读取到的字符都是数字,当然读完整个表达式也就结束了。其次+-*/之后只能是数字

    result[index] = 0;
    return index;
}

//返回类型 主要为了 +- */ (可以判断优先级
int CCALC_NBL::GetType(char ch)
{
    if (ch == '(' || ch == ')')
        return KUOHAO;
    if (ch == '*' || ch == '/')
        return MULDIV;
    if (ch == '+' || ch == '-')
        return ADDSUB;
    if (ch == 0)
        return ZERO;
    return NUMBER;
}

//string转double
bool CCALC_NBL::StrToDouble(const char * str, int Len, double * res)
{
    int index_d, index;
    for (index_d = 0; index_d < Len; index_d++)
        if (str[index_d] == '.')
            break;
    for (index = index_d + 1; index < Len; index++)
        if (str[index] == '.')
            return false;

    double result = 0.0;
    double p = 0.1;

    for (index = 0; index < index_d; index++)
        result = result * 10 + (double)(str[index] - '0');
    for (index = index_d + 1; index < Len; index++)
    {
        result = result + (double)(str[index] - '0') * p;
        p /= 10.0;
    }
    *res = result;
    return true;
}

//Unicode转ansi
char* CCALC_NBL::UnicodeToAnsi(const wchar_t* szStr)
{
    int nLen = WideCharToMultiByte(CP_ACP, 0, szStr, -1, NULL, 0, NULL, NULL);
    if (nLen == 0)
        return NULL;
    char * pResult = new char[nLen];
    WideCharToMultiByte(CP_ACP, 0, szStr, -1, pResult, nLen, NULL, NULL);
    return pResult;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值