Question on some C code that I saw

Discussion in 'C Programming' started by Chad, Nov 15, 2007.

  1. Chad

    Chad Guest

    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
     
    Chad, Nov 15, 2007
    #1
    1. Advertising

  2. Chad <> wrote:
    > 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.

    --
    Peter
     
    Peter Nilsson, Nov 15, 2007
    #2
    1. Advertising

  3. Chad

    santosh Guest

    In article
    <>,
    Chad <> wrote on Thursday 15 Nov 2007 8:34 am:

    > 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.
     
    santosh, Nov 15, 2007
    #3
  4. Chad

    Jack Klein Guest

    On Wed, 14 Nov 2007 19:04:18 -0800 (PST), Chad <>
    wrote in comp.lang.c:

    > 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?

    > Chad


    --
    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
     
    Jack Klein, Nov 15, 2007
    #4
  5. Chad

    Chad Guest

    On Nov 14, 7:46 pm, Jack Klein <> wrote:
    > On Wed, 14 Nov 2007 19:04:18 -0800 (PST), Chad <>
    > wrote in comp.lang.c:
    >
    >
    >
    > > 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?
    >
    > > Chad

    >
    > --
    > Jack Klein


    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.
     
    Chad, Nov 15, 2007
    #5
  6. Chad

    Chad Guest

    On Nov 14, 7:38 pm, santosh <> wrote:
    > In article
    > <>,
    > Chad <> wrote on Thursday 15 Nov 2007 8:34 am:
    >
    >
    >
    > > 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.
     
    Chad, Nov 15, 2007
    #6
  7. santosh <> writes:
    > In article
    > <>,
    > Chad <> wrote on Thursday 15 Nov 2007 8:34 am:
    >> 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).

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Looking for software development work in the San Diego area.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Nov 15, 2007
    #7
  8. Chad said:

    <snip>

    > 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."

    --
    Richard Heathfield <http://www.cpax.org.uk>
    Email: -http://www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999
     
    Richard Heathfield, Nov 15, 2007
    #8
  9. Peter Nilsson said:

    > Chad <> wrote:
    >> Someone had the following

    >
    > 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.

    --
    Richard Heathfield <http://www.cpax.org.uk>
    Email: -http://www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999
     
    Richard Heathfield, Nov 15, 2007
    #9
  10. Richard Heathfield <> wrote:
    > Peter Nilsson said:
    > > Chad <> wrote:
    > > > Someone had the following

    > >
    > > 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?


    Obviously I don't know for sure, but there's a 7 year old post
    that looks very very similar...

    <http://groups.google.com/group/comp.lang.c/msg/e27d3d60aed071ac>

    [I googled on the code comment.]

    --
    Peter
     
    Peter Nilsson, Nov 15, 2007
    #10
  11. Peter Nilsson said:
    > Richard Heathfield <> wrote:


    >> Where did the OP dig up this code?

    >
    > Obviously I don't know for sure, but there's a 7 year old post
    > that looks very very similar...
    >
    > <http://groups.google.com/group/comp.lang.c/msg/e27d3d60aed071ac>


    Yes, you seem to have a point. (And yes, the fflush(fp) is redundantly
    superfluous and unnecessary.)

    --
    Richard Heathfield <http://www.cpax.org.uk>
    Email: -http://www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999
     
    Richard Heathfield, Nov 15, 2007
    #11
  12. "santosh" <> a écrit dans le message de news:
    fhgf0h$bcs$...
    > In article
    > <>,
    > Chad <> wrote on Thursday 15 Nov 2007 8:34 am:
    >
    >> 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.

    --
    Chqrlie.
     
    Charlie Gordon, Nov 25, 2007
    #12
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. gavino
    Replies:
    0
    Views:
    439
    gavino
    Aug 15, 2006
  2. vasudevram
    Replies:
    0
    Views:
    352
    vasudevram
    Dec 24, 2006
  3. HEBAbrothers

    Saw children in the face of tanks

    HEBAbrothers, Jan 10, 2009, in forum: C Programming
    Replies:
    0
    Views:
    417
    HEBAbrothers
    Jan 10, 2009
  4. HEBAbrothers

    Saw children in the face of tanks

    HEBAbrothers, Jan 10, 2009, in forum: Python
    Replies:
    0
    Views:
    323
    HEBAbrothers
    Jan 10, 2009
  5. Alont
    Replies:
    23
    Views:
    400
    Ben Morrow
    Aug 23, 2004
Loading...

Share This Page