tags:

views:

648

answers:

5

What is the correct way to declare and use a FILE * pointer in C/C++? Should it be declared global or local? Can somebody show a good example?

+11  A: 

It doesn't matter at all whether it's local or global. The scope of the file pointer has nothing to do with its use.

It's usually a good idea to avoid global variables as much as possible.

Here's a sample showing how to copy from input.txt to output.txt:

#include <stdio.h>
int main (void) {
    FILE *fin;
    FILE *fout;
    int c;

    fin = fopen ("input.txt", "r");
    if (fin != NULL) {
        fout = fopen ("output.txt", "w");
        if (fout != NULL) {
            c = fgetc (fin);
            while (c >= 0) {
                fputc (c, fout);
                c = fgetc (fin);
            }
            fclose (fout);
        } else {
            fprintf (stderr, "Cannot write to output.txt");
        }
        fclose (fin);
    } else {
        fprintf (stderr, "Cannot read from input.txt");
    }
    return 0;
}
paxdiablo
+1  A: 

Here is the first hit on google for "file io in c"

http://www.cs.bu.edu/teaching/c/file-io/intro/

Here is the third hit from gamedev with more of a C++ slant

http://www.gamedev.net/reference/articles/article1127.asp

You declare the pointer in the scope that you need it.

Andrew Barrett
+1  A: 

It's just an ordinary pointer like any other.

FILE *CreateLogFile() 
{
    return fopen("logfile.txt","w"); // allocates a FILE object and returns a pointer to it
}

void UsefulFunction()
{
   FILE *pLog = CreateLogFile(); // it's safe to return a pointer from a func
   int resultsOfWork = DoSomeWork();
   fprintf( pLog, "Work did %d\n", resultsOfWork );  // you can pass it to other functions
   fclose( pLog ); // just be sure to clean it up when you are done with fclose()
   pLog = NULL;    // and it's a good idea to overwrite the pointer afterwards
                   // so it's obvious you deleted what it points to
}
Crashworks
+1  A: 
int main(void)
{
  char c;
  FILE *read;
  read = fopen("myfile", "r"); // opens "myfile" for reading
  if(read == NULL)
  {
    perror("Error: could not open \"myfile\" for reading.\n");
    exit(1);
  }
  c = fgetc(read);
  fclose(read);
  printf("The first character of myfile is %c.\n", c);
  return 0;
}

You're perfectly allowed to declare global filehandles if you like, just like any other variable, but it may not be recommended.

This is the C way. C++ can use this, but I think there's a more C++ friendly way of doing it. As a note, I hate it when questions are marked C/C++, because C and C++ are not the same language and do not work the same. C++ has a lot of different ways to do things that C doesn't have, and they may be easier for you to do in the context of C++ but are not valid C. So while this will work for either language, it's not what you want if you predominantly use C++.

EDIT: Added some error checking. Always use error checking in your code.

Chris Lutz
A: 

First, keep in mind that a file pointer (and the associated allocated structure) is based on the lower level open() read() write() calls. The associated file descriptor (obtained by fileno(file_pointer) is the least interesting thing, but something you might want to watch your scope with.

If your going to declare a file pointer as global in a module, its usually a very good idea to keep it static (contained within that module / object file). Sometimes this is a little easier than storing it in a structure that is passed from function to function if you need to write something in a hurry.

For instance, (bad)

#include <stdio.h>
#include ...

#define MY_LOG_FILE "file.txt"

FILE *logfile

Better done as:

#include <stdio.h>

#define MY_LOG_FILE "file.txt"

static FILE *logfile;

int main(void)
{

UNLESS, you need several modules to have access to that pointer, in which case you're better off putting it in a structure that can be passed around.

If its needed only in one module, consider declaring it in main() and letting other functions accept a file pointer as an argument. So, unless your functions within the module have so many arguments that another would be unbearable .. there's (usually) no reason to declare a file pointer globally.

Some logging libraries do it, which I don't care for ... especially when dealing with re-entrant functions. Nevermind C's monolithic namespace :)

Tim Post