0

Can somebody tell me why this isn't working? This thing just doesn't want to write data to a file. Input is fine. fout.open("Dats.txt", std::ios::out | std::ios::app); doesn't work either.

std::ifstream fin;
std::fstream fout;

fin.open("Dats.txt");
fout.open("C:/Users/Shantykoff/Documents/visual studio 2017/Projects/Input_Output_fstream_basis/Input_Output_fstream_basis/Dats.txt",
          std::ios::out | std::ios::app);

The problematic piece of code:

void inputData() {
    Data temp;
    std::cout << "Inserisci x\n";
    std::cin >> temp.x;
    fout << temp.x << "\n";
}
Fureeish
  • 12,533
  • 4
  • 32
  • 62
  • 2
    Maybe make `fout`an ofstream instead of std::ftsream? Did you check that your reading to temp.x was alright? – Cyril Lemaire Jan 16 '18 at 23:31
  • 1
    Does the file open successfully? – chris Jan 16 '18 at 23:32
  • Yes, i checked that, it opens – Shantykoff Jan 16 '18 at 23:32
  • Is the stream still in a good state after the output statement, or does it go from good to bad? – chris Jan 16 '18 at 23:33
  • When/where do you `fout.close();` to ensure that any file buffer contents are written? Have a look at this basic [tutorial](http://www.cplusplus.com/doc/tutorial/files/), and then expand upon that for what you're trying to accomplish. The part about the file buffer contents is covered at the bottom of the page. – Paul T. Jan 16 '18 at 23:37
  • 1
    @PaulT., the `std::fstream` destructors are guaranteed to call `close()`. Calling it by yourself is simply pointless, as explained [here](https://stackoverflow.com/questions/748014/do-i-need-to-manually-close-an-ifstream) – Fureeish Jan 16 '18 at 23:39
  • @chris, its good, before and after trying to write to file :C – Shantykoff Jan 16 '18 at 23:43
  • @PaulT. I used fout.close() in the destructor of the class I use to manage inputs and outputs for that file. And, I'm sure this isn't important, but that function is a method :) – Shantykoff Jan 16 '18 at 23:47
  • @Fureeish: ...that is good to know. I come from a pre-C++03 point of view, and have always used close(). Seen it used in other source code to this day, had to do that WAY back in school, etc. Has the RAII been around since before that time, or is that part of a new[er] standard? – Paul T. Jan 16 '18 at 23:49
  • @CyrilLemaire i tried std::ofstream also, that didn't work. Also I checked temp.x input, input is working :C – Shantykoff Jan 16 '18 at 23:51
  • @PaulT., That's been around since at least C++98 :) – chris Jan 16 '18 at 23:52
  • @chris: yep, that would have been around the SAME time that I first learned C++. I have been involved with other languages, and have not used C++ for well over 12 years now (if not a bit longer), so that explains it! – Paul T. Jan 16 '18 at 23:55
  • 1
    The `fout` object within the `inputData()` function; is this object declared as a `global` object? – Francis Cugler Jan 17 '18 at 01:43

1 Answers1

1

In this section of your code:

void inputData() {
    Data temp;
    std::cout << "Inserisci x\n";
    std::cin >> temp.x;
    fout << temp.x << "\n";
}

The last line you have a variable named fout that has local scope to this function that isn't declared anywhere in this block of code or within this scope. You have two options to resolve this, unless you are declaring this object in global scope outside of the main function in which you have not specified:

  • You can create an std::ofstream temporary object within this function but you would have to open & close the file stream.
  • Or you can pass an ofstream object by reference to this function.

I'll show an example of each:

void inputData() {
    Data temp;
    std::cout << "Iserisci x\n";
    std::cin >> temp.x;
    std::ofstream fout;
    fout.open( /* filename & path */ );
    fout << temp.x << "\n"; 
}

Or

void inputData( std::ostream& out ) {
    Data temp;
    std::cout << "Iserisci x\n";
    std::cin >> temp.x;
    out << temp.x << "\n";
}

Then in the code block that is invoking this function you can do...

{
    //... some other code
    std::ofstream fout;
    fout.open( "path & filename", flags );
    inputData( fout );
    fout.close();

    //... some other code
 }

If you noticed closely in this function I passed a reference to a std::ostream object instead of a std::ofstream object. Why did I choose to do this? It is simple because this function can now take any output stream type object instead of just an output file stream object...

{    
    inputData( std::cout ); // will now print to console out
    std::ostringsream ostr;
    inputData( ostr ); // will now populate the output string stream object

    // etc...
}

Basically put this line of code: fout << temp.x << "\n"; in your function above the fout object is not declared or defined in the scope of this code block unless if fout is in the global namespace outside of the main function.


Edit - Optional but as a side note with this line of code:

fout.open("C:/Users/Shantykoff/Documents/visual studio 2017/Projects/Input_Output_fstream_basis/Input_Output_fstream_basis/Dats.txt",
      std::ios::out | std::ios::app);

What I'll typically do since you are using visual studio is this:

Under the current project settings in your solution explorer:

  • Under Configuration Properties - for current config & platform settings
    • General
      • Output Directory: set to - $(SolutionDir)"ProjectName"\_build\
    • Debugging
      • Working Directory: set to - $(ProjectDir)_build\

Note: "ProjectName" is just a place holder for the actual name of the project.

Then this way you don't have to specify your entire path from the root directory C:\

Then in your code when you have files such as this:

sample.txt - placed in the _build folder where the executable will now reside instead of "visual studio's" default location.

1 2 3 4 5 6 7 8 9

main.cpp

int main() {
    std::vector<unsigned> values;

    std::ifstream in;
    unsigned val;
    in.open( "sample.txt" );
    while ( in >> val ) {
        values.push_back( val );
    }
    in.close();

    // lets modify some values
    for ( auto v : values ) {
        v *= 10;
    }

    // Let's print new values to same file but lets append it to a new line
    std::ofstream out;
    out.open( "sample.txt", std::ios::app );
    for ( auto v : values ) {
        out << "\n";
        out << v << " ";
    }
    out.close();

    return 0;
}

sample.txt

1 2 3 4 5 6 7 8 9
10 20 30 40 50 60 70 80 90

Now by creating a _build folder within the solution explorer it makes the reading of code for long paths easier to read since the paths are now relative to the project's directories and should be pointing to the same folder that will contain the applications executable as well as any third party dependencies - external dlls. Now as for myself I chose to place an single underscore in the front of the build folders name only to keep it towards the top of its parent directory.

Francis Cugler
  • 7,788
  • 2
  • 28
  • 59
  • 1
    It may be awful practice, but there's no reason to assume they're not using a global fout stream that has been opened prior to calling the function. Awful practice, but still valid code. – Alex Huszagh Jan 17 '18 at 01:21
  • @AlexanderHuszagh Yes true, that is why I did mention it within the answer; because without it being shown there is no way to know if they are using such a `global object` or not. – Francis Cugler Jan 17 '18 at 01:36
  • 1
    Then this strictly isn't true: `The last line you have a variable named fout that has local scope to this function that isn't declared anywhere in this block of code or within this scope. You have two options to resolve this:`. They state no compile errors: Ask for more information. – Alex Huszagh Jan 17 '18 at 01:39
  • @AlexanderHuszagh true enough; but from what they have supplied even though I shouldn't have... making the assumptions that it's not outputting properly. This is the only thing that I can think of. They are able to "read" in from the file, but not output to a file, and I am seeing an undeclared ofstream object in local scope of a function. – Francis Cugler Jan 17 '18 at 01:42