FILE objects

B

Bill Cunningham

I've been trying to fopen a file, fread it and fwrite it to another file
or stdout while having k&r2 at hand and having no luck. The appendix seems
to be very vague on the FILE struct components.

Bill
 
C

Christopher Benson-Manica

Bill Cunningham said:
I've been trying to fopen a file, fread it and fwrite it to another file
or stdout while having k&r2 at hand and having no luck. The appendix seems
to be very vague on the FILE struct components.

Let's see the code - I'm sure clc can help.
 
G

Gordon Burditt

I've been trying to fopen a file, fread it and fwrite it to another file
or stdout while having k&r2 at hand and having no luck. The appendix seems
to be very vague on the FILE struct components.

It *SHOULD* be vague on the FILE struct components. Hands off!
The stuff in there is system-specific and is likely to not be very
helpful unless you really know how it works, in which case you
probably wouldn't be having the above problem.

When you call fopen(), do you check for whether it returns NULL?
If fopen() returns NULL, do you call perror() or strerror() and
then print the resulting string in a nice error message for the
user/programmer? (Yes, I know fopen() is not guaranteed to set
errno, but as long as it's not guaranteed to *NOT* set errno,
printing the possibly irrelevant message is more useful for the
programmer, or for the user who can report it to the programmer,
to debugging than not printing it). You do need to realize that
some error messages are not applicable, for example, "output.txt:
not a typewriter" doesn't make a lot of sense, but "output.txt:
permission denied" suggests a reason why the file couldn't be
created.

Did you fopen() the file in binary mode? Do you WANT to open the
file in binary mode? If you are trying to fwrite() the contents
of C types such as int, long, float, double, or struct, chances are
you want to open an output file in binary mode, and when you try
to read it back in, you also want it opened in binary mode. On the
other hand, if you're just going to fwrite() blobs of text, maybe
you want the file open in text mode.

Do you check the return values from fread() and fwrite()? Have you
tried using a hex dump utility on the output file, and compared the
file contents with what you expect to be in there? Does your code
realize that fread() may well read in the data in chunks that don't
correspond with the chunks that you wrote in the first place?

Gordon L. Burditt
 
E

Eric Sosman

Bill said:
I've been trying to fopen a file, fread it and fwrite it to another file
or stdout while having k&r2 at hand and having no luck. The appendix seems
to be very vague on the FILE struct components.

The vagueness is intentional, since the details of the
FILE object are not supposed to concern you, and indeed are
different from one implementation to the next.

None of the Standard library functions accept or return
`FILE' objects anyhow: they all deal in `FILE*' pointers to
such objects. Have you mixed up the pointer and the pointee?
 
M

Malcolm

Bill Cunningham said:
I've been trying to fopen a file, fread it and fwrite it to another file
or stdout while having k&r2 at hand and having no luck. The
appendix seems to be very vague on the FILE struct components.
FILE is an opaque structure. If you access the members then you are doing
something wrong.

Try the following

/*
a copy utility
*/
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
FILE *fpin;
FILE *fpout;
int ch;
fpin = fopen(argv[1], "rb");
if(!fpin)
{
printf("Can't open %s for reading\n", argv[1]);
exit(EXIT_FAILURE);
}

fpout = fopen(argv[2], "wb");
if(!fpout)
{
printf("Can't open %s for writing\n", argv[2]);
exit(EXIT_FAILURE);
}

/* the loop */
while( (ch = fgetc(fpin)) != EOF)
fputc(ch, fpout);

/* claen up and go home */
fclose(fpin);
if( fclose(fpout) != 0)
{
printf("Error closing %s\n", argv[2]);
exit(EXIT_FAILURE);
}

return 0;
}
 
B

Bill Cunningham

Let's see the code - I'm sure clc can help.

printf("EnterFilename-> ");
fflush(stdout);
char fname;
scanf("%c",&fname);
FILE *fp;
fopen(fname,30,30,fp);
fread(fname,"rb");
fwrite("file",30,30,fp);
fclose(fp);
Now I know there should be some casts here. I find k&r2's function
prototypes hard to read. Not the functions explained with bodies in the
book. But these file functions aren't described in detail. I don't
understand the parameters by looking at prototypes and no example of how to
write the code.

Bill
 
M

Marcin Hoppe

Bill said:
printf("EnterFilename-> ");
fflush(stdout);
char fname;
scanf("%c",&fname);
FILE *fp;
fopen(fname,30,30,fp);
fread(fname,"rb");
fwrite("file",30,30,fp);
fclose(fp);
Now I know there should be some casts here. I find k&r2's function
prototypes hard to read. Not the functions explained with bodies in the
book. But these file functions aren't described in detail. I don't
understand the parameters by looking at prototypes and no example of how to
write the code.

You have a problem with reading the filename. You declared it as a
single character, not as an array of characters (string). The second
problem I noticed is that you've misused fopen and fwrite functions.
After some improvements your code should be similar to this:

#include <stdio.h>

int main() {
/* File object */
FILE *fp = NULL;
/* File name */
char fname[256];
/* Some buffer to read, 30 bytes (on my computer) */
char rd_buf[30];

/* Nice prompt :) */
printf("EnterFilename->");
fflush(stdout);

/* This way you get the whole string */
scanf("%s", fname);

/* Open the file for reading in binary mode */
fp = fopen(fname, "rb");

/* Check if file was opened successfully */
if(fp != NULL) {
/* Read some bytes from the opened file */
/* Data is read to the rd_buf buffer */
/* Amount of data read is computed here, */
/* so you don't need to worry if you change */
/* size of the buffer */
fread( (void *) rd_buf, sizeof(char),
sizeof(rd_buf) / sizeof(rd_buf[0]), fp);
}

/* Close the file */
fclose(fp);

return 0;
}

I hope I've helped.
 
B

Bill Cunningham

Try the following

/*
a copy utility
*/
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
FILE *fpin;
FILE *fpout;
int ch;
fpin = fopen(argv[1], "rb");
if(!fpin)
{
printf("Can't open %s for reading\n", argv[1]);
exit(EXIT_FAILURE);
}

fpout = fopen(argv[2], "wb");
if(!fpout)
{
printf("Can't open %s for writing\n", argv[2]);
exit(EXIT_FAILURE);
}

/* the loop */
while( (ch = fgetc(fpin)) != EOF)
fputc(ch, fpout);

/* claen up and go home */
fclose(fpin);
if( fclose(fpout) != 0)
{
printf("Error closing %s\n", argv[2]);
exit(EXIT_FAILURE);
}

return 0;
}
I've never used stdlib. Is it the standard utilities header? That
parameter in main I've never quite understood either. I know main(void) but
that's it. How many parameters can main take.

Bill
 
E

Eric Sosman

Bill said:
Let's see the code - I'm sure clc can help.

printf("EnterFilename-> ");
fflush(stdout);
char fname;
scanf("%c",&fname);
FILE *fp;
fopen(fname,30,30,fp);
fread(fname,"rb");
fwrite("file",30,30,fp);
fclose(fp);
Now I know there should be some casts here. [...]

"This isn't right. It isn't even wrong." It's certainly
beyond the power of casts to correct.
I find k&r2's function
prototypes hard to read. Not the functions explained with bodies in the
book. But these file functions aren't described in detail. I don't
understand the parameters by looking at prototypes and no example of how to
write the code.

You'll notice that Christopher asked you for *the* code,
not just for *some* code. Please post *the* code, not a
sawed-off bleeding chunk, nor yet a paraphrase: *the* code,
cut'n'pasted straight from your editor into the message.

As it stands, we're all left guessing about what's going
on. You probably #include'd <stdio.h> because otherwise
the compiler would have barfed on the undefined identifier
`stdout' -- but if <stdio.h> was i#include'd the compiler
would have barfed on the incorrect arguments to fopen() and
fread(). Clearly you have done something very peculiar indeed,
and nobody's likely to give you a good diagnosis until you
reveal what you've done.

Or (sudden sad disillusionment) is it possible that you
have in fact written no code at all, and you're simply trying
to trick c.l.c. into writing your homework assignment for you?
Say it ain't so, Joe.
 
B

Bill Cunningham

Have you mixed up the pointer and the pointee?
Quite probably. I don't know when I need int var or int *var.

Bill
 
G

Gordon Burditt

Let's see the code - I'm sure clc can help.
printf("EnterFilename-> ");
fflush(stdout);
char fname;
In C89, this is not a valid place for a C variable declaration.
A filename is a NUL-terminated array of characters. One
character, including the terminating NUL, is not enough.
Try:
char fname[10240]; /* hope this is long enough */
scanf("%c",&fname);
A C string should use %s, not %c.
FILE *fp;
In C89, this is not a valid place for a C variable declaration.
fopen(fname,30,30,fp);

Check the return value of fopen()!! Also, fopen() has two arguments,
not 4.
fread(fname,"rb");

Check the return value of fread(). You seem to have gotten the
arguments to fopen() and fread() switched here.
fwrite("file",30,30,fp);
Check the return value of fwrite(). Also, the first argument is
a buffer containing the data to write, NOT the file name.
fclose(fp);
Now I know there should be some casts here. I find k&r2's function
prototypes hard to read. Not the functions explained with bodies in the
book. But these file functions aren't described in detail. I don't
understand the parameters by looking at prototypes and no example of how to
write the code.

It's obvious you need to do a lot of manual reading before trying
to write this code. Maybe you should get something more at a tutorial
level; K&R tends to be more of a reference manual for people who
know this stuff to look up the details rather than trying to teach
the basics.

Gordon L. Burditt
 
T

Thomas stegen

Bill said:
Have you mixed up the pointer and the pointee?


Quite probably. I don't know when I need int var or int *var.

My suggestion to you is to stay completely away from
pointers and file operations until you have a better grasp
of the language. Do some calculations using loops and
whatnot until you are sure you understand how variables work.
Then do the same using function calls. Then maybe add in
some structs and after that start using pointers. Build slowly,
and only when you are sure you have the foundation in place
move on. If you have trouble with the difference between
int var and int *var I suggest you stay away from FILE
objects for now.
 
M

Malcolm

Bill Cunningham said:
I've never used stdlib. Is it the standard utilities header?
Yes. Here it is used for the exit() function and the EXIT_FAILURE value that
we use to indicate that the program hasn't worked for some reason. You also
need stdlib for malloc().
That parameter in main I've never quite understood either. I know
main(void) but that's it. How many parameters can main take.
main() can either be void, or it can take 2 parameters, argc and argv. argc
tells you how many words were typed on the command line, argv is an array of
strings. Conventionally, argv[0] is the name of the program. If you typed
copy.exe myfile.x newfile.x

argv[0] = copy.exe
argv[1] = myfile.x
argv[2] = newfile.x

(Incidentally there is a bug in my program. Really we should check that argc
== 3 and report an error if it does not. It might crash if invoked with only
one filename.)
 
B

Bill Cunningham

You have a problem with reading the filename. You declared it as a
single character, not as an array of characters (string). The second
problem I noticed is that you've misused fopen and fwrite functions.
After some improvements your code should be similar to this:

#include <stdio.h>

int main() {
/* File object */
FILE *fp = NULL;
/* File name */
char fname[256];
/* Some buffer to read, 30 bytes (on my computer) */
char rd_buf[30];

/* Nice prompt :) */
printf("EnterFilename->");
fflush(stdout);

/* This way you get the whole string */
scanf("%s", fname);

/* Open the file for reading in binary mode */
fp = fopen(fname, "rb");

/* Check if file was opened successfully */
if(fp != NULL) {
/* Read some bytes from the opened file */
/* Data is read to the rd_buf buffer */
/* Amount of data read is computed here, */
/* so you don't need to worry if you change */
/* size of the buffer */
fread( (void *) rd_buf, sizeof(char),
sizeof(rd_buf) / sizeof(rd_buf[0]), fp);
}

/* Close the file */
fclose(fp);

return 0;
}

I hope I've helped.
Those sizeof's in your code. Do they report to size_t ?

Bill
 
M

Marcin Hoppe

Bill said:
Those sizeof's in your code. Do they report to size_t ?

The sizeof operator returns the size of its argument. Its "unit" is the
size of char (on x86 platform it is usually 1 byte) and the return type
is size_t. It's written in K&R :).
 
B

Bill Cunningham

If you have trouble with the difference between
int var and int *var I suggest you stay away from FILE
objects for now.
I know what they mean. var is a variable. A place in memory for an int.
And *var is a pointer to a location in memory that is an int. What I confuse
is how to use this in function parameters.

For example int function(void**)
That's a pointer to a pointer to a void. But what do you do with it in
code ?

Bill
 
B

Bill Cunningham

Eric Sosman said:
Bill said:
Let's see the code - I'm sure clc can help.

printf("EnterFilename-> ");
fflush(stdout);
char fname;
scanf("%c",&fname);
FILE *fp;
fopen(fname,30,30,fp);
fread(fname,"rb");
fwrite("file",30,30,fp);
fclose(fp);
Now I know there should be some casts here. [...]

"This isn't right. It isn't even wrong." It's certainly
beyond the power of casts to correct.
I find k&r2's function
prototypes hard to read. Not the functions explained with bodies in the
book. But these file functions aren't described in detail. I don't
understand the parameters by looking at prototypes and no example of how to
write the code.

You'll notice that Christopher asked you for *the* code,
not just for *some* code. Please post *the* code, not a
sawed-off bleeding chunk, nor yet a paraphrase: *the* code,
cut'n'pasted straight from your editor into the message.

As it stands, we're all left guessing about what's going
on. You probably #include'd <stdio.h> because otherwise
the compiler would have barfed on the undefined identifier
`stdout' -- but if <stdio.h> was i#include'd the compiler
would have barfed on the incorrect arguments to fopen() and
fread(). Clearly you have done something very peculiar indeed,
and nobody's likely to give you a good diagnosis until you
reveal what you've done.

Or (sudden sad disillusionment) is it possible that you
have in fact written no code at all, and you're simply trying
to trick c.l.c. into writing your homework assignment for you?
Say it ain't so, Joe.
That's *the* code. And it isn't a joke though alot of people in clc look
at my code and think that. And yes take it for granted #include <stdio.h> is
there. And int main(void).

Bill
 
I

Irrwahn Grausewitz

Marcin Hoppe said:
The sizeof operator returns the size of its argument. Its "unit" is the
size of char (on x86 platform it is usually 1 byte)

Minor correction: sizeof(char) is 1 byte per definition on every
conforming C implementation. What might be different on different
platforms is the number of bits per byte.
and the return type
is size_t. It's written in K&R :).

Regards
 
C

Christopher Benson-Manica

Malcolm said:
Conventionally, argv[0] is the name of the program.

In the not-too-distant past, there was a rather extended (I think)
discussion about this point; I'd be most grateful if someone could
remind me what the end consensus was.
 
C

CBFalconer

Christopher said:
Malcolm said:
Conventionally, argv[0] is the name of the program.

In the not-too-distant past, there was a rather extended (I think)
discussion about this point; I'd be most grateful if someone could
remind me what the end consensus was.

As usual, "it depends". :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
474,141
Messages
2,570,817
Members
47,366
Latest member
IanCulpepp

Latest Threads

Top