[C++ Calculator 项目] 初试

Calculator V1.0

注:这是一个C++计算器项目的初始部分。
大体功能简介:
  • 能够输入一串数学表达式
  • 逐字符扫描,提取数字和符号得到一组队列
  • 逐行输出提取的符号与数字
实现代码如下:
  • scan.h
#ifndef _SCAN_H_
#define _SCAN_H_
#include<string>
#include<iostream>
#include<queue>
using std::string;
using std::queue;
class Scan{
    queue<string> expression;	 //用于接收表达式
    bool isDigit(char c);		//判断是否是数字或'.'
    void numErr();				//当数值超过10位后报错
public:
    Scan(){};                        //    ->暂无
    ~Scan(){};                       //    ->暂无
    queue<string> getExp(){return expression;}  //返回expression队列的内容
    queue<string> toStringQueue(string );  //toStringQueue将string的内容逐字符提取转换为string队列
}; 
#endif
  • print.h
#ifndef _PRINT_H_
#define _PRINT_H_
#include<iostream>
#include<string>
#include<queue>
using namespace std;
class Print{
    // parameter 
public:
    Print(){};    //暂无
    ~Print(){}; 	//暂无
    bool putq(queue<string> output); //逐行输出string队列
};
#endif
  • Calculator.cpp
    #include<iostream>
    #include<string>
    #include"scan.h"
    #include"print.h"
    int main()
    {
    	using namespace std;
    	string exp;			//exp用来接收键盘输入的表达式
    	getline(cin,exp);
    	Scan input;
    	Print output;
    	output.putq( input.toStringQueue(exp));	//调用input类的toStringQueue方法,返回一个<string>的队列,传入output的putq方法输出队列
    	cin.get();  
    	return 0;
    }
  • scan.cpp
    #include"scan.h"
    bool Scan::isDigit(char c)										//判断是否是数字或句点
    {
    	if( (c<='9'&&c>='0')|| c=='.')return true;
    
    	return false;
    }
    
    void Scan::numErr()
    {
    	std::cout<<"numerical ERROR
";
    	std::cin.get();
    	std::exit(-1);
    }
    
    queue<string> Scan::toStringQueue(string input)
    {
    	int i=0,dlen=0;			//i用于循环,dlen用于表示数值长度
    	int len=input.length();	//用input的长度len来作为循环条件
    	string& c=input;	//用c来代替input不然打的太累了=。=
    	string temp="";		//temp用来暂储input中的元素
    	while( i<len){
    		if(isDigit(c[i]) ){
    			temp+=c[i];
    			dlen++;
    			if(dlen>10)numErr();		//判断数值是否超出范围
    			if( (i+1)<len && isDigit(c[i+1]) && ++i ) continue;	//判断是否还有下一个字符以及下一个字符是不是数字或句点,若是++i跳回循环开头,
    										//    否则,将条件后的数个语句执行
    		}
    		else temp=c[i];
    		dlen=0;								/重置dlen
    		expression.push(temp);			//将temp推入队列
    		temp="";
    		i++;
    	}
    	return expression;
    }
  • print.cpp
        #include"print.h"
        bool Print::putq(queue<string> output)
        {
        	int count=0;     //count计数确保输出正确
        	while( !output.empty() ){
        		cout<<output.front()<<endl;
        		output.pop();
        		count++;
        	}
        	return count==output.size();  //返回输出个数是否正确的布尔值
        }
源文件可以在[github](https://github.com/F0UR3r/object-oriented/tree/master/Calculator)上下载

代码编写过程遇到的问题:

  这次的题目不是很难,尤其是之后题目一直在改简单,所以代码写得也比较流畅。
  不过原先编写Print类时,根本不知道queue是什么数据类型,于是就去百度了好多,不敢说都懂了,但是至少会用了。
  除了一些边边角角的问题外,在第一次编写完toStringQueue方法后进入了疯狂的调试状态,bug不停的出现,原始代码如下

  当时的想法是逐字符提取,

  •  若是字符则直接push(temp)

  •  若是数字temp+=c[i++],把数字接到temp上

    •  再判断下一个c[i] 是否也是数字

      • 是,就把下一个接到temp后面,dlen++
      • 否,就push(temp),重置temp和dlen

我的IDE是vs2010,编译过了,但是运行的时候会弹出警告“ string subscript out of range
string 下标越界,一开始百度并没懂是这意思,一直在找是不是自己哪里的指针或者什么的没初始化或者哪里进入了死循环

后来在DEBUG模式下才找到罪魁祸首,上面这个语句中,当i不小于len后程序向下运行

但是运行到箭头处时,此时的c[i]已经超出下标范围了,之后又一次i++了,

而且在下面这步的循环条件中的dlen++<=10有错,这使得数值最大可达11位

第一次写的这个函数的逻辑有点乱,把上面所有bug总结了一遍后,开始大换血,重新写了一个逻辑稍清晰的,正确运行。


最后......当然是总结啦:

因为一个不小心,耗费了自己一下午时间来debug,简直血与泪的代价啊,事实告诉自己以后写程序还是要多想一会,否则大把大把的时间就这样没了,同时也告诫自己以后要多注重程序的逻辑,这样才能写出更健壮的代码来。

作为大学生活的第一个C++项目,肯定有许多不足之处,欢迎看过的各位给我批评与建议,谢谢!

原文地址:https://www.cnblogs.com/tr3e/p/5222778.html