计算器第三次作业——完善

github链接



很高兴在我的不懈努力下,终于是把第三次作业完善了,对我来说真的是很不容易,当我完成这道题时,我觉得一切都是值得的。上次做的时候,对于整个类的实现并没有很清晰的认识,在这次完善作业过程中,我通过对比和类比,对于整个类的结构有了比较清楚地认识。接下来我就这次作业的完善过程,谈谈自己的一些心得体会。

关于类的理解:

抛开题目本身不说,在完成这道题之前,应该要对整个项目的构建有比较清晰地思路。首先是新建类,这个的话只要在编译器上新建就好了,建完之后,会自动生成一个头文件(.h)和一个实现文件(.cpp)。在上一次做这个作业,根本不知道这两个文件的各自用处和联系。这一次,在写第一个scan类时,我发现在头文件里面写的都是对于变量或者函数等的声明,如:

scan.h

#pragma once
#include<iostream>
#include<string>
#include<queue>

using namespace std;

class scan
{
public:
    queue<string>tostringqueue(string input);
    queue<string>queue;
private:
    int i;
    string temp;
};

print.h

#pragma once
#include<iostream>
#include<string>
#include<queue>

using namespace std;

class print
{
public:
    void printstring(queue<string>queue);

private:
    int j, l;
};

而在实现文件里写的是对变量的运用和函数实现具体的方法,于是,我就把这两个文件之间的联系这样去理解:头文件和实现文件,就是把一个方法的声明部分和实现部分分开放在两个文件里,并用#include" .h"联系起来,而头文件里的private和public分别对应局部变量和全局变量,这样一类比,在写print类时就很快了。而每个类与主函数之间的联系,就好比是把主函数和自定义函数分开,放在两个文件里,同样用#include" .h"联系起来,如:在main函数里加上

#include<iostream>
#include<string>
#include<queue>
#include"scan.h"
#include"print.h"

使用类的好处是可以分工合作,每个人负责一块内容,之后整合成一个项目,提高效率。

关于队列:

这里就列一些基本的队列知识:

定义 queue 对象:queue<类型>队列名,如:queue q1; queue q2。
queue 的基本操作有:

  • 入队,如:q.push(x),将元素x接到队列的末端。
  • 出队,如:q.pop(),弹出队列的第一个元素,注意,并不会返回被弹出元素的值。
  • 访问队首元素,如:q.front(),即最早被压入队列的元素。
  • 访问队尾元素,如:q.back(),即最后被压入队列的元素。
  • 判断队列为空,如:q.empty(),当队列空时,返回true。
  • 访问队列中的元素个数,如:q.size()。

关于题目:

这道题目对我来说,有四道关卡,第一是类和对象的定义和使用,第二是队列的使用方法,这两道关卡上面已有介绍。后面两道分别是ToStringQueue方法的编写和位数出错的判断。对于前者,这也是最难的坎,可以把整个字符串看成两种元素,数字元素(包括小数点)和非数字元素。总体思路就是扫描整个字符串,把各个元素分别存进一个队列。对于非数字元素,可以直接存入队列,而数字元素(包括小数点)则必须把连在一起的数字看成一个元素,再将整个元素存入不能逐个数字存入。这样的话,可以借助第三方来暂存数字,定义一个string类型的字符串变量temp,利用它把连在一起的数字拼接成一个整体,再存入队列(注意,在存入队列前应该判断temp是否为空,用temp.empty()可以实现;存入后应该把temp初始化,用temp.clear()可以实现。刚开始我就没有这么做,会输出空行和很多重复部分。)代码如下:

scan.cpp

#include "scan.h"

queue<string> scan::tostringqueue(string input)
{
    for (i = 0; i < input.size(); i++)
    {
	    if (input[i] > 47 && input[i] < 58
		    || input[i] == '.')

		    temp += input[i];           //把单个数字拼接成一个

	    else
	    {
		    if (!temp.empty())         //判断是否为空,下同
			    queue.push(temp);  //存入队列,下同
		    temp.clear();              //把temp初始化,下同

		    temp = input[i];
		    if (!temp.empty())
			    queue.push(temp);
		    temp.clear();
	    }
    }

    if (!temp.empty())
	    queue.push(temp);

    return queue;                              //返回这个队列
}

而对于后者,做一个计数器,当位数超标时报错就行了,相对好处理一些。代码如下:

main.cpp

int numlen(string str)
{
	    int i, num = 0, real = 0;

    for (i = 0; i < str.size(); i++)
    {
	    if (str[i] > 47 && str[i] < 58
		    || str[i] == '.')

	    {
		    num++;                              //计数

		    if (str[i] == '.')                 //判断是否有小数点
			    real = 1;

		    if (num > 10 && real == 0)         //无小数点的情况
		    {
			    return 0;
			    break;
		    }
		    else if (num > 11 && real == 1)    //有小数点的情况
		    {
			    return 0;
			    break;
		    }
	    }

	    else
		    num = 0;
    }

    return 1;
}

int main()
{
    queue<string>q;
    string string;

    cin >> string;

    if (numlen(string) == 0)
	    cout << "ERROR" << endl;

    else
    {……}
}

当位数符合要求时,则创建scan和print对象,调用tostringqueue和printstring,代码如下:

main.cpp

int main()
{
    ……

    else
    {
	    scan scan;
	    print print;
	    q = scan.tostringqueue(string);
	    print.printstring(q);
    }

    return 0;
}

至于最后的输出,只要把队列首元素逐个输出并删除就好了,用q.front()和q.pop()可以实现。代码:

print.cpp

#include "print.h"

void print::printstring(queue<string>queue)
{
    l = queue.size();                           //判断队列元素个数  

    for (j = 0; j < l; j++)
    {
	    cout << queue.front() << endl;     //输出队列首元素
	    queue.pop();                       //删除队列首元素
    }
}


原文地址:https://www.cnblogs.com/jiuweilinghu/p/5352721.html