zoukankan      html  css  js  c++  java
  • 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
    ",p1);
            cout << p1 << endl;
            cout << *p1 << endl;
            cout << "==分割线==" << endl; 
    
            char** p2 = &p1;
            printf("%x
    ",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;
    }
    

    调用样例:

  • 相关阅读:
    gdb调试工具
    一步步理解Linux之中断和异常
    英语感受 5月份英语思维
    2013年6月4日星期二
    2013年5月29日星期三
    2013年6月3日星期一
    第22周六晚上
    2013年5月26日星期日
    2013年5月28日20:16:21
    2013年6月2日星期日
  • 原文地址:https://www.cnblogs.com/mingyueanyao/p/5714468.html
Copyright © 2011-2022 走看看