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) a
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
/ostream
s. This way you don't have to mess with the rdbuf
s 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)) {
// ...
}