Thread: Instantiate FILE handler in header file

  1. #1
    Registered User
    Join Date
    Oct 2008
    Posts
    77

    Instantiate FILE handler in header file

    Hi,
    I need to define a macro in a header file in C++ which is called lots of time in the application (for particular, thus non-negociable, log reasons).
    I have created the macro as following:

    Code:
    #pragma once
    // include statements
    #define MYMACRO(one, two) {\
    FILE *filepointer;\
    /* code */\
    filepointer = fopen("logfile.txt", "a");\
    fprintf(filepointer, "%s", somemessage);\
    fclose(filepointer);\
    }\
    The code is built and does the job it is intended for. But it opens and closes the file at each call. I want to create the 'filepointer' object, and instantiate it with the fopen() value as above, outside de macro, just before the
    Code:
    #define MYMACRO
    statement, so that not to have to open/close each time the macro is called.
    I have quickly read that this is possible by defining a class in the header, with diffferent possibilities for the instantiation. I this case I think I would also be able to take off
    Code:
    fclose()
    (the file will be closed when application exits).
    Therefore, I appreciate your contribution on how to properly implement this requirement.
    Thanks!

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    In C++ you really should be avoiding macros in all but the rarest of circumstances and IMO the same goes for using the C-stdio functions.

    While global variables are usually considered a bad practice, this might be a case where a global ofstream might be an acceptable alternative.

    I this case I think I would also be able to take off fclose() (the file will be closed when application exits).
    One of the benefits of using a C++ stream is that it automatically closes when the stream goes out of scope (the end of the program in this case).

    Jim

  3. #3
    Registered User
    Join Date
    Oct 2008
    Posts
    77
    Thanks Jim,
    I keep my question because, as I've mentioned, I have to do so. But what would be the code then as you propose?
    Thanks

  4. #4
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    Here is a very simple example (no horrible, potentially unsafe macro required).

    Code:
    #include <fstream>
    
    std::ofstream log;
    
    int main()
    {
        log.open("LogFileName");
    
       // Write to log file.
       log << "Error: " << 23 << " Something bad happened!" << std::flush();
    
    }
    Jim

  5. #5
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    An even better solution might be to have a global function that handles the setup and logging.

    Code:
    #include <fstream>
    
    template<typename... Args>
    void log(Args... args)
    {
      std::ofstream logStream("LogFileName");
    
      int i = 0;
      std::initializer_list<int>{ ((logStream << (i++ ? " " : "") << std::forward<Args>(args)), 0)... };
      logStream.flush();
    }
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  6. #6
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    But won't that "global function" open and close the stream every time you call the function?

    Jim

  7. #7
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Yes, it will, but so does the OP's macro.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  8. #8
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    but so does the OP's macro.
    Yes, but the purpose of this topic is to find a method to avoid the opening and closing of the stream each time the log functionality is used.

    so that not to have to open/close each time the macro is called.
    Jim

  9. #9
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    It would be a simple matter to have the ofstream defined somewhere, and have the log function reference it, opening the file if it is not already open.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    If you're going to keep it inside a function, you may as well declare it static.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Registered User
    Join Date
    Dec 2010
    Location
    Trinidad, CO (log cabin in middle of nowhere)
    Posts
    148
    Is this simply for debugging purposes?

  12. #12
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Quote Originally Posted by Elysia View Post
    If you're going to keep it inside a function, you may as well declare it static.
    I considered that for my example, but then there would be (potentially) one copy for every translation unit that included the header. Still an improvement over opening and closing on every call though.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I'm not 100% sure on the rules, but if you make an inline function, you get ONE function and therefore ONE object. If you're going to include the header in multiple source units, the function should be declared inline anyway, or you're going to get compile errors.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #14
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Quote Originally Posted by Elysia View Post
    I'm not 100% sure on the rules, but if you make an inline function, you get ONE function and therefore ONE object. If you're going to include the header in multiple source units, the function should be declared inline anyway, or you're going to get compile errors.
    Except in the case of template functions, such as in my example, where there'd be one created for each unique instantiation of the template.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    True, now THAT detail (template function) I missed.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 09-12-2014, 04:45 PM
  2. Replies: 16
    Last Post: 04-05-2014, 09:23 PM
  3. Replies: 11
    Last Post: 09-25-2011, 12:22 AM
  4. Replies: 30
    Last Post: 06-19-2006, 12:35 AM
  5. Replies: 4
    Last Post: 12-14-2005, 02:21 PM

Tags for this Thread