很高兴在我的不懈努力下,终于是把第三次作业完善了,对我来说真的是很不容易,当我完成这道题时,我觉得一切都是值得的。上次做的时候,对于整个类的实现并没有很清晰的认识,在这次完善作业过程中,我通过对比和类比,对于整个类的结构有了比较清楚地认识。接下来我就这次作业的完善过程,谈谈自己的一些心得体会。
关于类的理解:
抛开题目本身不说,在完成这道题之前,应该要对整个项目的构建有比较清晰地思路。首先是新建类,这个的话只要在编译器上新建就好了,建完之后,会自动生成一个头文件(.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(); //删除队列首元素
}
}