1
#include<iostream>
#include<fstream>
#include<string>
#include<vector>

using namespace std;

int main(){

    ofstream out;
    ifstream in;

    out.open("The Necessary Death of Charlie Countryman2.srt");
        if (out.fail()) {
            perror("The Necessary Death of Charlie Countryman2.srt");
        }

    in.open("The Necessary Death of Charlie Countryman.srt");
        if (in.fail()) {
            perror("The Necessary Death of Charlie Countryman.srt");
        }

    vector<string> input;
    string inc;

    while (getline(in, inc)) {
        input.push_back(inc);
    }

    for (int k = 0; k < input.size(); k++) {
        out << input[k] << endl;
    }    
    return 0;
}

When I read from somefile.txt using ifstream in and write into anotherfile.txt using ofstream in, everything works fine, but suppose I comment out out.open("anotherfile.txt") and execute the code, there is no error and when I open anotherfile.txt it is empty.

My question is during

for (int k = 0; k < input.size(); k++) {
            out << input[k] << endl;
        }

what happens?

Where or to what is input[k] sent to? If it was cout it goes to command prompt and if out.open("anotherfile.txt") was not commented then it goes to anotherfile.txt.

nSv23
  • 429
  • 6
  • 19
  • 1
    seems like it is sent to a buffer which is never used. But I couldn't find more info about it – I3ck Dec 29 '15 at 19:12
  • 1
    When an output file isn't being opened, the text is simply loaded in a buffer and destroyed therein when the program terminates. Unless you open a file for reading, text you attempt to send to the output file will be relayed back to the stack. – Poriferous Dec 29 '15 at 19:17
  • @I3ck and @ Poriferous thank you both, this is what I wanted to know where does my `input[k]` is sent to. – nSv23 Dec 29 '15 at 19:28

4 Answers4

2

Every << operation fails, and that's it (that's (1)all that happens).


(1) A stream can be set in a mode where it throws exceptions on failures, but that's not the default. By default failures are just silently ignored. Except that the fail state bits are set, which you can check with either fail() or via conversion to bool.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • I dont think `getline` fails, because `getline(in, inc)` reads from `in` which is `ifstream` object it has nothing to do with `out` which is `ofstream` object. – nSv23 Dec 29 '15 at 19:10
  • @nSv23: Oh, right you are: it's the other stream that's outcommented. Okay, fixing. – Cheers and hth. - Alf Dec 29 '15 at 19:11
  • yes `input` is a `std::vector`, but this is pretty much the entire code, just read from `in` and write to `out`. – nSv23 Dec 29 '15 at 19:15
2

I assume that out is declared to be an ostream (or a subclass such as ofstream). When you comment out the line out.open(...), out is initialized as a closed file. As such when you try to write to it, nothing happens, and the injection fails... but you fail to test whether it succeeded or not!

If you tested it with:

    for (int k = 0; k < input.size(); k++) {
        out << input[k] << endl;
        if out.fail() {
            // process error condition...
        }
    }

you would pass in the error condition branch and would be able to know that the injection did not occur.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
2

ofstream uses this operator<< signature

basic_ostream& operator<<( std::basic_streambuf<CharT, Traits>* sb);

From cpppreference, operator<<, 8)

After constructing and checking the sentry object, checks if sb is a null pointer. If it is, executes setstate(badbit) and exits.

You can check this easily by doing

#include <iostream>
#include <fstream>

int main()
{
    std::ofstream sink;
    //sink.open("/dev/null");

    sink << "check state";

    switch(sink.rdstate())
    {
        case std::ios_base::failbit:
            std::cout << "stream state is failbit\n";
            break;
        case std::ios_base::goodbit:
            std::cout << "stream state is goodbit\n";
            break;
        case std::ios_base::eofbit:
            std::cout << "stream state is eofbit\n";
            break;
        case std::ios_base::badbit:
            std::cout << "stream state is badbit\n";
            break;
        default:
            break;
    }

    return 0;
}

Prints: stream state is badbit

hlscalon
  • 7,304
  • 4
  • 33
  • 40
1

out is an object of type std::ostream, similarly std::cout is an object of type std::ostream that lives in the global namespace (it is available in the beginning of your program).

objects of type std::ostream (output streams, including sub classes that extend it like std::ofstream ) have their << operator overloaded.

this way having cout<<"hello"; is the same thing as std::cout.operator<<("Hello World");

note that the overloaded << operator returns a reference to the ostream object so cout<<"hi" << " there"; is basically

std::cout.operator<<("hi").operator<<(" there"));

you need to open any output file stream before writing to it. By doing so, you are invoking a syscall to the OS that gives you access to the files so you can write to them. Otherwise, you are attempting to write to a closed file that your process has no access writing to.

you don't have to do this explicitly for std::cout but you should open your own output file streams.

Don't forget to close your open files!!

ForeverStudent
  • 2,487
  • 1
  • 14
  • 33