c++计算器后续(3)

自娱自乐:

本来只是想改改第二次的代码规范的,然后好像把原来的代码玩坏了,真是尴尬。。。然后大概是又发现了一些东西。以上。

main的参数:

大概是说main函数的括号里是可以带参数的,写成这个样子:int main(int argc, char* argv[]),然后这时main函数的输入来自命令行。也就是用cmd直接调用.exe文件时,可以在后面跟上一些数,然后这些数就会被输到main函数里。其中argc表示输入的参数个数,argv则是一个指针数组,指向各个参数,然后argv[0]表示的是.exe文件的路径。写了个简单的代码玩了玩,感觉大概就是这么回事吧。附上代码和调用结果:

    #include<iostream>
    using namespace std;
    int main(int argc, char* argv[])
    {
        int i = argc;
        while (i > 0)
        {
            cout << argv[argc - i] << endl;
            i--;
        }
        return 0;
    }

大概也是因为我这么玩了,然后一不小心把argv数组里的元素当成了字符串,然后我Calculator项目里的main函数写成了这样:

    #include<iostream>
    #include<queue>
    using namespace std;
    int main(int argc,char * argv[])
    {
        Scan CScan;
        Print CPrint;
        Calculation CCalculate;
        string s_input = argv[argc-1];  //输入的字符串 
        queue<string> qs;   //数字和运算符分开的队列 
        double ans; //四则算式的答案 
        qs = CScan.ToStringQueue(s_input); 
        ans = CCalculate.CalculateStringQueue(qs); 
        if (argv[1] == "-a")
        {
            CPrint.PrintAns(s_input, ans);
        } 
        else
        {
            CPrint.PrintAns(ans);
        }
        return 0;
    }

结果当然是cmd里面输入'-a'它也只输出一个答案,然后不幸的还是个错误的答案,啊,这是后话,被我玩坏的代码。

于是又再去看看int main(int argc,char * argv[]),指向字符的指针,然后就凌乱了,那我前面的输出是什么鬼,不应该输出地址吗,你输出元素也不该是字符串啊。

然后就写了一些东西来试试看:

    #include<iostream>
    #include<string.h>
    using namespace std;
    int main()
    {
        string str;
        cin >> str;
        char* p1 = &str[0];
        printf("%x\n",p1);
        cout << p1 << endl;
        cout << *p1 << endl;
        cout << "==分割线==" << endl; 
        char** p2 = &p1;
        printf("%x\n",p2);
        cout << p2 << endl;
        cout << *p2 << endl;
        cout << "==分割线==" << endl; 
        char arr[3] = {'a', 'b', 'c'};
        cout << &arr[0] << endl;
        return 0;
    }

按照我的理解来说,输出p1应该是输出str的首地址才对,但是cout直接输出了str。然后输出*p大概还是符合预期的,只有一个a。所以cout不用指定输出的类型,如果你给它一个地址,它大概会输到底的意思?好像有点模糊的体会,不是很懂。

那我的判断条件argv[1] == "-a",大概是比较第一参数的地址和"-a"的整型值(就像字符有整型值那样吧),会一样才奇怪。

于是去百度了比较字符串的函数,有挺多乱七八糟的,考不考虑大小写啊啥的,感觉strcmp(const char*, const char*)就可以,形参大概是那么个意思,相等就返回零,然后要#include<string.h>
大概改完了玩坏的代码第一步,然后是计算的问题。。。

代码相关:

大概是知道代码错在哪里了,遍历队列的条件不能写i < qs.size(),因为每次都会弹出队列元素,所以qs.size()一直都在变的,这样没办法遍历整个队列。怎么说,还好没有找很久。。。

还有一件事是,全局变量不能在.h文件里声明,不然每include一次都会再定义一次,会报错说重复定义。

然后这次的代码改动主要是main函数改为从命令行传参,Print类里的输出用了函数重载,Scan类里面的拆分区分了负号和减号以及加了个Calculation类。代码挺长,不具体贴,这里给出链接:点我啊有些注释在dev c++ 里面明明是对齐好的,传上去就乱来。还有六个字变成了乱码,明明是一样的编码不是,其他注释至少还是汉字。去改了下缩进,git表示文件没有变,那我也没办法,将就先看吧。。。那我还是贴一些好了,还有一些调用样例:

Calculation.h

#ifndef CALCULATION_H
#define CALCULATION_H
#include<iostream>
#include<queue>
#include<stack>
using namespace std;
class Calculation
{
    public: 
        //计算并返回算式的答案 
        double CalculateStringQueue(queue<string> qs);
        //返回当前情况在优先级数组里的位置 
        char GetPosition(string CharStackTop, string t_str);
        //借助优先级数组,用两个栈来计算表达式 
        void CalculateByStack(char order, string t_str);	
};
#endif

Calculation.cpp

/******************************************************************************* 
    FileName: Calculation.cpp
    Author:newmoon      
    Version :2.0        
    Date:16/07/25   
    Description:
        定义实现Calculation类中的相关方法 
    Function List:	 
        double CalculateStringQueue(queue<string> qs)	计算并返回算式的答案  
        void CalculateByStack(char order, string t_str)	用两个栈来计算表达式
        char GetPosition(string CharStackTop, string t_str)	返回优先级数组位置
    History:               
        <author>  <time>   <version >   <desc>        
        newmoon   16/07/27    2.0     代码规范相关   
*******************************************************************************/
#include"Calculation.h"
#include<iostream>
#include<sstream> 
#include<queue>
#include<stack>
using namespace std;
int flag;	//是否继续计算 
double ans;	//最终的计算结果 
stack<double> NumStack;	//储存数字的栈 
stack<string> CharStack;	//储存运算符的栈 
//用于运算优先级判断的数组
//行表示运算符栈顶的运算符
//列表示算式当前遍历到的运算符
//">"表示栈顶优先级高,应弹出来进行计算
//"<"表示栈顶优先级低,遍历到的运算符直接入栈
//"="表示遍历到底,NumStack最后一个元素即答案 
//或是遍历到")"且栈顶为"(",应弹出栈顶继续遍历
//"0"表示算式有误 
                   //'+', '-', '*', '/', '(', ')', '#' 
char order[7][7] = {{'>', '>', '<', '<', '<', '>', '>'}, //'+'
                    {'>', '>', '<', '<', '<', '>', '>'}, //'-'
                    {'>', '>', '>', '>', '<', '>', '>'}, //'*'
                    {'>', '>', '>', '>', '<', '>', '>'}, //'/'
                    {'<', '<', '<', '<', '<', '=', '0'}, //'('
                    {'>', '>', '>', '>', '0', '>', '>'}, //')'
                    {'<', '<', '<', '<', '<', '0', '='}  //'#'
};
/**********************************************   
    Description:返回优先级数组位置    
    Input:运算符栈的栈顶元素string CharStackTop
          算式当前遍历到的运算符string t_str 
    Output:无  
    Return:优先级数组的字符型元素order[x][y];   
    Others:无 
***********************************************/
char Calculation :: GetPosition(string CharStackTop, string t_str)
{
    int x, y;
    switch (CharStackTop[0])
    {
        case '+':
            x = 0;
            break;
        case '-':
            x = 1;
            break;
        case '*':
            x = 2;
            break;
        case '/':
            x = 3;
            break;
        case '(':
            x = 4;
            break;
        case ')':
            x = 5;
            break;
        case '#':
            x = 6;
            break;
    }
    switch (t_str[0])
    {
        case '+':
            y = 0;
            break;
        case '-':
            y = 1;
            break;
        case '*':
            y = 2;
            break;
        case '/':
            y = 3;
            break;
        case '(':
            y = 4;
            break;
        case ')':
            y = 5;
            break;
        case '#':
            y = 6;
            break;
    }
    return order[x][y];
}
/*****************************************   
    Description:用两个栈来计算表达式    
    Input:优先级数组元素char order
        算式当前遍历到的运算符string t_str
    Output:无   
    Return:无  
    Others:答案存在全局变量ans里 
******************************************/
void Calculation :: CalculateByStack(char order, string t_str)
{
    char m_order;	//表示优先级数组中的位置
    double num, num1, num2;	//用于辅助计算 
    //借助优先级数组进行具体计算 
    switch (order)
    {
        //栈顶的运算符优先级较高
        //弹出栈顶的运算符和两个数来计算 
        case '>':
            num1 = NumStack.top();
            NumStack.pop();
            num2 = NumStack.top();
            NumStack.pop();
            switch (CharStack.top()[0])
            {
                case '+':
                    num = num1 + num2;
                    NumStack.push(num);
                    CharStack.pop();
                    break;
                case '-':
                    num = num2 - num1;
                    NumStack.push(num);
                    CharStack.pop();
                    break;
                case '*':
                    num = num1 * num2;
                    NumStack.push(num);
                    CharStack.pop();
                    break;
                case '/':
                    num = num2 / num1;
                    NumStack.push(num);
                    CharStack.pop();
                    break;
            }                
            //下一个栈顶元素优先级仍然较高则继续计算 
            while(!CharStack.empty() && flag)
            {
                m_order = GetPosition(CharStack.top(), t_str);
                CalculateByStack(m_order, t_str);
            }
            break;
        //栈顶运算符优先级较低
        //遍历到运算符直接入栈 
        case '<':
            flag = 0;
            CharStack.push(t_str);
            break;
        case '=':
            //表示遍历结束 
            if (t_str[0] == '#')
            {
                //最终答案 
                ans = NumStack.top();
                NumStack.pop();
                CharStack.pop();
            }
            //遍历到")"且栈顶为"(",应弹出栈顶继续遍历
            else
            {
                CharStack.pop();
                flag = 0;
            }
            break;
        //算式有误的"0"情况 
        default:
            cout << "输入的算式有误" << endl;
            exit(1);
    }
}
/*******************************************   
    Description:计算并返回算式的答案     
    Input:拆分好好的算式队列queue<string> qs 
    Output:无   
    Return:算式的答案   
    Others:无 
********************************************/
double Calculation :: CalculateStringQueue(queue<string> qs)
{
    //辅助判断遍历结束 
    qs.push("#");
    CharStack.push("#");
    char m_order;	//表示优先级数组中的位置 
    string t_str;	//遍历到的队列元素 
    double t_num;	//辅助将string转为double
    int n = qs.size();	//每次循环qs.size()都会减小 
    stringstream stream;	//辅助将string转为double
    //遍历队列开始计算 	
    for (int i = 0; i < n; i++)
    {
        flag = 1;	//是否继续计算 
        t_str = qs.front();
        qs.pop();
        //遍历到运算符,进行相应计算 
        if (t_str == "+" || t_str == "-" || t_str == "*" 
            || t_str == "/" || t_str == "(" 
                || t_str == ")" || t_str == "#")
        {
            //借助优先级数组判断运算的优先级 
            m_order = GetPosition(CharStack.top(), t_str);
            //实际的计算 
            CalculateByStack(m_order, t_str);
        }
        //遍历到数字,转为double并入栈		 
        else
        {
            stream.clear();
            stream << t_str;
            stream >> t_num;
            NumStack.push(t_num);
        }
    }
    return ans;
}

调用样例:

posted @ 2016-07-28 13:32  archeroc  阅读(328)  评论(0编辑  收藏  举报