Thread: New stream flushing FAQ candidate?

  1. #1
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708

    Question New stream flushing FAQ candidate?

    I've run a few tests on this and it appears to flush both input and output streams, but I've only tried it on Windows systems. Could someone test this out on other systems (ie: Linux, Mac, etc) to see how well it fares in portability? If it does, I'll ask the admins to add this to the FAQ. Thanks.

    Code:
    #include <stdio.h>
    
    int flush( FILE* stream )
    {
        return fseek( stream, 0, SEEK_END ) == 0;
    }
    
    int get( void )
    {
        flush( stdin );    
        return fgetc( stdin );
    }
    
    int main( int argc, char** argv )
    {
        int
            ch;
        FILE*
            out = 0;
        if( argc == 1 )
            fprintf( stderr, "Stream Flush Test Usage: %s [output_files]\n", *argv );    
        else 
        {
            while( *( ++argv ) )
            {
                out = fopen( *argv, "a" );
                if( out == 0 )
                    fprintf( stderr, "Error: could not open output file '%s'\n", *argv );    
                else
                {
                    printf( "Enter a string of characters > " );
                    get( );
                    printf( "Enter a character not in the set above > " );
                    ch = get( );
                    printf( "Sending character '%c' to output stream\n", ch );
                    fputc( ch, out );
                    printf( "Press [ENTER] to flush the output stream > " );
                    get( );
                    flush( out );
                    fclose( out );
                }
            }
            printf( "Press [ENTER] after verifying output >" );
            get( );
        }    
        return 0;
    }
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  2. #2
    Registered User
    Join Date
    Sep 2001
    Posts
    4,912
    Problem on Linux (Ubuntu 9.04, gcc 4.3): When asked to enter a string of characters, I do so and press enter. The second character I typed is then automatically used as input at the next prompt, and the remaining prompts are displayed without me doing anything. (That second character is written to the output file)

  3. #3
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    What are you running on Windows? The fseek returns -1 in both VS9 and MinGW 3.4.5 for me with perror blaming "invalid file descriptor" in both cases.

    It has the effects of working since the MS CRT does what is essentially a fflush operation regardless of whether the seeking actually succeeded or not. Given the -1 return, I wouldn't rely on it always being that way.

  4. #4
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> What are you running on Windows? The fseek returns -1 in both VS9 and MinGW 3.4.5 for me with perror blaming "invalid file descriptor" in both cases.

    I've read that the return value isn't always correct under Windows, so I just ignored it.

    After mulling through the standard, though, it turns out that the behavior isn't clearly described for all streams, so it's essentially implementation defined. Incidentally, I realized that you wouldn't necessarily want to reposition an output stream's file pointer to the end just to flush it, so the idea was flawed, anyway.

    Well, just out of curiosity, then, how well do these work (understanding that they aren't actually standard compliant, of course):

    Code:
    void flush2( FILE* stream )
    {
    	long int
    		position = ftell( stream );	
    	if( fseek( stream, 0, SEEK_END ) == 0 )
    		fseek( stream, position, SEEK_SET );
    	else if( position >= 0 )
    		while( fgetc( stream ) != EOF )
    			continue;
    }
    
    void flush3( FILE* stream )
    {
    	setvbuf( stream, NULL, _IONBF, 0 );
    	setvbuf( stream, NULL, _IOFBF, BUFSIZ );
    }
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  5. #5
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    I know there's something weird about using fseek with some streams, I'm just too tired right now to remember what it is. You can't fseek std...something...out I think. Like I said, I'm too tired to rememb exactly what the issue is.


    Quzah.
    Hope is the first step on the road to disappointment.

  6. #6
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> You can't fseek std...something...out I think.

    Well, as far as the standard goes, it doesn't explicitly dictate the required behavior, the wording used being something to the effect of "...streams that support the operation..." which leaves a lot of room for interpretation.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Whilst the standard may not specify when or under what situation fseek will or won't work. But if you read the underlaying SetFilePosition or lseek() functions, I'm pretty sure you'll find that it explicitly says "only works for files that are REAL FILES, not console or pipes" (probably stated in a different way, I'm paraphrasing).

    Whilst what you are doing MAY work in some situations, it's definitely not guaranteed any more than fflush(stdin) is. It may just happen to work in a DIFFERENT set of systems, but it's still not reliable or working.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    The setvbuf approach also "works" for stdin though the MS docs say:
    Quote Originally Posted by http://msdn.microsoft.com/en-us/library/86cebhfs(VS.100).aspx
    stream must refer to an open file that has not undergone an I/O operation since it was opened.
    Though it hasn't been enforced in any way since at least VC6.

  9. #9
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> Whilst what you are doing MAY work in some situations, it's definitely not guaranteed any more than fflush(stdin) is. It may just happen to work in a DIFFERENT set of systems, but it's still not reliable or working.

    You're right, of course - I was just looking for something that worked in 'most' situations, but then I guess that really is kind of pointless, isn't it?
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  10. #10
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> The setvbuf approach also "works" for stdin though the MS docs say: "stream must refer to an open file that has not undergone an I/O operation since it was opened".

    Yeah, that's basically why I didn't suggest it as a 'real' solution. Another potential problem (possibly) is that BUFSIZ may well be a very non-optimal size for the buffer, and unfortunately, AFAIK there's no way to check the old value beforehand. Besides that, it seems to me a little extreme to have to turn on and off buffering like that just to flush a stream.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Discard wrong data from stream
    By mesmer in forum C Programming
    Replies: 7
    Last Post: 11-16-2008, 02:30 AM
  2. if statement is evaluating incorrectly ...
    By Niss in forum C Programming
    Replies: 3
    Last Post: 09-12-2008, 04:39 PM
  3. Wiki FAQ
    By dwks in forum A Brief History of Cprogramming.com
    Replies: 192
    Last Post: 04-29-2008, 01:17 PM
  4. Help! About text stream and binary stream
    By Antigloss in forum C Programming
    Replies: 1
    Last Post: 09-01-2005, 08:40 AM
  5. FAQ Check/Lock
    By RoD in forum A Brief History of Cprogramming.com
    Replies: 2
    Last Post: 10-15-2002, 11:21 AM