views:

334

answers:

4

It's been awhile since I worked with the standard C library's string parsing code (sprintf, atoi, etc).

My specific, current need is as follows:

advance_buf( const char*& buf, const char* removed_chars, int size );

It should advance the buf pointer to beyond the group of whitespace and copy the removed characters into removed_chars ... The size is to keep things safe.

Example before and after, state of buf and removed_chars:

  • Before: buf: "123 456 789", removed_chars: (empty or garbage).
  • After: buf: "456 789", removed_chars: "123".

I'm also interested in a succinct resource for functions of this sort.

+1  A: 

Sounds like strtok() and friends can do the job you want.

Michael Foukarakis
A: 

I would recommend having a look at the strspn() and strcspn() functions. The following will tell you how many characters there are until the next chunk of whitespace:

strcspn(string, " \t");

And the following will tell you how long a chunk of whitespace is:

strspn(string, " \t");

You can use those numbers to do this task fairly easily, and probably thread-safely if you need.

Chris Lutz
+1  A: 

This should be trivial:

const char * advance_buf(const char *buf, char *removed_chars, size_t size)
{
  /* Copy characters until whitespace found or buffer space runs out. */
  while(!isspace(*buf) && --size > 0)
    *removed_chars++ = *buf++;
  *removed_chars = '\0';

  /* Remove separating whitespace. */
  while(isspace(*buf))
    buf++;
  return buf;
}

I changed the signature a bit, to return the updated buf pointer.

unwind
I'm aware that the implementation is trivial, but I would prefer to use a standard c solution, if one exists.
Dan O
isblank() is C99-only, so isspace() would be a safer choice
qrdl
@qrdl: Thanks, I changed it to isspace().
unwind
+1  A: 

How about:

#define SPACE " \t"

const char *advance_buf(const char *buf, char *removed_chars, int size)
{
    buf += sprintf(removed_chars, "%.*s", min(size - 1, strcspn(buf, SPACE)), buf);
    return buf + strspn(buf, SPACE);
}

Note: if removed_chars fills up, the excess characters will not be removed from buf.

const char *buf = "123 456789 X"
char removed_chars[5];

// Before: buf: "123 456789 X", removed_chars: (empty).
buf = advance_buf(buf, removed_chars, sizeof (removed_chars));
// After: buf: "456789 X", removed_chars: "123".
buf = advance_buf(buf, removed_chars, sizeof (removed_chars));
// After: buf: "89 X", removed_chars: "4567".

Note 2: Although the sprintf call is safe because the "%.*s" guards against buffer overflow, some modern compilers generate warnings for any use of sprintf() and some company coding standards prohibit it. If so then it should trivial to substitute snprintf or sprintf_s.

finnw