is there an easier way?
Giorgos Keramidas
keramida at ceid.upatras.gr
Tue Feb 19 00:45:09 UTC 2008
On 2008-02-18 15:03, Gary Kline <kline at thought.org> wrote:
>
> To my fellow C nerds,
>
> It's been a great manny years since I wrote this appended
> snippet. Now I can't remember why (of if ) I need all the
> strcpy() calls. Is there a simpler, more logical way of
> printing a bunch of string by snipping off the left-most?
>
> In short,, can anyone 'splain why strtok needs all this?
> #include <stdio.h>
> #include <string.h>
>
> main()
> {
> char *bp, buf[512], *tok, tstr[512];
> static char *delim=" ", s1[256]="abc def ghi jkl mno.";
>
> bp = strcpy(buf, tstr);
> strcpy(bp, s1); /* bp filled with writable mem works like this, too */
> while ((tok = strtok(bp, delim)) != NULL)
> {
> bp = NULL;
> printf("tok = [%s]\n", tok);
> }
> }
I don't know about `simpler', but the hardcoded `magic' numbers above,
like 256 and 512, make me nervous.
Another point which is worth noting is that you don't need to copy the
string at all, for one thing.
If you have a string defined like this:
const char *s = "hello world";
Then you can use a second pointer to point somewhere within that string
and print from that point:
const char *point = s + 7;
printf("%s\n", point);
So if you want to strip the first 'word' from a C string, you can do
this in the following steps:
[0] Get the initial string in your s1[] buffer, i.e.:
const char s1[] = "abc def ghi jkl mno.";
Note that if you use `s1[]' to define the string, the
compiler is smart enough to grab enough space for it. This
way you don't need all the `magic' numbers, like 256 and
512 in the original code.
[1] Find the first whitespace character in the string, using
strcspn() to match everything *except* a whitespace:
const char *p;
size_t num_chars;
num_chars = strcspn(s1, " \t");
p = s1 + num_chars;
[2] If the character pointed at by the new value of `p' is the
terminating '\0' character of the original string, you are
done; the original string contains a single word, so you
can skip it entirely.
if (*p == '\0') {
printf("\n");
return;
}
[3] Now you can use strspn(), which is the *inverse* operation,
to skip the whitespace characters you just found:
num_chars = strspn(p, " \t");
p += num_chars;
[4] If the character pointed at by the new value of `p' is the
terminating '\0' character of the original string, then you
hit the end of the string again, so there is no `second'
word; you can move on again:
if (*p == '\0') {
printf("\n");
return;
}
[5] If you are still around, then `p' now points right at the
beginning of the second word.
printf("%s\n", p);
return;
A sample function which returns a pointer to the second word of the
string you pass to it, could be something like this:
#include <stdlib.h>
#include <string.h>
#define SPACECHARS " \t"
char *
secondword(char *s)
{
size_t num_chars;
char *p;
if (s == NULL)
return NULL;
/*
* Skip any non-whitespace chars first.
*/
num_chars = strcspn(s, SPACECHARS);
p = s + num_chars;
if (*p == '\0')
return p;
/*
* Then skip whitespace, until we hit the end of the
* string, or we find the second word.
*/
num_chars = strspn(p, SPACECHARS);
p += num_chars;
/*
* Even if we just hit '\0' or a non-space, we can
* simply return whatever our next match character is.
* It's either going to end up being the start of an
* empty string, or the second word we wanted to find.
*/
return p;
}
More information about the freebsd-questions
mailing list