C++计算器项目的初始部分
第三次作业碰到的困难&解决过程
题目链接:http://www.cnblogs.com/fzuoop/p/5187275.html
Github地址:https://github.com/leijing000/object-oriented
乍一看这个题目,完全没看懂,于是我百度了一下类的相关知识,然后我找到了一篇博客(学习C++ -> 类(Classes)的定义与实现),看了之后对类有了初步的了解。
但是仅是对类有了初步的了解,想要自己写代码还是有些困难。于是我又在MOOC上看了关于类的视频课程:http://www.imooc.com/learn/382,
看完之后对类有了进一步了解,并跟着视频中的例子编写代码。
然而再次看题目时还是无从下手,队列感觉是个新的东西,于是我又去百度了一下关于队列的相关概念,以下是关于队列的几个参考网址:
将这些概念搞懂了之后,我于是着手准备编写代码,首先我想到的是要如何将一个四则运算表达式的数字和符号提取出来,并分开输出,想了很久都没有什么思路。于是我便尝试着先将表达式当中的数和字符分开,而先不考虑队列。经过了无数次的错误尝试,我在此列出几个我较为纠结的错误。
错误1:
#include<iostream>
#include<string>
#include"math.h"
using namespace std;
int main()
{
double c[1000];
double num[1000],str[1000];
string input;
string number;
cin>>input;
double m;
int i,j,p,l,d=0,k=0;
l=input.size();
for(i=0;i<l;i++)
{
if(input[i]=='+'||input[i]=='-'||input[i]=='*'||input[i]=='/'
||input[i]=='%'||input[i]=='('||input[i]==')')
{
d++;
number[d]=input[i];
k=i+1;
}
else
{
if(i=l-1)
{
d++;
for(j=i-k;j>=0;j--)
c[j]=pow(10.0,j*1.0);
for(p=k;p<=i;p++)
num[p]=input[p]-'0';
for(j=i-k,p=k;j>=0,p<=i;j--,p++)
m=m+c[j]*num[p];
str[d]=m;
number[d]=str[d]+'0';
}
if(input[i+1]=='+'||input[i+1]=='-'||input[i+1]=='*'||input[i+1]=='/'
||input[i+1]=='%'||input[i+1]=='('||input[i+1]==')')
{
m=0;
d++;
for(j=i-k;j>=0;j--)
c[j]=pow(10.0,j*1.0);
for(p=k;p<=i;p++)
num[p]=input[p]-'0';
for(j=i-k,p=k;j>=0,p<=i;j--,p++)
m=m+c[j]*num[p];
str[d]=m;
number[d]=str[d]+'0';
}
continue;
}
}
for(i=1;i<=d;i++)
cout<<number[i]<<endl;
system("pause");
return 0;
}
我本是想将数字和字符依次存入一个新的字符串中,然后通过循环一个个push到队列中。本来想通过pow函数将几个数字作为一个整体存入一个数组元素之中,并用d来计数,最后依次输出,但是该程序始终无法输出,改了好几次发现都会中断,这让我十分苦恼。后来我想,我把这个符号之间夹杂的数作为一个整体存入一个字符中,然而一个字符型变量只能接受一个字符,我这么做显然是无法运行的,更不用说push到队列中了。所以我换了一个思路。于是我有了第二次尝试
错误2:
#include<iostream>
#include<string>
#include<queue>
using namespace std;
int main()
{
queue<string>q;
string input;
cin>>input;
string s;//定义一个存放数据的空串
int i,j,l;
l=input.size();
for(i=0;i<l;i++)
{
if(input[i]=='+'||input[i]=='-'||input[i]=='*'||input[i]=='/'
||input[i]=='%'||input[i]=='('||input[i]==')')
{
q.push(s);
s.clear();//将数字存入队列
s=s+input[i];
q.push(s);
s.clear();
}
else
{
s=s+input[i];
}
}
if(!s.empty()) q.push(s);
s.clear();
while(!q.empty())
{
cout<<q.front()<<endl;
q.pop();
}
system("pause");
return 0;
}
输出成功地将符号和数分开了,就是有的地方多了空格,我发现若要将数字存入队列,那就应判断当不再为数字时的字符串s是否为空,若为空,则无需再push到队列中,否则将会将一个空串push到队列中,输出时就会产生空格。于是在此处我加上了判断字符串是否为空的语句。检查过后我还发现我没有考虑到当数的长度为10时的情况。于是我用d来计数,当d为10时系统就报错,而且因为小数点是不能算一个位数的,所以我还做了一个判断,当不为小数点时d才加一。最终我得到了我感觉正确的代码,因为没有提交测试,无法保证自己做得全对。
这是我最终的到的关于函数定义部分的代码:
#include"Calculator.h"
queue<string> Scan::ToStringQueue(string input)
{
queue<string>q;
string s;
int i;
int l;
int d = 0;//用来计数,看计数的长度是否超过十位数。
l = input.size();
for (i=0; i<l; i++)
{
if (input[i] == '+' || input[i] == '-' || input[i] == '*' || input[i] == '/'
|| input[i] == '%' || input[i] == '(' || input[i] == ')')
{ d = 0;//当数的长度不足10位时,停止计数,开始准备对下一个数重新计数。
//要判断字符串s是否为空,若为空,就不用存入队列,否则每次循环都会存入一个空字符串,这会导致输出时会有一行为空。此操作是将数字存入队列中。
if (!s.empty())
{
q.push(s);
s.clear();
}
s = s + input[i];
q.push(s);
s.clear();
}
else
{
s = s + input[i];
if (input[i]!='.')
{
d++;
}
if (d == 10)
{
break;
}
}
}
if(d == 10)
{
cout << "ERROR" << endl;//数字长度超过十位时系统报错。
}
else
{
//当最后面为数字时,剩余的数无法再通过if条件句push到队列中,所以这里还要判断一下s是否为空,并push到队列中。
if (!s.empty())
{
q.push(s);
s.clear();
}
}
return q;
}
void Print::OutstringQueue(queue<string> q)
{
while (!q.empty())
{
cout << q.front() << endl;
q.pop();
}
}
以下是这个项目的头文件和程序实现的代码:
#include"Calculator.h"
int main()
{
queue<string>q;
string input;
cin >> input;
Scan Input;
Print Output;
q = Input.ToStringQueue(input);
Output.OutstringQueue(q);
system("pause");
return 0;
}
#include<iostream>
#include<string>
#include<queue>
using namespace std;
class Scan
{
public:
queue<string> ToStringQueue(string input);
};
class Print
{
public:
void OutstringQueue(queue<string> q);
};
总结
这次作业我花了很长的时间来完成,但在这个过程中我也学到了很多,知道了什么是队列,对C++又有了更深一步的了解。在一次次的错误当中又学到了许多知识点,过程漫长,但也收获颇多。在写这篇博文时感觉对markdown的写法又有些生疏了,正好又重温了。而且我还通过此次学习稍微规范了自己的代码。