tags:

views:

109

answers:

4

Hi,

Right now I use:

    char    record[BUFLEN];
    if(fgets(record, BUFLEN, fp) != NULL) {

      /* some code */

    }

to get lines from input like:

city=Boston;name=Bob;age=35
city=New York;name=Michael;age=29

Can I use something else in C that would give me not entire lines until '\n' but separate pairs like: "city=Boston" then "name=Bob", etc?

+1  A: 

Check out the strtok() function. Successive calls will retrieve each token from the string.

Using your example:

char    record[BUFLEN];
if(fgets(record, BUFLEN, fp) != NULL) {
    char *token;

    token = strtok( record, ";" );
    while ( token != NULL )
    {
            doSomethingWith( token );
            token = strtok( NULL, ";" );
    }
}
Bob Kaufman
you would still have to read the full line then tokenize it. it kinda sounds like the OP doesn't want to read a full line of text in the first place.
dice
I was wrestling with that. Since you've provided an answer that satisfies that criterion, our OP has two contrasting viewpoints to consider, depending on how vital it is to avoid caching the entire line.
Bob Kaufman
+2  A: 

you could read it a byte at a time using fgetc.

read up till = into one array then up till ; in another

        do {
          c = fgetc (pFile);

          if (c == ';') 
          // etc

        } while (c != EOF);
dice
After additional consideration, I like your answer better than mine. I'm leaving mine in place as an alternative.
Bob Kaufman
A: 

You could possibly duplicate the functionality of fgets(), only have it "fget" by a delimiter you specify, rather than \n. Code would look something like (THIS IS PSEUDOCODE):

In this function, "DELIM" is the delimiter you want to use. rather than \n, it might be ;.

char *GOEfgets(char *buf, int BUFLEN, FILE *fp, char DELIM)
{
   int i = 0; /* counter */
   int character;

   while(character = fgetc(fp)) /* we get a char from the stream one at a time */
   {
      buf[i] = (char)character; /* store that character in the stream */

      if ((char)character == DELIM) /* if we run into our delimiter, we stop */
      {
         return buf;
      }
   }

}
rascher
+3  A: 

This looks like one of those relatively rare occasions when scanf() could be used.

You could try:

while (fscanf(fp, "%[^=]=%[^;]", name, value) == 2)
{
    if ((c = fgetc(fp)) == EOF)
        break;
    else if (c == ';')
        ...continue with same line...
    else if (c == '\n')
        ...wrap up current line...
    else
        ...congratulations - format error of some sort...
}

Alternatively, continue to use 'fgets()' but use 'sscanf()' in a loop similar to this.

Working demo code:

#include <stdio.h>
int main(void)
{
    char name[20];
    char value[20];

    while (fscanf(stdin, "%19[^=]=%19[^;]", name, value) == 2)
    {
        int c;
        if ((c = fgetc(stdin)) == EOF)
            break;
        else if (c == ';')
            printf("name = %s; value = %s\n", name, value);
        else if (c == '\n')
            printf("name = %s; value = %s\n", name, value);
        else
            fprintf(stderr, "Ooops!\n");
    }
    return(0);
}
Jonathan Leffler
+1 nice code, `scanf` is the right tool IMO too. Why would anyone implement manual parsing for such a simple case :)
AraK
+1 you've shown me just how rusty my C is.
dice