Question on some C code that I saw

C

Chad

Someone had the following

#include <stdio.h>

int main(int argc, char *argv[])
{
FILE *fp = NULL;
char buffer[8];

/* insert argc/argv checking code here */

fp = fopen(argv[1], "w");
if(fp != NULL)
{
while(fgets(buffer, sizeof buffer, stdin))
{
printf("%s", buffer);
fprintf(fp, "%s", buffer);
}
fflush(stdout);
fflush(fp);
fclose(fp);
}
else
{
fprintf(stderr, "Broken tee.\n");
}
return 0;

}


Why did they call fllush()? I thought that flush() got called when you
called fclose(). Is this a coding error? If not, why call fflush()
when reading from stdin.

Chad
 
P

Peter Nilsson

Chad said:
Someone had the following

Richard won't be embarrased if you quote his code. Indeed,
he may prefer that you quote it in context.
#include <stdio.h>

int main(int argc, char *argv[])
{
FILE *fp = NULL;

[This is the giveaway line as to who the author was, but
I confirmed it with Google. ;-]
char buffer[8];

The original had 80 not 8, though it won't change the
semantics.
/* insert argc/argv checking code here */

fp = fopen(argv[1], "w");
if(fp != NULL)
{
while(fgets(buffer, sizeof buffer, stdin))
{
printf("%s", buffer);
fprintf(fp, "%s", buffer);
}
fflush(stdout);
fflush(fp);
fclose(fp);
}
else
{
fprintf(stderr, "Broken tee.\n");
}
return 0;

}

Why did they call fllush()?

ITYM fflush()
I thought that flush()

ITYM fflush()
got called when you called fclose().
Yes.

Is this a coding error?
No.

If not, why call fflush()

For fp, there's no requirement since it's closed straight
afterwards. Richard's reasons are probably aesthetic.

But for stdout, the last line read need not be terminated
with a newline. On many implementations, non-newline
terminated text won't appear on a stdout console until it
is flushed.
when reading from stdin.

That is incidental. fflush() generally only works on output
streams and is not dependant on whatever input stream (or
streams) you happen to be reading from.
 
S

santosh

Chad said:
Someone had the following

#include <stdio.h>

int main(int argc, char *argv[])
{
FILE *fp = NULL;
char buffer[8];

/* insert argc/argv checking code here */

fp = fopen(argv[1], "w");
if(fp != NULL)
{
while(fgets(buffer, sizeof buffer, stdin))
{
printf("%s", buffer);
fprintf(fp, "%s", buffer);
}
fflush(stdout);
fflush(fp);
fclose(fp);
}
else
{
fprintf(stderr, "Broken tee.\n");
}
return 0;

}


Why did they call fllush()? I thought that flush() got called when you
called fclose(). Is this a coding error? If not, why call fflush()
when reading from stdin.

When a stream is closed via an explicit call to fclose() or implicitly
by normal program termination, all it's buffers are flushed. But
sometimes it is necessary to make sure that the data is written to the
device immediately. Waiting till the stream is closed, or till the
program terminates, or till the buffers fill up, may be unacceptable.
In such situations fflush() can be employed. One alternative is to turn
off buffering for the stream by using setvbuf(), but this may not be
quite enough.

Note that fflush(stdin) is undefined behaviour.

The program doesn't seem to make a lot of sense to me. What exactly is
it supposed to accomplish? At a minimum it must remove the null
character written by fgets() before sending the buffer to 'fp'
and 'stdout'. Also I think the two calls to fflush() should be within,
not outside, the while loop. Also it returns "successful" termination
for regardless of the program's actual outcome.
 
J

Jack Klein

Someone had the following

#include <stdio.h>

int main(int argc, char *argv[])
{
FILE *fp = NULL;
char buffer[8];

/* insert argc/argv checking code here */

fp = fopen(argv[1], "w");
if(fp != NULL)
{
while(fgets(buffer, sizeof buffer, stdin))
{
printf("%s", buffer);
fprintf(fp, "%s", buffer);
}
fflush(stdout);
fflush(fp);

A single call to fflush(NULL) could replace both calls above, with
exactly the same result.
fclose(fp);
}
else
{
fprintf(stderr, "Broken tee.\n");
}
return 0;

}


Why did they call fllush()? I thought that flush() got called when you
called fclose(). Is this a coding error? If not, why call fflush()
when reading from stdin.

It is never an error to call fflush(NULL) on a valid file pointer
opened for output and not closed.

As to why, either a programmer who does not know what he is doing or,
much less likely, a broken library.

But what makes you think that reading from stdin has anything to do
with is?

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
 
C

Chad

Someone had the following
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp = NULL;
char buffer[8];
/* insert argc/argv checking code here */
fp = fopen(argv[1], "w");
if(fp != NULL)
{
while(fgets(buffer, sizeof buffer, stdin))
{
printf("%s", buffer);
fprintf(fp, "%s", buffer);
}
fflush(stdout);
fflush(fp);

A single call to fflush(NULL) could replace both calls above, with
exactly the same result.
fclose(fp);
}
else
{
fprintf(stderr, "Broken tee.\n");
}
return 0;

Why did they call fllush()? I thought that flush() got called when you
called fclose(). Is this a coding error? If not, why call fflush()
when reading from stdin.

It is never an error to call fflush(NULL) on a valid file pointer
opened for output and not closed.

As to why, either a programmer who does not know what he is doing or,
much less likely, a broken library.

But what makes you think that reading from stdin has anything to do
with is?

Ughhh....I should have proofread before making the post. I'm sure the
typos aren't inspiring any kind of fear and awe into the regulars on
this newsgroup.


Now I think this is probably the first time that I've seen someone
call fflush() and then fclose() when calling fgets(). I figured this
might have had to do something with stdin.
 
C

Chad

Someone had the following
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp = NULL;
char buffer[8];
/* insert argc/argv checking code here */
fp = fopen(argv[1], "w");
if(fp != NULL)
{
while(fgets(buffer, sizeof buffer, stdin))
{
printf("%s", buffer);
fprintf(fp, "%s", buffer);
}
fflush(stdout);
fflush(fp);
fclose(fp);
}
else
{
fprintf(stderr, "Broken tee.\n");
}
return 0;

Why did they call fllush()? I thought that flush() got called when you
called fclose(). Is this a coding error? If not, why call fflush()
when reading from stdin.

When a stream is closed via an explicit call to fclose() or implicitly
by normal program termination, all it's buffers are flushed. But
sometimes it is necessary to make sure that the data is written to the
device immediately. Waiting till the stream is closed, or till the
program terminates, or till the buffers fill up, may be unacceptable.
In such situations fflush() can be employed. One alternative is to turn
off buffering for the stream by using setvbuf(), but this may not be
quite enough.

Note that fflush(stdin) is undefined behaviour.

The program doesn't seem to make a lot of sense to me. What exactly is
it supposed to accomplish? At a minimum it must remove the null
character written by fgets() before sending the buffer to 'fp'
and 'stdout'. Also I think the two calls to fflush() should be within,
not outside, the while loop. Also it returns "successful" termination
for regardless of the program's actual outcome.

I'm really not that sure what this program is supposed to accomplish.
 
K

Keith Thompson

santosh said:
Someone had the following

#include <stdio.h>

int main(int argc, char *argv[])
{
FILE *fp = NULL;
char buffer[8];

/* insert argc/argv checking code here */

fp = fopen(argv[1], "w");
if(fp != NULL)
{
while(fgets(buffer, sizeof buffer, stdin))
{
printf("%s", buffer);
fprintf(fp, "%s", buffer);
}
fflush(stdout);
fflush(fp);
fclose(fp);
}
else
{
fprintf(stderr, "Broken tee.\n");
}
return 0;

}
[...]
The program doesn't seem to make a lot of sense to me. What exactly is
it supposed to accomplish? At a minimum it must remove the null
character written by fgets() before sending the buffer to 'fp'
and 'stdout'. Also I think the two calls to fflush() should be within,
not outside, the while loop. Also it returns "successful" termination
for regardless of the program's actual outcome.

The '\0' characters aren't a problem, since {,f}printf with a "%s"
format expects a string and doesn't print the terminating '\0'.

The fflush(fp) is unnecessary, since it's immediately followed by
fclose(fp), but the fflush(stdout) is probably right where it needs to
be. Putting it inside the loop would cause output to be flushed
repeatedly.

The point of the program, I think, is to implement a version of the
Unix "tee" program, which copies stdin both to stdout and to a named
file. The use of fgets is probably just meant to demonstrate the use
of fgets (using fgetc and fputc would be simpler and likely just as
fast).
 
R

Richard Heathfield

Chad said:

fflush(stdout);
fflush(fp);
fclose(fp);
}
else
{
fprintf(stderr, "Broken tee.\n");
}
return 0;

}


Why did they call fllush()? I thought that flush() got called when you
called fclose().

7.19.5.1(2) reads: "A successful call to the fclose function causes the
stream pointed to by stream to be flushed and the associated file to be
closed."
Is this a coding error?

The failure to check the return values from fflush and fclose might be
considered a coding error, but the flush itself is only an error if you
consider redundant code to be a redundancy error for redundant code,
redundantly.
If not, why call fflush() when reading from stdin.

Calling fflush on an input stream *is* an error. 7.19.5.2(2): "If stream
points to an output stream or an update stream in which the most recent
operation was not input, the fflush function causes any unwritten data for
that stream to be delivered to the host environment to be written to the
file; otherwise, the behavior is undefined."
 
R

Richard Heathfield

Peter Nilsson said:
Richard won't be embarrased if you quote his code. Indeed,
he may prefer that you quote it in context.

If you mean me, yes, I think I would prefer some context. Where did the OP
dig up this code? The tee in CU is rather different in several details.
#include <stdio.h>

int main(int argc, char *argv[])
{
FILE *fp = NULL;

[This is the giveaway line as to who the author was, but
I confirmed it with Google. ;-]
char buffer[8];

The original had 80 not 8, though it won't change the
semantics.

The CU version has 2048. I guess you don't, after all, mean me.
 
C

Charlie Gordon

santosh said:
Chad said:
Someone had the following

#include <stdio.h>

int main(int argc, char *argv[])
{
FILE *fp = NULL;
char buffer[8];

/* insert argc/argv checking code here */

fp = fopen(argv[1], "w");
if(fp != NULL)
{
while(fgets(buffer, sizeof buffer, stdin))
{
printf("%s", buffer);
fprintf(fp, "%s", buffer);
}
fflush(stdout);
fflush(fp);
fclose(fp);
}
else
{
fprintf(stderr, "Broken tee.\n");
}
return 0;

}


Why did they call fllush()? I thought that flush() got called when you
called fclose(). Is this a coding error? If not, why call fflush()
when reading from stdin.

When a stream is closed via an explicit call to fclose() or implicitly
by normal program termination, all it's buffers are flushed. But
sometimes it is necessary to make sure that the data is written to the
device immediately. Waiting till the stream is closed, or till the
program terminates, or till the buffers fill up, may be unacceptable.
In such situations fflush() can be employed. One alternative is to turn
off buffering for the stream by using setvbuf(), but this may not be
quite enough.

Note that fflush(stdin) is undefined behaviour.

The program doesn't seem to make a lot of sense to me. What exactly is
it supposed to accomplish? At a minimum it must remove the null
character written by fgets() before sending the buffer to 'fp'
and 'stdout'. Also I think the two calls to fflush() should be within,
not outside, the while loop. Also it returns "successful" termination
for regardless of the program's actual outcome.

This program is a simplistic implementation of the unix tee command. It
copies its standard input to its standard output while saving a copy to a
file whose name is passed as a command line argument.
Of course the buffer size is ridiculous, so is the use of printf and fprintf
instead of fputs, not to mention the redundant calls to fflush.

Your remark regarding the "null character written by fgets" is erroneous:
printf does not output the string terminator. But you have inadvertantly
pointed to a real issue with this implementation: it cannot copy NUL bytes
from stdin to stdout (nor to the file), and may even drop entire chunks of
input in this case. Another issue is the inability to handle binary
streams.
 

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

Members online

Forum statistics

Threads
474,262
Messages
2,571,044
Members
48,769
Latest member
Clifft

Latest Threads

Top