How to read strings from a file with comments

Discussion in 'C Programming' started by I. Myself, Apr 9, 2006.

  1. I. Myself

    I. Myself Guest

    This is about reading the .ini files which are used in several of our
    projects.

    Currently, the actual read of each line of the file is with this statement:

    fscanf(file, "%s %s", name, value); /* reads two strings from .ini
    file */

    This works, but it does not allow any comments to the right of the two
    strings.
    I would like to allow the .ini file to have long comments on the right.
    Even better would be to allow additional lines of commentary also. The
    computer should ignore the commentary, and just read the initial two
    strings on each line.

    Can anyone tell me how to do it?

    Thanks,

    Mitchell Timin

    --
    I'm proud of http://ANNEvolve.sourceforge.net. If you want to write software,
    or articles, or do testing or research for ANNEvolve, let me know.

    Humans may know that my email address is: (but remove the 3 digit number)
    zenguy at shaw666 dot ca
    I. Myself, Apr 9, 2006
    #1
    1. Advertising

  2. I. Myself

    Ian Collins Guest

    I. Myself wrote:
    > This is about reading the .ini files which are used in several of our
    > projects.
    >
    > Currently, the actual read of each line of the file is with this statement:
    >
    > fscanf(file, "%s %s", name, value); /* reads two strings from .ini
    > file */
    >
    > This works, but it does not allow any comments to the right of the two
    > strings.
    > I would like to allow the .ini file to have long comments on the right.
    > Even better would be to allow additional lines of commentary also. The
    > computer should ignore the commentary, and just read the initial two
    > strings on each line.
    >
    > Can anyone tell me how to do it?
    >

    Read the full line and check the first character (assuming you use
    something like '#' for a comment marker). If it is a comment, ignore
    the line, else replace your fscanf with scanf on the line you have just
    read.

    --
    Ian Collins.
    Ian Collins, Apr 9, 2006
    #2
    1. Advertising

  3. On Sun, 09 Apr 2006 21:04:40 GMT, in comp.lang.c , "I. Myself"
    <> wrote:

    >Currently, the actual read of each line of the file is with this statement:
    >
    >fscanf(file, "%s %s", name, value); /* reads two strings from .ini
    >file */
    >
    >This works, but it does not allow any comments to the right of the two
    >strings.


    Presumably you plan to delimit the comment somehow

    SETTING=wibble #this bit is a comment

    if so, use fgets() to read the line, then read up on sscanf() and
    strchr().
    Mark McIntyre
    --
    "Debugging is twice as hard as writing the code in the first place.
    Therefore, if you write the code as cleverly as possible, you are,
    by definition, not smart enough to debug it."
    --Brian Kernighan
    Mark McIntyre, Apr 9, 2006
    #3
  4. I. Myself

    CBFalconer Guest

    "I. Myself" wrote:
    >
    > This is about reading the .ini files which are used in several of
    > our projects.
    >
    > Currently, the actual read of each line of the file is with this
    > statement:
    >
    > fscanf(file, "%s %s", name, value); /* reads two strings from
    > .ini file */
    >
    > This works, but it does not allow any comments to the right of the
    > two strings. I would like to allow the .ini file to have long
    > comments on the right. Even better would be to allow additional
    > lines of commentary also. The computer should ignore the
    > commentary, and just read the initial two strings on each line.
    >
    > Can anyone tell me how to do it?


    You can see a method in my id2id-20, function readidpairs. In
    essence it is the following:

    do {
    ch = getident(leftwd, BUFMAX, idp, NULL);
    ch = getident(rightwd, BUFMAX, idp, NULL);
    ch = flushln(idp);
    /* code to process the id pair */
    } while (EOF != ch);

    which needs the code for getident and flushln (both present). You
    can get the complete package and source at:

    <http://cbfalconer.home.att.net/download/id2id-20.zip>

    --
    "If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers." - Keith Thompson
    More details at: <http://cfaj.freeshell.org/google/>
    Also see <http://www.safalra.com/special/googlegroupsreply/>
    CBFalconer, Apr 9, 2006
    #4
  5. I. Myself

    Joe Estock Guest

    I. Myself wrote:
    > This is about reading the .ini files which are used in several of our
    > projects.


    There are many pre-written utilities written in c which conform to the c
    standards. Try a search on google, or if you prefer to use a home-rolled
    version see below.

    >
    > Currently, the actual read of each line of the file is with this statement:
    >
    > fscanf(file, "%s %s", name, value); /* reads two strings from .ini
    > file */


    fscanf wouldn't be my first choice for this.

    >
    > This works, but it does not allow any comments to the right of the two
    > strings.
    > I would like to allow the .ini file to have long comments on the right.


    This is rather trivial to accomplish. Read in one line of text (using
    fgets perhaps). Pass a pointer to the buffer containing that line of
    text to a new function you write (perhaps called remove_comments). Below
    is an untested example. This assumes that your comments begin with the
    '#' character and continue until EOL.

    /**
    * Remove comments denoted with a preceding '#' in a given string
    *
    * @param buffer Pointer to a string in which to remove comments from
    * @return New length of string
    */
    size_t remove_comments(char **buffer)
    {
    char *p;

    if(strchr(p, '#') == NULL)
    return(0); /* no comment found */

    for(p = *buffer; p != '\0' && p != '#'; p++) ;

    /* at this point, *p should be either '#' or '\0' */
    *p = '\0';

    return(strlen(p));
    }

    > Even better would be to allow additional lines of commentary also. The
    > computer should ignore the commentary, and just read the initial two
    > strings on each line.


    Ignoring multiple lines of comments would be a little more tricky, but
    it certainly could be done. I'll leave you with finding a solution for
    this task. The only thing you will need to do now is check for an empty
    string after calling the above function. Additionally you can also
    implement some sort of a trim function which removes all leading and
    trailing whitespace from a given string.

    >
    > Can anyone tell me how to do it?
    >
    > Thanks,
    >
    > Mitchell Timin
    >


    You're welcome and I hope that points you in the right direction. Again,
    note that the above code is untested (however it should work).

    Joe
    Joe Estock, Apr 10, 2006
    #5
  6. Ian Collins <> writes:
    [...]
    > Read the full line and check the first character (assuming you use
    > something like '#' for a comment marker). If it is a comment, ignore
    > the line, else replace your fscanf with scanf on the line you have just
    > read.


    I think you mean sscanf, not scanf.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Keith Thompson, Apr 10, 2006
    #6
  7. I. Myself

    Ian Collins Guest

    Keith Thompson wrote:
    > Ian Collins <> writes:
    > [...]
    >
    >>Read the full line and check the first character (assuming you use
    >>something like '#' for a comment marker). If it is a comment, ignore
    >>the line, else replace your fscanf with scanf on the line you have just
    >>read.

    >
    >
    > I think you mean sscanf, not scanf.
    >

    Well spotted.

    --
    Ian Collins.
    Ian Collins, Apr 10, 2006
    #7
  8. I. Myself

    Guest

    Ο/Η Joe Estock έγÏαψε:
    > I. Myself wrote:
    > > This is about reading the .ini files which are used in several of our
    > > projects.

    >
    > There are many pre-written utilities written in c which conform to the c
    > standards. Try a search on google, or if you prefer to use a home-rolled
    > version see below.
    >
    > >
    > > Currently, the actual read of each line of the file is with this statement:
    > >
    > > fscanf(file, "%s %s", name, value); /* reads two strings from .ini
    > > file */

    >
    > fscanf wouldn't be my first choice for this.
    >
    > >
    > > This works, but it does not allow any comments to the right of the two
    > > strings.
    > > I would like to allow the .ini file to have long comments on the right.

    >
    > This is rather trivial to accomplish. Read in one line of text (using
    > fgets perhaps). Pass a pointer to the buffer containing that line of
    > text to a new function you write (perhaps called remove_comments). Below
    > is an untested example. This assumes that your comments begin with the
    > '#' character and continue until EOL.
    >
    > /**
    > * Remove comments denoted with a preceding '#' in a given string
    > *
    > * @param buffer Pointer to a string in which to remove comments from
    > * @return New length of string
    > */
    > size_t remove_comments(char **buffer)
    > {
    > char *p;
    >
    > if(strchr(p, '#') == NULL)
    > return(0); /* no comment found */
    >
    > for(p = *buffer; p != '\0' && p != '#'; p++) ;
    >
    > /* at this point, *p should be either '#' or '\0' */
    > *p = '\0';
    >
    > return(strlen(p));
    > }


    Maybe a better (and working) version would be:

    size_t remove_comments(char *buffer)
    {
    char *p;

    if(strchr(buffer, '#') == NULL)
    return strlen(buffer); /* no comment found */

    for(p = buffer; *p != '\0' && *p != '#'; p++) ;

    /* at this point, *p should be either '#' or '\0' */
    *p = '\0';

    return strlen(p);
    }

    And one could even avoid the final strlen() call by calculating the
    string length in the previous loop.
    , Apr 10, 2006
    #8
  9. On Sun, 09 Apr 2006 23:25:10 GMT, Joe Estock wrote:
    >/**
    > * Remove comments denoted with a preceding '#' in a given string
    > *
    > * @param buffer Pointer to a string in which to remove comments from
    > * @return New length of string
    > */
    >size_t remove_comments(char **buffer)
    >{
    > char *p;
    >
    > if(strchr(p, '#') == NULL)
    > return(0); /* no comment found */
    >
    > for(p = *buffer; p != '\0' && p != '#'; p++) ;
    >
    > /* at this point, *p should be either '#' or '\0' */
    > *p = '\0';
    >
    > return(strlen(p));
    >}


    if *p==0 then strlen(p)==0
    RSoIsCaIrLiIoA, Apr 10, 2006
    #9
  10. <> wrote in message
    news:...

    Ï/Ç Joe Estock Ýãñáøå:
    > I. Myself wrote:
    > > This is about reading the .ini files which are used in several of our
    > > projects.

    >
    > There are many pre-written utilities written in c which conform to the c
    > standards. Try a search on google, or if you prefer to use a home-rolled
    > version see below.
    >
    > >
    > > Currently, the actual read of each line of the file is with this

    statement:
    > >
    > > fscanf(file, "%s %s", name, value); /* reads two strings from .ini
    > > file */

    >
    > fscanf wouldn't be my first choice for this.
    >
    > >
    > > This works, but it does not allow any comments to the right of the two
    > > strings.
    > > I would like to allow the .ini file to have long comments on the right.

    >
    > This is rather trivial to accomplish. Read in one line of text (using
    > fgets perhaps). Pass a pointer to the buffer containing that line of
    > text to a new function you write (perhaps called remove_comments). Below
    > is an untested example. This assumes that your comments begin with the
    > '#' character and continue until EOL.
    >
    > /**
    > * Remove comments denoted with a preceding '#' in a given string
    > *
    > * @param buffer Pointer to a string in which to remove comments from
    > * @return New length of string
    > */
    > size_t remove_comments(char **buffer)
    > {
    > char *p;
    >
    > if(strchr(p, '#') == NULL)
    > return(0); /* no comment found */
    >
    > for(p = *buffer; p != '\0' && p != '#'; p++) ;
    >
    > /* at this point, *p should be either '#' or '\0' */
    > *p = '\0';
    >
    > return(strlen(p));
    > }


    Maybe a better (and working) version would be:

    size_t remove_comments(char *buffer)
    {
    char *p;

    if(strchr(buffer, '#') == NULL)
    return strlen(buffer); /* no comment found */

    for(p = buffer; *p != '\0' && *p != '#'; p++) ;

    /* at this point, *p should be either '#' or '\0' */
    *p = '\0';

    return strlen(buffer);
    }
    stathis gotsis, Apr 10, 2006
    #10
  11. I. Myself

    Ben C Guest

    On 2006-04-10, stathis gotsis <> wrote:
    ><> wrote in message
    > news:...
    >
    >> /**
    >> * Remove comments denoted with a preceding '#' in a given string
    >> *
    >> * @param buffer Pointer to a string in which to remove comments from
    >> * @return New length of string
    >> */


    >> [...]


    > Maybe a better (and working) version would be:
    >
    > size_t remove_comments(char *buffer)
    > {
    > char *p;
    >
    > if(strchr(buffer, '#') == NULL)
    > return strlen(buffer); /* no comment found */
    >
    > for(p = buffer; *p != '\0' && *p != '#'; p++) ;
    >
    > /* at this point, *p should be either '#' or '\0' */
    > *p = '\0';
    >
    > return strlen(buffer);
    > }


    Or instead of "return strlen(buffer)", just

    return p - buffer;

    which is a bit more efficient (strlen will scan all the way from start
    to end to find the NUL).
    Ben C, Apr 10, 2006
    #11
  12. I. Myself

    Ben C Guest

    On 2006-04-10, stathis gotsis <> wrote:
    ><> wrote in message
    > news:...
    >> /**
    >> * Remove comments denoted with a preceding '#' in a given string
    >> *
    >> * @param buffer Pointer to a string in which to remove comments from
    >> * @return New length of string
    >> */


    >> [..]


    > Maybe a better (and working) version would be:
    >
    > size_t remove_comments(char *buffer)
    > {
    > char *p;
    >
    > if(strchr(buffer, '#') == NULL)
    > return strlen(buffer); /* no comment found */
    >
    > for(p = buffer; *p != '\0' && *p != '#'; p++) ;
    >
    > /* at this point, *p should be either '#' or '\0' */
    > *p = '\0';
    >
    > return strlen(buffer);
    > }


    Well, or just do it like this:

    size_t remove_comments(char *buffer)
    {
    char *p = strchr(buffer, '#');
    if (p != NULL) *p = '\0';

    return strlen(buffer);
    }
    Ben C, Apr 10, 2006
    #12
  13. "Ben C" <> wrote in message
    news:...
    > On 2006-04-10, stathis gotsis <> wrote:
    > ><> wrote in message
    > > news:...
    > >> /**
    > >> * Remove comments denoted with a preceding '#' in a given string
    > >> *
    > >> * @param buffer Pointer to a string in which to remove comments from
    > >> * @return New length of string
    > >> */

    >
    > >> [..]

    >
    > > Maybe a better (and working) version would be:
    > >
    > > size_t remove_comments(char *buffer)
    > > {
    > > char *p;
    > >
    > > if(strchr(buffer, '#') == NULL)
    > > return strlen(buffer); /* no comment found */
    > >
    > > for(p = buffer; *p != '\0' && *p != '#'; p++) ;
    > >
    > > /* at this point, *p should be either '#' or '\0' */
    > > *p = '\0';
    > >
    > > return strlen(buffer);
    > > }

    >
    > Well, or just do it like this:
    >
    > size_t remove_comments(char *buffer)
    > {
    > char *p = strchr(buffer, '#');
    > if (p != NULL) *p = '\0';
    >
    > return strlen(buffer);
    > }


    Thanks for the suggestion, i got stuck on correcting the initial code, and
    as a result i made one more mistake and missed the obvious. Too bad.
    stathis gotsis, Apr 10, 2006
    #13
  14. On Mon, 10 Apr 2006 20:57:06 +0300,
    stathis gotsis <> wrote
    in Msg. <e1e696$2jfa$>

    > Maybe a better (and working) version would be:
    >
    > size_t remove_comments(char *buffer)
    > {
    > char *p;
    >
    > if(strchr(buffer, '#') == NULL)
    > return strlen(buffer); /* no comment found */
    >
    > for(p = buffer; *p != '\0' && *p != '#'; p++) ;
    >
    > /* at this point, *p should be either '#' or '\0' */
    > *p = '\0';
    >
    > return strlen(buffer);
    > }


    How about just:

    strtok(buffer, "#");

    robert
    Robert Latest, Apr 11, 2006
    #14
  15. "Robert Latest" <> wrote in message
    news:...
    > On Mon, 10 Apr 2006 20:57:06 +0300,
    > stathis gotsis <> wrote
    > in Msg. <e1e696$2jfa$>
    >
    > > Maybe a better (and working) version would be:
    > >
    > > size_t remove_comments(char *buffer)
    > > {
    > > char *p;
    > >
    > > if(strchr(buffer, '#') == NULL)
    > > return strlen(buffer); /* no comment found */
    > >
    > > for(p = buffer; *p != '\0' && *p != '#'; p++) ;
    > >
    > > /* at this point, *p should be either '#' or '\0' */
    > > *p = '\0';
    > >
    > > return strlen(buffer);
    > > }

    >
    > How about just:
    >
    > strtok(buffer, "#");


    I tend to avoid strtok() in general, but it can work in simple cases like
    this one.
    stathis gotsis, Apr 11, 2006
    #15
  16. I. Myself

    WaterWalk Guest

    I. Myself 写é“:

    > This is about reading the .ini files which are used in several of our
    > projects.
    >
    > Currently, the actual read of each line of the file is with this statement:
    >
    > fscanf(file, "%s %s", name, value); /* reads two strings from .ini
    > file */
    >
    > This works, but it does not allow any comments to the right of the two
    > strings.
    > I would like to allow the .ini file to have long comments on the right.
    > Even better would be to allow additional lines of commentary also. The
    > computer should ignore the commentary, and just read the initial two
    > strings on each line.
    >
    > Can anyone tell me how to do it?
    >
    > Thanks,
    >
    > Mitchell Timin
    >
    > --
    > I'm proud of http://ANNEvolve.sourceforge.net. If you want to write software,
    > or articles, or do testing or research for ANNEvolve, let me know.
    >
    > Humans may know that my email address is: (but remove the 3 digit number)
    > zenguy at shaw666 dot ca


    Those suggestions are all good in simple situations. But what if there
    are comment indicator such as "#" inside the "Key=Value" pair? For
    example: Val1="ab#3". Then to simply search the "#" symbol and discard
    the right part won't work. So I intend to put comment in a separate
    line. This makes things simple.
    WaterWalk, Apr 12, 2006
    #16
    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. Replies:
    0
    Views:
    1,095
  2. Monk
    Replies:
    10
    Views:
    1,438
    Michael Wojcik
    Apr 20, 2005
  3. Ben

    Strings, Strings and Damned Strings

    Ben, Jun 22, 2006, in forum: C Programming
    Replies:
    14
    Views:
    739
    Malcolm
    Jun 24, 2006
  4. Alex Dowad
    Replies:
    4
    Views:
    258
    Michel Demazure
    May 1, 2010
  5. Replies:
    4
    Views:
    575
    Dr John Stockton
    Jun 3, 2006
Loading...

Share This Page