-2

Not to bother anyone, but i have ran into an issue with a class of mine, somehow when i write to a file with the FILE* and fprintf() function i don't get any text in my text file that i created, i have searched all over youtube and i don't know what i'm doing wrong, because my code is the same.

Heres a copy of my .c++ and .h code:

main.c++:

#include <iostream>

#include "../include/include.h"

using namespace std;

int main() {
    
    write_file wf("test.txt");
    wf.write_line("Hello, world!");

    return 0;
}

include.h:

#ifndef INCLUDE_H
#define INCLUDE_H

#include <iostream>

class write_file {
public:
    write_file(const char *file_name) {
        FILE* fp = fopen(file_name, "w");
    }
    void write_line(const char *line) {
        fprintf(fp, "%s\n", line);
    }
    void close() {
        fclose(fp);
    }
    private: FILE* fp;
};

#endif /* include.h */
Daniel Trugman
  • 8,186
  • 20
  • 41
  • 6
    `FILE* fp = fopen(file_name, "w");` in the constructor declares and initializes a local variable named `fp`, which is destroyed at the end of the function. The data member named `fp` remains uninitialized. `write_line` then exhibits undefined behavior by way of accessing this uninitialized data member. – Igor Tandetnik Jun 14 '22 at 21:51
  • 2
    Even after fixing that, you are leaking the `FILE*` since you are never `fclose()`'ing it. You should call your `close()` method in your class destructor. Also: "*i have searched all over youtube and i don't know what i'm doing wrong*" - you are using YouTube to learn C++, which is not a good option. Seriously, get yourself a [good C++ book](https://stackoverflow.com/questions/388242/) instead. – Remy Lebeau Jun 14 '22 at 21:52
  • You should `#include ` instead of `` if you want to use C streams – Ted Lyngmo Jun 14 '22 at 21:52
  • 1
    You should use C++'s `std::ofstream` class instead of C's `FILE` struct. – Remy Lebeau Jun 14 '22 at 21:54
  • You should also read [The rule of three/five/zero](https://en.cppreference.com/w/cpp/language/rule_of_three) so that you don't get in trouble later. – Ted Lyngmo Jun 14 '22 at 22:13

2 Answers2

2

Main issue:

To fix your issue, you have to remove the local fp variable that shadows the class member.

When the compiler sees FILE *fp in your method, it uses a separate variable and is not referring to the one in your class instance.

Change the method definition to:

    write_file(const char *file_name) {
        fp = fopen(file_name, "w");
    }

Additional points I really ought to comment on:

  • You never call close. Mishandling resources is one of the most common mistakes in C & CPP. Make sure to implement a destructor that calls close. If you do that, make sure to improve the close implementation to handle multiple calls.

  • Consider using standard CPP classes for interacting with files, specifically ifstream and ofstream. Those handle a lot of the fuss automagically for you.

  • Please don't use .c++ as a file extension. This is really odd. Most CPP developers use .cpp or .cc for CPP source files.

  • I might be saying that because I'm not a gen-Z kid, but please don't search Youtube for programming tutorials. Searching text-based sources is so much more efficient. Learn how to use cplusplus or cppreference instead.

Daniel Trugman
  • 8,186
  • 20
  • 41
0

The problem arises because your FILE* file handle that you declare inside the class constructor goes out of scope once program execution exits the constructor (and also when you have just opened the file, ironically).

To avoid this , remove the FILE* declaration part in

FILE* fp = fopen(file_name, "w");

and use the fp data member you have in your class as

this->fp = fopen(file_name, "w");

You can also go on and remove the this-> if it hinders readability. As mentioned in the other answer you have not provided a fclose() on the file that you just opened. This can lead to several worse problems than being unable to read files that I don't wish to expand upon now but which you can read from here .

Considering your class and use case where you are reading the file separately after opening it in constructor it's best to add fclose() in your class destructor like this.

~write_file() {
    fclose(this->fp);
}