Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
671 views
in Technique[技术] by (71.8m points)

c++ - read and write from files or from cin and cout

my code work good when the argc is 1 but when I try to read and write from files (when argc is 3) the program not working well. Gcalc get the ostream (output file or cout) and current line in input file or cin and decode the string to command on gcalc data.

#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;
  }
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
  • Check that opening the files was done successfully.
  • Check that the istream you read from doesn't have the failbit set after you've read from it. Since an istream in a boolean context checks badbit and failbit and that std::getline returns the same istream you gave it, replace your while (cin.good()) with:
    while(getline(cin, current_line)) {
        // ... only entered if badbit and failbit are false ...
    }
    

That said, it's usually better to create a separate function for reading/writing to generic istream/ostreams. This way you don't have to mess with the rdbufs of cin and cout.

#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);
    }
}

If you want to give the user a prompt when the program is running in interactive mode, you could add a function that prints the prompt and then calls std::getline. You can combine this inside the while loop, but it looks messy, so I would suggest something like this:

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)) {
        // ...
    }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...