help on this text file i/o code

Discussion in 'C Programming' started by c, Sep 26, 2007.

  1. c

    c Guest

    hi all
    i read this code from "sudoku.c", the source code for the console game
    sudoku on my ubuntu box.
    and i have some questions with the text i/o operations in this code.

    1)
    static char line[ 80 ];
    static char title[ 80 ];
    FILE * f; (has been initialised, i put it here for clarity)

    /* Skip lines until a '%' is found */
    line[ 0 ] = ' ';
    while( '%' != line[ 0 ] )
    if( 0 == fgets( line, sizeof( line ), f ) )
    return -1;

    here i am not sure of the use of fgets
    does it read from file line by line ? what keeps track of which line
    we will read next ?
    is there a sort of internal position marker ?



    2) the above code is followed by

    /* Read optional title, and removing trailing whitespace */
    for( p = line + 1 ; *p && isspace( *p ) ; ++p )
    ;

    if( *p )
    {
    for( q = title ; '\0' != ( *q++ = *p++ ) ; )
    ;
    --q;
    while( isspace( *--q ) )
    ;
    *++q = '\0';
    }
    else
    strcpy( title, "(untitled)" );

    i'm really confused about the pointer uses here
    and how this code achieves its function, namely, removing trailing
    whitespace

    btw: i'm not able to judge the coding style here, whether it's the
    right way to code in c. so any comments on that will be helpful too.
    also can anyone point me to some well commented and well coded
    opensource c program? i'm sure there's a lot out there
    thanks in advance
     
    c, Sep 26, 2007
    #1
    1. Advertising

  2. c

    Mark Bluemel Guest

    c wrote:
    > hi all
    > i read this code from "sudoku.c", the source code for the console game
    > sudoku on my ubuntu box.
    > and i have some questions with the text i/o operations in this code.
    >
    > 1)
    > static char line[ 80 ];
    > static char title[ 80 ];
    > FILE * f; (has been initialised, i put it here for clarity)
    >
    > /* Skip lines until a '%' is found */
    > line[ 0 ] = ' ';
    > while( '%' != line[ 0 ] )
    > if( 0 == fgets( line, sizeof( line ), f ) )
    > return -1;
    >
    > here i am not sure of the use of fgets


    If you are not sure about fgets() I suggest reading a book or an online
    tutorial - see the resources links from http://www.c-faq.com

    >
    > 2) the above code is followed by
    >
    > /* Read optional title, and removing trailing whitespace */
    > for( p = line + 1 ; *p && isspace( *p ) ; ++p )
    > ;


    skip over the leading '%' and any leading whitespace.

    > if( *p )


    If there's anything to be processed, i.e. we haven't reached the end of
    the input line.

    The pointer p points to our current position in the input line.

    The pointer q will be used to point to our position in the title buffer.

    > {
    > for( q = title ; '\0' != ( *q++ = *p++ ) ; )
    > ;


    Copy from after white space into "title".

    > --q;
    > while( isspace( *--q ) )
    > ;


    Work backwards over trailing whitespace

    > *++q = '\0';


    Terminate "title"

    > }
    > else
    > strcpy( title, "(untitled)" );
    >
    > i'm really confused about the pointer uses here
    > and how this code achieves its function, namely, removing trailing
    > whitespace


    It's probably not the clearest code for a newbie...
     
    Mark Bluemel, Sep 26, 2007
    #2
    1. Advertising

  3. c

    Army1987 Guest

    On Wed, 26 Sep 2007 09:23:33 +0000, c wrote:

    > hi all
    > i read this code from "sudoku.c", the source code for the console game
    > sudoku on my ubuntu box.
    > and i have some questions with the text i/o operations in this code.
    >
    > 1)
    > static char line[ 80 ];
    > static char title[ 80 ];
    > FILE * f; (has been initialised, i put it here for clarity)
    >
    > /* Skip lines until a '%' is found */
    > line[ 0 ] = ' ';
    > while( '%' != line[ 0 ] )
    > if( 0 == fgets( line, sizeof( line ), f ) )
    > return -1;
    >
    > here i am not sure of the use of fgets
    > does it read from file line by line ?

    Yes, it does (or better it reads up to sizeof(line) characters).
    > what keeps track of which line we will read next ?
    > is there a sort of internal position marker ?

    The same one which keeps track of which character we will read
    next using getc().
    >
    >
    > 2) the above code is followed by
    >
    > /* Read optional title, and removing trailing whitespace */
    > for( p = line + 1 ; *p && isspace( *p ) ; ++p )
    > ;

    This increments p until it points to non-whitespace.

    > if( *p )
    > {
    > for( q = title ; '\0' != ( *q++ = *p++ ) ; )
    > ;

    This copies bytes from p to q until they're nonzero...
    Now q points on the terminating null of title.
    > --q;

    And now to the last nonzero character of title.
    > while( isspace( *--q ) )
    > ;

    This decrements q until it points to non-whitespace...
    > *++q = '\0';

    And sets the next character to '\0', thus terminating the string.
    > }
    > else
    > strcpy( title, "(untitled)" );
    >
    > i'm really confused about the pointer uses here and how this code
    > achieves its function, namely, removing trailing whitespace

    See above.

    --
    Army1987 (Replace "NOSPAM" with "email")
    A hamburger is better than nothing.
    Nothing is better than eternal happiness.
    Therefore, a hamburger is better than eternal happiness.
     
    Army1987, Sep 26, 2007
    #3
  4. c

    Richard Guest

    c <> writes:

    > hi all
    > i read this code from "sudoku.c", the source code for the console game
    > sudoku on my ubuntu box.
    > and i have some questions with the text i/o operations in this code.
    >
    > 1)
    > static char line[ 80 ];
    > static char title[ 80 ];
    > FILE * f; (has been initialised, i put it here for clarity)
    >
    > /* Skip lines until a '%' is found */
    > line[ 0 ] = ' ';
    > while( '%' != line[ 0 ] )
    > if( 0 == fgets( line, sizeof( line ), f ) )
    > return -1;
    >
    > here i am not sure of the use of fgets
    > does it read from file line by line ? what keeps track of which line
    > we will read next ?
    > is there a sort of internal position marker ?


    Don't ask here for that - use google or your Ubuntu documentation and
    then ask if you are unsure. To the c library documentation:

    In Ubuntu (in a terminal)

    sudo apt-get install build-essential
    sudo apt-get install manpages-dev

    then

    info fgets


    >
    >
    >
    > 2) the above code is followed by
    >
    > /* Read optional title, and removing trailing whitespace */
    > for( p = line + 1 ; *p && isspace( *p ) ; ++p )
    > ;


    While there are valid characters (*p) and they are spaces (isspace) then
    move forward (++p). In other words the comment is wrong. It should say
    "remove prefix whitespace, read optional title and remove trailing white
    space" or similar.

    >
    > if( *p )
    > {
    > for( q = title ; '\0' != ( *q++ = *p++ ) ; )


    aargh. I detest it when the constant is first. Anyway .... copy the
    title into the title buffer pointed to by q including any trailing
    whitespace. He could have used strcpy.

    > ;
    > --q;


    look at last character+1 in the title.

    > while( isspace( *--q ) )
    > ;


    go back to find the first non white space

    > *++q = '\0';


    mark the end of the title.

    He could have done it a different way.

    1) find first non white space.

    2) keep copying char by char and maintaining a pointer to the last non
    whitespace character.

    e.g (2)

    while(((isspace(*p))?1:(lastPtr=q)) && (*q++=*p++));
    *++lastPtr='\0';

    I didn't test the above but would be interested in seeing it ripped apart
    by the standards commission :-; What the above says is (or is supposed
    to say)

    while we copy the string, if the character is not a white space then
    store a pointer to it so that we can later terminate the string after
    the last non white space. You would need NULL checks for lastptr I
    suspect. Anyway, just to get you thinking .....



    > }
    > else
    > strcpy( title, "(untitled)" );
    >
    > i'm really confused about the pointer uses here
    > and how this code achieves its function, namely, removing trailing
    > whitespace
    >
     
    Richard, Sep 26, 2007
    #4
  5. c

    c Guest

    On Sep 26, 12:07 pm, Richard <> wrote:
    > c <> writes:
    > > hi all
    > > i read this code from "sudoku.c", the source code for the console game
    > > sudoku on my ubuntu box.
    > > and i have some questions with the text i/o operations in this code.

    >
    > > 1)
    > > static char line[ 80 ];
    > > static char title[ 80 ];
    > > FILE * f; (has been initialised, i put it here for clarity)

    >
    > > /* Skip lines until a '%' is found */
    > > line[ 0 ] = ' ';
    > > while( '%' != line[ 0 ] )
    > > if( 0 == fgets( line, sizeof( line ), f ) )
    > > return -1;

    >
    > > here i am not sure of the use of fgets
    > > does it read from file line by line ? what keeps track of which line
    > > we will read next ?
    > > is there a sort of internal position marker ?

    >
    > Don't ask here for that - use google or your Ubuntu documentation and
    > then ask if you are unsure. To the c library documentation:
    >
    > In Ubuntu (in a terminal)
    >
    > sudo apt-get install build-essential
    > sudo apt-get install manpages-dev
    >
    > then
    >
    > info fgets
    >
    >
    >
    > > 2) the above code is followed by

    >
    > > /* Read optional title, and removing trailing whitespace */
    > > for( p = line + 1 ; *p && isspace( *p ) ; ++p )
    > > ;

    >
    > While there are valid characters (*p) and they are spaces (isspace) then
    > move forward (++p). In other words the comment is wrong. It should say
    > "remove prefix whitespace, read optional title and remove trailing white
    > space" or similar.
    >
    >
    >
    > > if( *p )
    > > {
    > > for( q = title ; '\0' != ( *q++ = *p++ ) ; )

    >
    > aargh. I detest it when the constant is first. Anyway .... copy the
    > title into the title buffer pointed to by q including any trailing
    > whitespace. He could have used strcpy.
    >
    > > ;
    > > --q;

    >
    > look at last character+1 in the title.
    >
    > > while( isspace( *--q ) )
    > > ;

    >
    > go back to find the first non white space
    >
    > > *++q = '\0';

    >
    > mark the end of the title.
    >
    > He could have done it a different way.
    >
    > 1) find first non white space.
    >
    > 2) keep copying char by char and maintaining a pointer to the last non
    > whitespace character.
    >
    > e.g (2)
    >
    > while(((isspace(*p))?1:(lastPtr=q)) && (*q++=*p++));
    > *++lastPtr='\0';
    >
    > I didn't test the above but would be interested in seeing it ripped apart
    > by the standards commission :-; What the above says is (or is supposed
    > to say)
    >
    > while we copy the string, if the character is not a white space then
    > store a pointer to it so that we can later terminate the string after
    > the last non white space. You would need NULL checks for lastptr I
    > suspect. Anyway, just to get you thinking .....
    >
    > > }
    > > else
    > > strcpy( title, "(untitled)" );

    >
    > > i'm really confused about the pointer uses here
    > > and how this code achieves its function, namely, removing trailing
    > > whitespace


    thanks a lot
    especially to richard's explanation, very clear
    one question though: why *p can be a test of valid character if(*p)
    what does the program mean by valid character ?
    thx again
     
    c, Sep 26, 2007
    #5
  6. c

    Army1987 Guest

    On Wed, 26 Sep 2007 12:07:01 +0200, Richard wrote:

    > c <> writes:


    >> if( *p )
    >> {
    >> for( q = title ; '\0' != ( *q++ = *p++ ) ; )

    >
    > aargh. I detest it when the constant is first. Anyway .... copy the
    > title into the title buffer pointed to by q including any trailing
    > whitespace. He could have used strcpy.

    Well, he needed the end of the copied string in q. Maybe strchr()
    after strcpy(), but why scan the string twice when you can scan
    it once?

    > He could have done it a different way.
    >
    > 1) find first non white space.
    >
    > 2) keep copying char by char and maintaining a pointer to the last non
    > whitespace character.
    >
    > e.g (2)
    >
    > while(((isspace(*p))?1:(lastPtr=q)) && (*q++=*p++));
    > *++lastPtr='\0';

    Good point, but how 'bout to write it in a clearer way?

    > I didn't test the above but would be interested in seeing it ripped
    > apart by the standards commission :-; What the above says is (or is
    > supposed to say)
    >
    > while we copy the string, if the character is not a white space then
    > store a pointer to it so that we can later terminate the string after
    > the last non white space. You would need NULL checks for lastptr I
    > suspect.

    Why? The string has at least a non-whitespace character, namely
    the null. Replace isspace(*p) with *p && isspace(*p) (just because
    the Standard doesn't forbid a locale to be so brain-dead to
    consider '\0' whitespace), and you're done.

    --
    Army1987 (Replace "NOSPAM" with "email")
    A hamburger is better than nothing.
    Nothing is better than eternal happiness.
    Therefore, a hamburger is better than eternal happiness.
     
    Army1987, Sep 26, 2007
    #6
  7. c

    pete Guest

    Richard wrote:
    >
    > c <> writes:


    > > here i am not sure of the use of fgets
    > > does it read from file line by line ? what keeps track of which line
    > > we will read next ?
    > > is there a sort of internal position marker ?


    It's called a "file position indicator".
    The file position indicator is one of the things
    recorded by the FILE type object associated with the stream.

    > Don't ask here for that


    Why not?

    --
    pete
     
    pete, Sep 26, 2007
    #7
  8. On Wed, 26 Sep 2007 13:39:22 -0000, c <> wrote:


    snip 100 lines

    >
    >thanks a lot


    Please trim the amount of quoted material to what is relevant to your
    addition.

    >especially to richard's explanation, very clear
    >one question though: why *p can be a test of valid character if(*p)
    >what does the program mean by valid character ?


    *p is the character that p points to. If that character is '\0', then
    it is the nul character that terminates the string. In that case, "if
    (*p)" will evaluate to false and the statement following the if will
    not execute.

    In many types of string processing, it is common not to include the
    terminal nul (such as strlen). In this case, the phrase "While there
    are valid characters" meant "until we reach the end of the string".


    Remove del for email
     
    Barry Schwarz, Sep 27, 2007
    #8
    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. Krish
    Replies:
    1
    Views:
    1,092
    =?Utf-8?B?Q3VydF9DIFtNVlBd?=
    Oct 20, 2005
  2. keithb
    Replies:
    1
    Views:
    941
    Bruce Barker
    Mar 29, 2006
  3. walterbyrd
    Replies:
    7
    Views:
    321
    Asun Friere
    May 17, 2007
  4. Bruno Desthuilliers
    Replies:
    4
    Views:
    553
    Paul McGuire
    Feb 9, 2009
  5. leo
    Replies:
    1
    Views:
    297
    Bob Lehmann
    Dec 5, 2005
Loading...

Share This Page