《面向对象程序设计》第三次作业(读入运算表达式逐个输出)
在系统性的大致学习了c++视频课程后,可以说对面向对象思维有了一定的认识。感觉c++对比c语言来说,不管是可读性还是写程序的逻辑性都提升了很多。看过有人把面向对象和面向过程的思维差别描述为盖房子,面向对象思维会先从房子的结构入手,再想具体实现怎么砌墙怎么搭柱子;而面向过程会先从砌墙撘柱子起,然后构建房子结构。从人的思维角度来说,也应该是面向对象的思维更容易接受。更重要的是,思维的转变很大程度上提高了代码的灵活性,把实现功能的代码写在各个类中,随时方便修改或引入某个类的功能而不必考虑其他代码受其影响,单凭这一点就能秒杀面向过程的程序设计思维,也更能理解为什么极少人会选择用c语言写项目了...
话不多说,先上代码:
主要代码:
Main.cpp
if(check(input))
{
cout<<"Error!"<<endl;
return 0; //数字位数大于10时报错
}
else //数字位数不大于10时处理字符串
{
Scan scan; //创建Scan对象
Print print; //创建Print对象
queue<string> q = scan.ToStringQueue(input); //调用ToStringQueue()方法获取目标队列
print.PrintQueue(q); //调用PrintQueue()方法输出队列各元素
return 0;
}
bool check(string s)
{
int num = 0;
bool flag = false;
for(int i=0;i<s.size();i++)
{
if(!isdigit(s[i])&&s[i]!='.') //若为不为小数点的非数字字符
{
num = 0;
}
else if(isdigit(s[i])||'.') //若为数字字符或小数点
{
num++;
if(s[i] == '.')
{
flag = true;
}
if(num>11&&flag) //有小数位
{
return true;
}
else if(num>10&&!flag) //无小数位
{
return true;
}
}
}
return false;
}
Scan.cpp
queue<string> Scan::ToStringQueue(string input)
{
m_sInput = input;
for(int i=0;i<m_sInput.size();i++) //遍历input的每个字符
{
if(!isdigit(m_sInput[i])&&m_sInput[i]!='.') //若为不为小数点的非数字字符
{
if(!temp.empty())
StrQueue.push(temp); //暂存字符串非空则入队
temp.clear(); //入队后清除暂存字符串
temp = m_sInput[i]; //当前符号入队
if(!temp.empty())
StrQueue.push(temp);
temp.clear();
}
else if(isdigit(m_sInput[i])||'.') //若为数字字符或小数点
{
temp += m_sInput[i]; //当前数字或小数点跟于暂存字符串末
continue;
}
}
if(!temp.empty())
{
StrQueue.push(temp); //遍历完成后暂存字符串非空则入队
}
return StrQueue; //返回此队列
}
Print.cpp
void Print::PrintQueue(queue<string> theQueue)
{
queue<string>::iterator itor = theQueue.front();
for(;itor!=theQueue.end();itor++)
{
cout << *itor <<endl;
}
*/
int len = theQueue.size(); //记录弹出元素前的队列长度
for(int i = 0;i < len;i++) //输出队首元素后弹出 直到输出len个元素
{
cout << theQueue.front() <<endl;
theQueue.pop();
}
数据测试截图:
以上代码已按要求上传github,网址点这里。
觉得在代码注释中已经包含了应有的思路解释,这里就不赘述了。
【在写代码中遇到的问题:】
- 数组越界。一开始在Scan类中判断当前读到的字符是数字小数点还是普通字符后考虑判断下一位位字符,运行起来没有数字输出,忽略了数组越界问题,数组越界貌似是不会报错的...后来直接在判断当前字符之后对已保存在temp中的字符串做入队处理就可以了。
- 运行时输出迷之空行。在小伙伴的提醒下发现Scan当前后为两个符号位时会把存有空字符串的temp存入队列...于是在入队前做了是否为空的判断。
- 没有考虑输入无意义字符如&、¥...的处理方法(比如在入队前判断是否是正常的运算符),后面想想如果做可视化的话用按钮键入就不会发生这种情况了就没有做处理了。
- 输出队列发现队列没有迭代器。本来试图用iterator输出队列,发现原来queue是没有迭代器的...只好输出一遍逐个pop掉变成空队列。要怎么输出完还留着原来的队列呢?查了半天好像也没有什么特别好的办法,无过于拷贝一下队列,在新的队列中输出然后pop掉元素。不过抹去队列元素对本程序并没啥影响,不去管它。
- 在Print中没有存输出前的队列长度。开始没检查Print类,一直奇怪怎么只能正常输出一部分元素,debug发现输出的时候还没有执行到队列长度就退出了。想起来抹去元素后size自然就减少了,所以只输出了一半元素...于是设个变量存弹出元素前的队列长度,i<这个长度。
顺带码一下期间get到的几个比较好的参考资料
C++ STL--stack/queue 的使用方法
标准C++中的string类的用法总结
c++字符串详解(一些常用函数)
C++字符串长度 (其中对sizeof()/strlen()/GetLength()/size()/length()做了详解)
c++ Reference