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?
问题:
回答1:
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.
In general, it's 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, *fout; int c;
// Open both files, fail fast if either no good.
if ((fin = fopen("input.txt", "r")) == NULL) {
fprintf(stderr, "Cannot read from input.txt");
return 1;
}
if ((fout = fopen("output.txt", "w")) == NULL) {
fprintf(stderr, "Cannot write to output.txt");
fclose(fin);
return 1;
}
// Transfer character by character.
while ((c = fgetc(fin)) >= 0) {
fputc (c, fout);
}
// Close both files and exit.
fclose(fin);
fclose(fout);
return 0;
}
回答2:
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
}
回答3:
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.
回答4:
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.
回答5:
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 :)