【问题标题】:read and write from files or from cin and cout从文件或 cin 和 cout 读取和写入
【发布时间】:2020-08-10 13:30:11
【问题描述】:

我的代码在 argc 为 1 时运行良好,但当我尝试从文件读取和写入时(当 argc 为 3 时) 该程序运行不正常。 Gcalc 获取 ostream(输出文件或 cout)和输入文件中的当前行 或 cin 并将字符串解码为 gcalc 数据上的命令。

#include <ostream>
#include <fstream>
#include <string>
#include <iostream>

#include "Gcalc.h"

using namespace std;

int main(int argc, char* argv[]) {
    Gcalc gcalc;
    string current_line;
    ifstream input;
    ofstream output;
    if (argc != 1 && argc != 3) {
        return 0;
    }
    if (argc == 3) {
       input = ifstream(argv[1]);
       cin.rdbuf(input.rdbuf());
       output = ofstream(argv[2]);
       cout.rdbuf(output.rdbuf());
   }
   while (cin.good()) {
       if (argc == 1) {
            cout << "Gcalc> ";
       }
       getline(cin, current_line);
       try {
           gcalc.implementCommand(cout, current_line);
       }
       catch (Quit_Program& error) {
             break;
       }
       catch (std::bad_alloc& error) {
             std::cerr << "Error: fatal error - bad allocation" << endl;
             break;
       }
       catch (Exception& error) {
            cout << error.what() << endl;
       } 
   }
   return 0;
  }

【问题讨论】:

  • “程序运行不正常”不是一个好的错误描述。我确信程序正在这样做,正如代码所说的那样。
  • OT:您可能可以像这样将getline(cin, current_line) 移动到while 的条件中:while (getline(cin, current_line)) { ...
  • 我的建议是将所有代码放在 while() 循环中的函数中,该函数具有 1 个参数,该参数是通过引用传递的 istream。这样您就可以传递cin 或打开的文件。
  • 你为什么要这样做 argc != 1 ???
  • @ΦXocę웃Пepeúpaツ 如果提供的参数数量不正确,则退出程序。

标签: c++


【解决方案1】:
  • 检查文件打开是否成功。
  • 检查您从中读取的istream 是否在您读取它之后设置了failbit。由于布尔上下文中的istream 检查badbitfailbit 并且std::getline 返回相同的istream,因此将while (cin.good()) 替换为:
    while(getline(cin, current_line)) {
        // ... only entered if badbit and failbit are false ...
    }
    

也就是说,通常最好创建一个单独的函数来读取/写入通用istream/ostreams。这样你就不用搞乱cincoutrdbufs了。

#include <fstream>
#include <iostream>
#include <string>

#include "Gcalc.h"

void do_stuff(std::istream& is, std::ostream& os) {
    Gcalc gcalc;
    std::string current_line;

    while(getline(is, current_line)) {
        try {
            gcalc.implementCommand(os, current_line);
        } catch(Quit_Program& error) {
            break;
        } catch(const std::bad_alloc& error) {
            std::cerr << "Error: fatal error - " << error.what() << std::endl;
            break;
        } catch(Exception& error) {
            std::cout << error.what() << std::endl;
            // or, if you really want it:
            // os << error.what() << std::endl;
        }
    }
}

int main(int argc, char* argv[]) {
    if(argc == 1) {
        do_stuff(std::cin, std::cout);
    } else if(argc == 3) {
        std::ifstream input(argv[1]);
        std::ofstream output(argv[2]);
        if(input && output) do_stuff(input, output);
    }
}

如果您想在程序以交互模式运行时给用户一个提示,您可以添加一个打印提示然后调用std::getline 的函数。您可以在 while 循环中组合它,但它看起来很乱,所以我建议这样:

std::istream& prompt(std::istream& is, std::string& line) {
    if(&is == &std::cin) std::cout << "Gcalc> ";
    return std::getline(is, line);
}

// ...

    while(prompt(is, current_line)) {
        // ...
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-08
    • 1970-01-01
    • 1970-01-01
    • 2018-12-15
    • 1970-01-01
    相关资源
    最近更新 更多