emdez
emdez

Reputation: 25

C++ Input/Output stream

I have a problem with I/O streams in C++. I have to write a program which reads data from a file and writes to another file. The command in CMD should be like:

program < file1 > file2

The names of the files should be provided by the user (could be random).

I've written some code, but it's not correct. I don't know how to redirect the stream to a file using the command > file2.

What can I change in my code to make it work? Can somebody help me?

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

int main() {
    std::string input_line;
    while (std::getline(std::cin, input_line)) {
        std::ofstream output_file("file2.txt", std::ios::app);
        if (!output_file.is_open()) {
            std::cerr << "Error" << std::endl;
            return 1;
        }

        output_file << input_line << std::endl;
        output_file.close();
    }

    return 0;
}

Upvotes: 1

Views: 358

Answers (3)

Pepijn Kramer
Pepijn Kramer

Reputation: 13076

Files are just streams, so implement a copy function in terms of std::istream& and std::ostream&. This allows you to avoid file (location) problems during testing, use a std::istringstream for testing (instead of std::ifstream). And similar instead of std::ofstream you can use std::cout as output.

Also, learn to write functions with readable names.

It will become something like this:

#include <sstream>

std::istringstream input_file
{
   "Line 1 : One\n"
   "Line 2 : Two\n"
   "Line 3 : Three\n"
   "Line 4 : Four\n"
};    

void copy(std::istream& is, std::ostream& os)
{
    std::string line;
    while (std::getline(is, line)) os << line << "\n";
}

int main()
{
    copy(input_file, std::cout);
}

Upvotes: 0

lastchance
lastchance

Reputation: 6685

If you want to dictate the filenames from the command line then you don't really need the '<' and '>' redirectors. You could just state the names of the files and use the int main( int argc, char * argv[] ) form of program.

Thus:

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main( int argc, char * argv[] )
{
   if ( argc != 3 )
   {
      cerr << "Correct usage is myprog.exe infile outfile";
      return 1;
   }

   ifstream in( argv[1] );
   if ( !in )
   {
      cerr << "Input file not found";
      return 1;
   }

   ofstream out( argv[2] );
   for ( string line; getline( in, line); ) out << line << '\n';
}

Upvotes: 0

Loki Astari
Loki Astari

Reputation: 264631

I have a problem with I/O streams in c++.

OK.

Command in CMD should be like: "program < file1 > file2"

This implies you are using the shell to do the work. Here. The < and > are shell "operators" to redirect files to standard in and standard out of the program. This means your program should read from std::cin and write to std::cout.

You assume the output file is "file2.txt"!

std::ofstream output_file("file2.txt", std::ios::app);

You are always appending to it. If the file already exists, this may not be what you want, as it will add the new content onto any old content. I would probably change that (if I was using files). But the simpler solution is to use std::cout (as indicated above).

I am assuming you are doing this as part of an exercise, so going through the steps.

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

int main() 
{
    std::string input_line;
    while (std::getline(std::cin, input_line)) {


        // This should open file is inside the loop. 
        // You should probably move it outside the loop.
        // A side effects of this is that you don't need to append
        // so you will destroy the old content and get rid of it.
        std::ofstream output_file("file2.txt", std::ios::app);

        if (!output_file.is_open()) {
            std::cerr << "Error" << std::endl;
            return 1;
        }

        // probably don't want to use `std::endl` here.
        // This forces a flush from the internal buffer to the hardware.
        // You probably just want to use `"\n"` here.
        output_file << input_line << std::endl;

        // You are closing the output file after writting one line to it.
        // May be more effecient to only close the file after writting
        // all the lines to the file.
        output_file.close();
     }

    return 0;
}

If I was writing this for a class that was trying to understand streams. This is how I would re-write more like this:

#include <iostream>
#include <string>

int main() 
{
    std::string input_line;

    // Use a while loop to read a line from the input.
    while (std::getline(std::cin, input_line)) {

        // If the read worked the we write line back to the
        // output.
        std::cout << input_line << "\n";
    }

    // When the read (std::getline()) fails the loop
    // will not be entered. So you can stop the loop
    // and end up here.

    // Optional return at the end of main.
    return 0;
}

Note: This is not quite perfect as the last line may not include a new line character, but the code above always add a newline to every line. I leave it as an exercise for you to solve this last simple issue.

Upvotes: 3

Related Questions