第五次作业(计算器第三步)

MyGitHub


输入方式

所有方式都是通过命令行传递,即在第四次的基础上新增:

带等号的等式

需要在scan中新增对等号的判断,即遇见等号跳出循环即可

    if (input[i] == '=')
    {
       break;
    }

自定义文件名文件流输入输出(FILE*stream)

判断当X:argv[1]=="-f"时,则Y为输入文件路径,z为输出文件路径(默认路径存在),通过资料查阅得知,常用的文件输入输出方式有:

  • fstream
    fstream //输入文件流
    ofstream //输出文件流
    需要头文件:fstream
    由于教程太过详细,便不在这里一一唠叨,就写写我学到的。

    1. 文件打开方式
       1. ifstream(filename); //只读,此时默认打开方式为ios::in,若文件不存在则创建文件;注意文件路径斜杠双写,例:"E://in.txt")
      2. 使用成员函数open
      fstream f;
      f.open(filename,ios::out||ios::in); //读写的方式打开文件
      以上两种打开方式的区别主要在于:如果你想用一个句柄打开多个文件或不马上指定文件路径(如本次作业情况),可以选择f.open();

    2. 检查文件是否成功打开
      可以用一个bool函数判断
      bool F{if(f)...}

    3. 读写操作
      f>>x; //读取数据
      f<<x; //写入数据

    4. 关闭文件
      f.close();

    5. 根据以上所学知识,一个简单的测试代码

      void main()
      {
      int i;
      fstream f,fs;
      string filename_out;
      cin >> filename_out; //输出文件名自定义
      f.open("D://test.txt",ios::in); //打开输入文件
      fs.open(filename_out.c_str(),ios::out); //创建输出文件
      while (!f.eof()) //处理至文件结束
      {
      f >> i;
      fs << i;
      }

      f.close(); //关闭文件
      fs.close();
      }

  • freopen
    函数声明:FILE *freopen( const char *path, const char *mode, FILE *stream );
    需要头文件:stdio.h

    1. 文件打开方式:
      FILE* stream;
      freopen("in.txt","r",stdin); //输入重定向,此时输入的数据从in.txt文件读取,并且in.txt文件在工程//Debug文件夹下和.exe处于同一个位置。
      //"r"是文件打开模式,*mode对应下 r-只读,w-写
      //stdin标准输入流,默认键盘;stdout标准输出流,默认屏幕

    2. 输入输出
      保持原函数不变

    3. 关闭文件
      fclose(stdin);
      fclose(stdout);

    4. 测试代码

        int main()
       {
         int a, b;
         char s[20];
         void cal(int c, int d);
         FILE *stream;
         cin >> s;
         freopen_s(&stream,s,"r",stdin);
         freopen_s(&stream,"output.txt", "w", stdout);
         while (cin >> a >> b)
         cout << a + b << endl;
      
         fclose(stdin);//关闭文件
         fclose(stdout);//关闭文件
         return 0;
       }
      
  • 方法比较:
    以上两种方式目前在我看来似乎并没有很大的区别,但是freopen的一大优势是对原有的代码完全不用修改~~十分方便,只要加上几行重定向语句就好了!!
    所以我选用freopen,但是在vs_2015实测中,如果按照大多数教程的重定向语句写成这样freopen(s,"r",stdin);,vs会提示改成freopen_s,然后会告诉你不接受3个参数...一开始改了很久,然后看了一下vs提供的解决方案,总算是明白了freopen_s的函数声明为 freopen_s(FILE**_stream,char const_FileName,char const_Mode,FILE* _OldStream),说白了应写成 freopen_s(&stream,filename,"r",stdin); 格式即可。
    值得注意的是,在fstream中,输入文件不存在可自动创建,而用freopen需要指定已存在的文件。

  • 自定义文件名:
    本题文件路径由用户端的参数控制由于函数freopen的filename只接受char类型的参数,所以我选择用string接受用户输入,然后借用c_str()函数转换

              FILE*stream;
              string filename;   
              cin >> filename;                                      
              freopen_s(&stream,filename.c_str(),"r",stdin);  
    
  • 我的相关代码:

        if (argv[1] == "-f")
      {
    
      	string filename_in, filename_out;
      	filename_in = argv[2];
      	filename_out = argv[3];
    
      	FILE* stream;
    
      	freopen_s(&stream, filename_in.c_str(), "r", stdin);  //重定向
      	freopen_s(&stream, filename_out.c_str(), "w", stdout);
    
      	while (cin >> s1)      //输入到文件结束
      	{
      		calcu(s1);      //调用函数队式子进行计算并输出
      	}
    
      	fclose(stdin);          //关闭文件
      	fclose(stdout);
      }
    

命令行输入:

文件输入:

输出文件:

  • 所有输出代码都在printf函数内:
    之前确实偷懒了一下下部分输出直接在main函数进行,于是printf函数变得鸡肋~于是在printf.cpp新建了<报错><结果输出><表达式输出>函数

描述框架图

注:以下所有调用皆在main.cpp进行,箭头只是判断关系。

参考资料:


更新16/5/23

  • 将freopen换成更高效率的fstream,并分别在scan和printf中执行输入输出文件流。输出文件流用到了“ios;;app”。
  • 合并calculation和result类,减少函数调用次数,提高效率。
  • 删去多余的代码注释和旧版本。
  • 各个类函数之间的调用仍然过于冗杂,还在继续优化修改。
原文地址:https://www.cnblogs.com/mingtime/p/5470114.html