第五次作业(计算器第三步之文件输入输出)
2016-05-09 17:42
375 查看
题目要求:
下面按照解决的过程一一记录说明
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; }
但是运行结果一直是打开失败,百度了一下之后,把路径名中的斜杠换成了双写,然后运行结果是:
![](http://images2015.cnblogs.com/blog/886021/201605/886021-20160509173938015-560809986.jpg)
但是我的数据是:
![](http://images2015.cnblogs.com/blog/886021/201605/886021-20160509174001265-899083264.jpg)
又去百度了解之后,把输出的代码改成了这样:
while(!infile.eof()) { getline(infile,str,'\n'); cout<<str<<endl; }
然后输出的结果终于对了:
![](http://images2015.cnblogs.com/blog/886021/201605/886021-20160509174017062-864312967.jpg)
然后我又定义了一个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; }
运行结果:
![](http://images2015.cnblogs.com/blog/886021/201605/886021-20160509174048062-1210094996.jpg)
输出文件结果:
![](http://images2015.cnblogs.com/blog/886021/201605/886021-20160509174117280-1069537601.jpg)
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; }
不知道为什么会停止运行。。。不过检查输出的文件里面是确实有正确的输出的:
![](http://images2015.cnblogs.com/blog/886021/201605/886021-20160510004023812-924854186.jpg)
![](http://images2015.cnblogs.com/blog/886021/201605/886021-20160510004038609-1767138283.jpg)
后来发现好像只要输出结果就好,不用把表达式也输到文件里面。。。
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.框架图
其实不懂框架图是什么意思,大概做了一下:
![](http://images2015.cnblogs.com/blog/886021/201605/886021-20160510174901452-1123800886.jpg)
ps:感觉又是一次要改很久的作业。。。
相关文章推荐
- Linux中丢失grub文件怎么办?
- length()与lengthb()
- 求因子数的和问题
- Cocos2dx_3.x新的渲染流程
- BaseAdapter 抽取
- springMVC加载远程freemarker模板文件
- HTML DOCTYPE文档类型举例说明
- 在iis中设置文件下载而不是在浏览器上打开
- 去除android手机滚动条
- android notification完全解析【转】
- 集合框架--Map集合之LinkedHashMap
- 在配置文件(manifest file)中声明activity的一点理解
- c++中反斜杠(\)的不常用的用法
- 【转】NodeJS on Nginx: 使用nginx反向代理处理静态页面
- Android-GestureDetector手势滑动
- hive union 的问题
- A - Rooks
- [Learning OpenCV](1) OPenCV的结构和内容
- POJ_3281_Dining && NYOJ _326_Dining
- Gradle learn