zoukankan      html  css  js  c++  java
  • 第五次作业(计算器第三步之文件输入输出)

    题目要求:

    http://www.cnblogs.com/fzuoop/p/5451293.html

    下面按照解决的过程一一记录说明

    1.文件输入输出

    这个东西在谭浩强的书上也有,所以我看了点书之后先开始了粗糙的尝试,代码如下:

    #include<fstream>
    #include<iostream>
    #include<string>
    using namespace std;
    int main()
    {
        string str;
        //定义输入文件流对象,以输入方式打开磁盘文件text.txt
        ifstream infile("D:	ext.txt",ios::in);
        //打开失败的报错
        if(!infile)
        {
            cerr<<"open error!"<<endl;
            exit(1);
        }
        //从输入文件中获取数据,并输到屏幕上
        while(getline(infile,str,'
    '))
        {
            getline(infile,str,'
    ');
            cout<<str<<endl;
        }
        //将输入文件流所关联的磁盘文件关闭
        infile.close();
        return 0;
    }
    

    但是运行结果一直是打开失败,百度了一下之后,把路径名中的斜杠换成了双写,然后运行结果是:


    但是我的数据是:

    又去百度了解之后,把输出的代码改成了这样:

    while(!infile.eof())
    {
    	getline(infile,str,'
    ');
    	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,'
    ');
            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,'
    ');
                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,'
    ');
                //调用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:感觉又是一次要改很久的作业。。。

  • 相关阅读:
    python 操作ie 登陆土豆再退出
    python之sqlite3使用详解(转)
    python 获取当前目录下文件(转)
    python中使用time模块计算代码执行效率的精度测试(转)
    pythonhttplib模块使用(转)
    python技巧31[python中使用enum](转)
    python怎样压缩和解压缩ZIP文件(转)
    httplib2python下的http请求终结者(转)
    Python:使用ctypes库调用外部DLL(转)
    整理了下控制ie的代码(转)
  • 原文地址:https://www.cnblogs.com/mingyueanyao/p/5474814.html
Copyright © 2011-2022 走看看