zoukankan      html  css  js  c++  java
  • Calculator Part Ⅰ

    • GitHub/object-oriented
    • The title of the work
    • 关于这次的作业,一开始我是觉得不难的,毕竟学长在已经提供了足够多的提示,实现步骤、需要那些方面的知识等等。但是在个人在编写代码时还是遇到了不少麻烦,甚至在一个bug上卡了整整一天……
    • <queue>的相关用法

    【代码】

    main.cpp

    #include "scan.h"
    #include "print.h"
    #include<iostream>
    #include<string>
    #include<queue>
    using namespace std;
    
    int main()
    {
        Scan in;
        Print out;
    
        string input;
        cin>>input;
        if(!in.checkNumberLen(input))
    	{
            return 0;
    	}//首先判断输入字符串中数字串长度不超过10位
    	out.printQueue(in.ToStringQueue(input));
    
    	return 0;
    }
    

    scan.h

    #ifndef SCAN_H
    #define SCAN_H
    #include<iostream>
    #include<queue>
    #include<string>
    using namespace std;
    
    class Scan
    {
    public:
    	queue<string> ToStringQueue(string input);
    	bool checkNumberLen(string input);
    private:
    	queue<string> m_q;
    };
    
    #endif
    

    scan.cpp

    #include "scan.h"
    #include<iostream>
    #include<string>
    #include<queue>
    using namespace std;
    
    bool Scan::checkNumberLen(string input)
    {
    	int numberLen=0;
    	for(int i=0;i<input.size();i++)
    	{
        	if(input[i]==45||input[i]==47||input[i]<44&&input[i]>39)
        	{
    			numberLen=0;
    		}	
    
        	else if(input[i]>47&&input[i]<58)//小数点不参与计数
        	{
    			numberLen++;
    			if(numberLen>10)//当连续数字达到10位时报错并退出
    			{
    				cout<<"[ERROR]The length of number out of ten!"<<endl;
    				return false;
    				break;
    			}
    		}
    	}
    	return true;
    }
    
    queue<string> Scan::ToStringQueue(string input)
    {
    	int numberLen=0;
    	string numbers,operators;//numbers用于存储连续数字字符,operatoes用于存储运算字符
       	for(int i=0;i<input.size();i++)
    	{
    		if(input[i]==45||input[i]==47||input[i]<44&&input[i]>39)
    		{
        		//当运算符左端出现数字,代表上一串数字序列已经结束,这时把这个数字串推入序列
    			if(input[i-1]>47&&input[i-1]<58)
    			{
    				for(int j=i-1;numberLen>0;j--,numberLen--)
    				{
    					numbers=input[j]+numbers;//将多个数字字符组成一个连续的字符串
    				}
        			m_q.push(numbers);
    				numbers.clear();//须清空字符串numbers
    				numberLen=0;//须归零数字串长度numberLen
    			}
    			operators=input[i];
    			m_q.push(operators);
    		}
    
        	else if(input[i]>47&&input[i]<58)//在ASCII代码中表示数字的范围
        	{
        		numberLen++;
        		if(i==input.size()-1)
        		{
        			for(int j=i;numberLen>0;j--,numberLen--)
        			{
        				numbers=input[j]+numbers;
        			}
        			m_q.push(numbers);
        			numbers.clear();
    			}
            }
    	}
    	return m_q;
    }
    

    print.h

    #ifndef PRINT_H
    #define PRINT_H
    #include<iostream>
    #include<queue>
    #include<string>
    using namespace std;
    
    class Print
    {
    public:
    	void printQueue(queue<string> m_q);
    };
    
    #endif
    

    print.cpp

    #include "print.h"
    #include<iostream>
    #include <cstdlib>
    #include<string>
    #include<queue>
    using namespace std;
    
    void Print::printQueue(queue<string> m_q)
    {
    	while(!m_q.empty())//调用<queue>中自带的函数,将元素弹出,直至队列为空
    	{
    		cout<<m_q.front()<<endl;
    		m_q.pop();
    	}
    }
    

    【运行检查】

    • 能够达成分离数字串与运算符,并按顺序输出的目的;
    • 在数字超过10位时报错退出;

    alt text

    【关于思路】

    • 全局思路:关于大致思路我一开始想的比较麻烦,我原先在Class ScanClass Print中定义了不同成员变量queue<string> m_q,打算用Scan::ToStringQueue(string input)来接收处理字符串,推入队列,然后再用swap()直接将Scan::ToStringQueue(string input)Print::printQueue()中的队列内容对调……这样其实是有些愚蠢的,不但耗费更多的资源,而且成员变量受访问限定符private约束,是不能直接访问的,意识到这些,我就改成了现在的方法:用Scan::ToStringQueue(string input)处理好字符串后推入队列,然后return队列,再用Print::printQueue()直接接收打印队列。
    • 局部思路:遍历队列并分离数字串与运算符是这个程序的核心部分。通过循环逐个扫描字符,当扫描到数字时numberLen累加;当扫描到运算符时,先检查上一位字符是否为数字,若为数字则代表上一位数字(串)结束,将其推入队列,numberLen归零,否则将运算符推入队列。最终写好的这段代码我有点不太满意,感觉处理方法略微繁琐了,但暂时没有什么改进措施,希望看看别人的思路,刷新一下自己的思考方式,再修改一下。

    【出现的问题】

    • 程序要求能够在遇到超出10位的数字时报错,这段报错代码我原先是写在Scan::ToStringQueue(string input)中的,在累加numberLen的同时观测是否超出10位,但是这就遇到一个问题,我报错的话就要返回“0”或“false”,这和函数规定的返回值类型queue<string>不相符,于是我只好另外写一个检查函数,在main函数调用ToStringQueue()前先调用checkNumberLen(),若超出10位则return 0,使main函数终止。
    • 我在代码完成后很长一段时间被卡在一个错误上,报错信息为:[Error]Id returned 1 exit status。真相是我在定义成员函数的时候把checkNumberLen打成了checkNunberLen,后面调用的时候用的又是checkNumberLen,很细小同时很致命。改正这些地方之后,还是报错,并且这次的报错信息连看都看不懂(很遗憾当时忘记记录这个错误信息了),我又翻了翻代码,把创建类时自动生成的构造函数和析构函数删掉,然后编译通过了。
    • 关于这个debug的过程我还有一些不理解,没有查到相关的解答,问了同学也没得到答案,所以在此说明一下情况,希望能够交流一下:我在创建类时保留了自动生成的构造函数和析构函数,并且还在构造函数中利用初始化列表传入了一个值,这个值赋给Scan::m_iNumberLen(数字长度我一开始是选择在数据成员中定义的,后来改到成员函数里了),m_iNumberLen我在ToStringQueue()checkNumberLen()中都有调用。情况大致如此期待解答~

    【反思】

    1. 我认为既然C++面向对象,那么main函数中的各种行为执行都应该通过调用对象的方法来实现,这一点个人感觉没有很好的做到;
    2. 编写代码前应先将思路理清,将大致原理和主要使用的函数写下来,考虑一下可行性;
    3. 编写代码的时候还是要细心,debug类似于checkNumber的错误,真的没什么意义;
    4. 英文水平亟需加强,很多好的解答都在外文网站上,看的时候很抓狂,但努力看完的确能够获得许多收获。
  • 相关阅读:
    4、提取看似无用的委托变量,减少构造开销
    Cloud Foundry buildpack
    mysql中engine=innodb和engine=myisam的区别
    Maven中dependencyManagement的作用
    bean
    servlet
    web服务器 应用服务器区别 web框架
    Java和Python的Web开发
    spring mvc controller 高并发问题
    es 批量添加数据
  • 原文地址:https://www.cnblogs.com/wyq0808/p/5277790.html
Copyright © 2011-2022 走看看