第五次作业(计算器第三步之文件输入输出)
题目要求:
下面按照解决的过程一一记录说明
1.文件输入输出
这个东西在谭浩强的书上也有,所以我看了点书之后先开始了粗糙的尝试,代码如下:
#include<fstream>
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str;
//定义输入文件流对象,以输入方式打开磁盘文件text.txt
ifstream infile("D:\text.txt",ios::in);
//打开失败的报错
if(!infile)
{
cerr<<"open error!"<<endl;
exit(1);
}
//从输入文件中获取数据,并输到屏幕上
while(getline(infile,str,'\n'))
{
getline(infile,str,'\n');
cout<<str<<endl;
}
//将输入文件流所关联的磁盘文件关闭
infile.close();
return 0;
}
但是运行结果一直是打开失败,百度了一下之后,把路径名中的斜杠换成了双写,然后运行结果是:
但是我的数据是:又去百度了解之后,把输出的代码改成了这样:
while(!infile.eof())
{
getline(infile,str,'\n');
cout<<str<<endl;
}
然后输出的结果终于对了:
然后我又定义了一个string类型来接收输入的路径名,但是编译就过不去,是在别人的博客里看到了c_str()函数(通过string类的c_str()函数能够把string对象转换成c中的字符串的样式),然后就可以了。下面是尝试的最后代码:
#include<fstream>
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str,ifile,ofile;
//输入输入文件路径和输出文件路径
cin>>ifile>>ofile;
//定义输入文件流对象,以输入方式打开磁盘文件ifile
ifstream infile(ifile.c_str(),ios::in);
//打开失败的报错
if(!infile)
{
cerr<<" infile open error!"<<endl;
exit(1);
}
//定义输出文件流对象,以输入方式打开磁盘文件ofile
ofstream outfile(ofile.c_str(),ios::out);
//打开失败的报错
if(!outfile)
{
cerr<<"outfile open error!"<<endl;
exit(1);
}
//从输入文件中获取数据,传到输出文件里并输到屏幕上
while(!infile.eof())
{
getline(infile,str,'\n');
outfile<<str<<endl;
cout<<str<<endl;
}
//将输入文件流所关联的磁盘文件关闭
infile.close();
//将输出文件流所关联的磁盘文件关闭
outfile.close();
return 0;
}
运行结果:
输出文件结果:
2.代码修改
1.现在的表达式包括等号,于是在Scan类里做了修改,不会把最后一个等号输进去,这样子其他的按照原来的就好,具体代码如下:
Scan.cpp
#include"Scan.h"
#include<stdlib.h>
#include<iostream>
#include<string>
#include<queue>
using namespace std;
queue<string> ToStringQueue(string input)
{
//第二次题目要求数位不超过十位(包括小数位)
//这是用来记录数位的变量
int cnt=0;
queue<string>q;
string str;
//遍历传进来的字符串
for(int i=0; i<input.size(); i++)
{
//遍历到运算符或是符号
//注:多了一个等号的判断
if(input[i] == '+'||input[i] == '-'||input[i] == '*'||input[i] == '/'||input[i] == '('||input[i] == ')'||input[i] =='=')
{
//把碰到运算符之前接起来的数字符压入队列中
if(!str.empty())
{
q.push(str);
}
//特判第一个数字是负数的情况
//不入栈,准备与数字符接在一起
if(input[i]=='-'&&i==0)
{
str=str+input[i];
}
//算式中间出现合法的负数的情况
//不入栈,准备与数字符·接在一起
else if(input[i]=='-'&&q.back()=="(")
{
str=str+input[i];
}
//其他运算符直接入栈,并把中间变量置空
//注:不存入等号
else if(input[i]!='=')
{
cnt=0;
str=input[i];
q.push(str);
str.clear();
}
//注:等号不做处理
else
{
break;
}
}
//遍历到数字符
else
{
//把相邻数字符接起来
str=str+input[i];
//记录位数
if(input[i]!='.')
{
cnt++;
}
//位数报错
if(cnt==11)
{
cout<<"wrong input"<<endl;
system("pause");
}
//最后是数字符的话,直接入栈
//原来都是碰到运算符才入栈
if(i==input.size()-1)
{
q.push(str);
}
}
}
return q;
}
2.主要是多了一个文件输入输出的情况,然后把主函数改成了这样,然后Calculation类的成员函数也改成有返回值的:
Main.cpp
#include<stdlib.h>
#include<iostream>
#include<fstream>
#include<string>
#include<string.h>
#include<queue>
#include"Scan.h"
#include"Print.h"
#include"Calculation.h"
using namespace std;
int main(int argc, char* argv[])
{
Scan scan;
Print print;
Calculation calculation;
string input;
double result;
queue<string>q;
//x为“-a”,y为表达式,则在屏幕输出表达式
if(strcmp(argv[1],"-a")==0)
{
input=argv[argc-1];
cout<<input<<" ";
}
//x为“-f”,y为输入文件路径,z为输出文件路径
if(strcmp(argv[1],"-f")==0)
{
string ifile=argv[2];
string ofile=argv[3];
//定义输入文件流对象,以输入方式打开磁盘文件ifile
ifstream infile(ifile.c_str(),ios::in);
//打开失败的报错
if(!infile)
{
cerr<<" infile open error!"<<endl;
exit(1);
}
//定义输出文件流对象,以输出方式打开磁盘文件ofile
ofstream outfile(ofile.c_str(),ios::out);
//打开失败的报错
if(!outfile)
{
cerr<<"outfile open error!"<<endl;
exit(1);
}
//从输入文件里获取input的值,并把计算结果传到输出文件
while(!infile.eof())
{
getline(infile,input,'\n');
q=scan.ToStringQueue(input);
result=calculation.getStringQueue(q);
outfile<<input<<" "<<result<<endl;
}
//将输入文件流所关联的磁盘文件关闭
infile.close();
//将输出文件流所关联的磁盘文件关闭
outfile.close();
}
//x不为“-f”时在屏幕输出
else
{
q=scan.ToStringQueue(input);
result=calculation.getStringQueue(q);
cout<<result<<endl;
}
system("pause");
return 0;
}
不知道为什么会停止运行。。。不过检查输出的文件里面是确实有正确的输出的:
后来发现好像只要输出结果就好,不用把表达式也输到文件里面。。。3.把所有关于输出的代码都放到Print类里。当初看到题目的时候就觉得这个最麻烦了,这个不做的话,感觉后面的框架图也没办法做,然后貌似代码要改很多。。。
这大概就是最终代码了:Main.cpp
#include<stdlib.h>
#include<iostream>
#include<fstream>
#include<string>
#include<string.h>
#include<queue>
#include"Scan.h"
#include"Print.h"
#include"Calculation.h"
using namespace std;
int main(int argc, char* argv[])
{
Scan scan;
Print print;
Calculation calculation;
string input;
double result;
queue<string>q;
//要求输出表达式的操作
if(strcmp(argv[1],"-a")==0)
{
//从命令行读入表达式
input=argv[argc-1];
//调用Scan类,获得一个存表达式的队列
q=scan.ToStringQueue(input);
//调用Calculation类,获得计算结果
result=calculation.getStringQueue(q);
//调用Print类,按照要求输出
print.putout(result,input,"0");
}
//要求从命令行获得输入文件和输出文件路径的操作
else if(strcmp(argv[1],"-f")==0)
{
//获取命令行的输入文件路径
string ifile=argv[2];
//定义输入文件流对象,以输入方式打开输入文件
ifstream infile(ifile.c_str(),ios::in);
//打开错误的报错
if(!infile)
{
cerr<<" infile open error!"<<endl;
exit(1);
}
//一直读到输入文件末尾
while(!infile.eof())
{
//从输入文件获取表达式
getline(infile,input,'\n');
//调用Scan类,获得一个存表达式的队列
q=scan.ToStringQueue(input);
//调用Calculation类,获得计算结果
result=calculation.getStringQueue(q);
//调用Print类,按照要求输出
print.putout(result,input,argv[3]);
}
//将输入文件流所关联的磁盘文件关闭
infile.close();
}
//只要求简单输出结果的操作
else
{
//从命令行读入表达式
input=argv[argc-1];
//调用Scan类,获得一个存表达式的队列
q=scan.ToStringQueue(input);
//调用Calculation类,获得计算结果
result=calculation.getStringQueue(q);
//调用Print类,按照要求输出
print.putout(result,"0","0");
}
system("pause");
return 0;
}
Print.cpp
#include"Print.h"
#include<stdlib.h>
#include<iostream>
#include<fstream>
#include<string>
#include<queue>
using namespace std;
void Print::putout(double res,string in,string out)
{
//定义输出文件流对象,以输出方式打开输出文件
string ofile=out;
//只是简单输出结果的操作
if(in=="0")
{
cout<<res<<endl;
}
//输出到输出文件的操作
else if(out!="0")
{
//定义输出文件流对象,以输出方式打开磁盘文件ofile
ofstream outfile(ofile.c_str(),ios::app);
//打开错误的报错
if(!outfile)
{
cerr<<"outfile open error!"<<endl;
exit(1);
}
//将结果输到输出文件里
outfile<<res<<endl;
//将输出文件流所关联的磁盘文件关闭
outfile.close();
}
//要求输出表达式和结果的操作
else
{
cout<<in<<" "<<res<<endl;
}
}
x是“-f”时还是会迷之崩溃,但是输出文件里确实有正确的输出。还有一件事是把输出文件的打开方式改成了ios::app,写入的数据接在原文件末尾(但是多输几次的话会重复感觉也不好),而ios::out的话会把原数据清空,我上面的代码最后会只有一个输出 。直接上GITHUB链接
3.框架图
其实不懂框架图是什么意思,大概做了一下:
ps:感觉又是一次要改很久的作业。。。