strtok but keep the separator

S

Steven

I need a way to use strtok or some other function to parse a string but keep
the original separator.

My string that is delimited by commas and spaces and I need to format the
string for output so that there is no breaks on the tokens.

So (notice no spaces after the commas):
"Mary had a little lamb,sheep,goat,frog and a couple of other herding
animals"

would be displayed on a 20 character output area as:
12345678901234567890
"Mary had a little lamb,
sheep,goat,frog and a
couple of other herding
animals"

Thanks,
Steve
 
C

Charlie Gordon

Steven said:
I need a way to use strtok or some other function to parse a string but keep
the original separator.

My string that is delimited by commas and spaces and I need to format the
string for output so that there is no breaks on the tokens.

So (notice no spaces after the commas):
"Mary had a little lamb,sheep,goat,frog and a couple of other herding
animals"

would be displayed on a 20 character output area as:
12345678901234567890
"Mary had a little lamb,
sheep,goat,frog and a
couple of other herding
animals"

strtok() is not what you need for this, simple pointer pushing will do.

NEVER use strtok(), it is rubish left over for historical compatibility.
If you need its functionality, write your own function with proper semantics.
 
M

Michael Mair

Note: It is at best strange that you want _at_least_ 20 characters
instead of _at_most_. You may want to consider specifying ranges
like, say, 20-30 characters to avoid having lines breaking where
they should not.

Something along these lines may get you started:
_______________________________________________________________

#include <stdio.h>
#include <string.h>
#include <stdlib.h> /* Not needed for PrintStringLinewise() */

#define SEPARATORS " ,"
#define WHITESPACES " \n\t\r"

void PrintStringLinewise (const char *string, int linewidth,
int direction)
{
long int maxoffset;
int offset;
const char *searchpos;

direction = (direction < 0) ? -1 : 1;
maxoffset = (long int) strlen(string);
offset = 0;
searchpos = string;

while (offset < maxoffset) {
if ((offset = linewidth) > maxoffset) {
puts(searchpos);
break;
}
while (offset > 0 && searchpos[offset]) {
if (strchr(SEPARATORS, searchpos[offset]))
{
if (direction < 0) {
while (strchr(SEPARATORS, searchpos[offset]))
offset--;
offset++;
}
if (strchr(WHITESPACES, searchpos[offset]))
offset--;
break;
}
offset += direction;
}
if (searchpos[offset])
offset++;
if (offset == 1)
offset = linewidth;
printf("%.*s\n", offset, searchpos);
searchpos += offset;
maxoffset -= offset;
offset = 0;
/* Gobble blanks */
while (*searchpos && strchr(WHITESPACES, *searchpos)) {
maxoffset--;
searchpos++;
}
}
}

int main (int argc, char **argv)
{
int i, linewidth = 23;
const char *teststring =
"Mary had a little lamb,sheep,goat,frog and a couple"
" of other herding animals";
const char *teststring2 =
"veryveryveryveryveryveryveryveryveryveryveryveryvery"
"veryverylongstring";

if (argc>1)
linewidth = atoi(argv[1]);

for (i=1; i<=linewidth; i++)
putchar((i%10)+'0');
putchar('\n');
PrintStringLinewise(teststring, linewidth, -1);
for (i=1; i<=linewidth; i++)
putchar((i%10)+'0');
putchar('\n');
PrintStringLinewise(teststring, linewidth, +1);
for (i=1; i<=linewidth; i++)
putchar((i%10)+'0');
putchar('\n');
putchar('\n');
for (i=1; i<=linewidth; i++)
putchar((i%10)+'0');
putchar('\n');
PrintStringLinewise(teststring2, linewidth, -1);
for (i=1; i<=linewidth; i++)
putchar((i%10)+'0');
putchar('\n');
PrintStringLinewise(teststring2, linewidth, +1);
for (i=1; i<=linewidth; i++)
putchar((i%10)+'0');
putchar('\n');
return 0;
}
_______________________________________________________________

Note: I did not perform any tests apart from the ones visible
in main(), so check whether everything is as it should be.
You also might want to consider whether int/long int are
the appropriate types for linewidth, offset and maxoffset.
Comments are left as exercise to the reader.

strtok() is not what you need for this, simple pointer pushing will do.
Agreed.


NEVER use strtok(), it is rubish left over for historical compatibility.
If you need its functionality, write your own function with proper semantics.

If I know about the limitations of strtok() and if strtok() is
what I need, then I will use it.
However, as most newbies will get a piece of sample code and
"adapt" it for their purposes, yours is probably good advice
for them.

One "good" use of strtok() certainly is obfuscating... ;-)


Cheers
Michael
 
M

Martin Ambuhl

Steven said:
I need a way to use strtok or some other function to parse a string but keep
the original separator.

Copy the string; keep the original; work on the copy.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,156
Messages
2,570,878
Members
47,404
Latest member
PerryRutt

Latest Threads

Top