strtok() problem

E

ern

I'm using it like this:

char * _command = "one two three four";
char * g_UserCommands[4];
const char * delimeters = " ";
g_UserCommands[0] = strtok(_command, delimeters);
g_UserCommands[1] = strtok(g_UserCommands[0], delimeters);
g_UserCommands[2] = strtok(g_UserCommands[1], delimeters);
g_UserCommands[3] = strtok(g_UserCommands[2], delimeters);
//Then I print each entry of g_UserCommands.

When I run this thing, it will just print out one one one one...

I can't figure out what I'm doing wrong...
 
A

Alexei A. Frounze

ern said:
char * _command = "one two three four";
char * g_UserCommands[4];
const char * delimeters = " ";
g_UserCommands[0] = strtok(_command, delimeters);
g_UserCommands[1] = strtok(g_UserCommands[0], delimeters);
g_UserCommands[2] = strtok(g_UserCommands[1], delimeters);
g_UserCommands[3] = strtok(g_UserCommands[2], delimeters);
//Then I print each entry of g_UserCommands.

When I run this thing, it will just print out one one one one...

I can't figure out what I'm doing wrong...

1st call to strtok() is with ptr to the string to be parsed.
All subsequent calls to strtok() must be with NULL.
To begin parsing next string, use a new non-NULL ptr.

Read The Manual.

Alex
 
E

ern

Thanks. That worked. Actually, I did read the manual and couldn't
figure it out... thus the question.
 
F

Flash Gordon

It is best to avoid identifiers starting with an _. Some of them can be
used in some scopes, but it is far easier to completely avoid them that
to remember which ones can be used where.
char * g_UserCommands[4];
const char * delimeters = " ";
g_UserCommands[0] = strtok(_command, delimeters);
g_UserCommands[1] = strtok(g_UserCommands[0], delimeters);
g_UserCommands[2] = strtok(g_UserCommands[1], delimeters);
g_UserCommands[3] = strtok(g_UserCommands[2], delimeters);
//Then I print each entry of g_UserCommands.

When I run this thing, it will just print out one one one one...

I can't figure out what I'm doing wrong...

1st call to strtok() is with ptr to the string to be parsed.
All subsequent calls to strtok() must be with NULL.
To begin parsing next string, use a new non-NULL ptr.

Read The Manual.

Another problem is that strtok modifies the string it is tokenising and
the C standard forbids you from modifying string literals. Common
effects of this include the program aborting, finding that string
literals have been merged so when you change one instance all the others
change, and demons flying out of your nose and then slapping you with a
wet kipper.

*Never* pass a string literal to strtok and never try to modify a string
literal in any other way.

char command[] = "one two three four";

would have been far better.
 
D

Default User

ern said:
Thanks. That worked. Actually, I did read the manual and couldn't
figure it out... thus the question.

Please quote enough of the previous message to provide context. To do
so from Google, click "show options" and use the Reply shown in the
expanded header.


You have another big problem in your code:
char * _command = "one two three four";
g_UserCommands[0] = strtok(_command, delimeters);


You are trying to use strtok() on a string literal, which is undefined
behavior. That's because the function modifies the string. You can't do
that.

Replace the first line with:

char command[] = "one two three four"; /* leading underscores suck */




Brian
 
K

Keith Thompson

ern said:
I'm using it like this:

char * _command = "one two three four";
char * g_UserCommands[4];
const char * delimeters = " ";
g_UserCommands[0] = strtok(_command, delimeters);
g_UserCommands[1] = strtok(g_UserCommands[0], delimeters);
g_UserCommands[2] = strtok(g_UserCommands[1], delimeters);
g_UserCommands[3] = strtok(g_UserCommands[2], delimeters);
//Then I print each entry of g_UserCommands.

When I run this thing, it will just print out one one one one...

I can't figure out what I'm doing wrong...

In addition to the problem Alexei pointed out, you're modifying the
contents of a string literal, which invokes undefined behavior.
Change
char * _command = "one two three four";
to
char _command[] = "one two three four";

(But in a real program, you'll presumbly be getting the data from some
external source rather than a string literal.)

And using identifiers that start with an underscore is a bad idea;
many of them are reserved to the implementation. The rules are
slightly more complicated than that, but it's best just to avoid such
identifiers altogethers.
 
A

Alexei A. Frounze

....
Another problem is that strtok modifies the string it is tokenising and
the C standard forbids you from modifying string literals. Common
effects of this include the program aborting, finding that string
literals have been merged so when you change one instance all the others
change, and demons flying out of your nose and then slapping you with a
wet kipper.

*Never* pass a string literal to strtok and never try to modify a string
literal in any other way.

char command[] = "one two three four";

would have been far better.

You're right on that. That's safe. An array is guaranteed not to intersect
with some other array, while the string literals may be combined (if
identical) and reused and be indeed put into read-only part of address
space. I'm not doing much of the string/text processing, so to me this is
something I don't catch, unldss I really do need to something like this.

How much does it take one to find all the rope to shoot in the foot if
speaking C? A few intensive years of using and rediscovering C again and
again? :)

Alex
 
R

Randy Howard

Alexei A. Frounze wrote
(in article said:
How much does it take one to find all the rope to shoot in the foot if
speaking C?

I guess that depends upon how long it takes you to read K&R2,
the clc FAQ, and whether or not you learn from your mistakes on
the first, second, or any subsequent incidents.
 
G

Gregory Pietsch

ern said:
I'm using it like this:

char * _command = "one two three four";
char * g_UserCommands[4];
const char * delimeters = " ";
g_UserCommands[0] = strtok(_command, delimeters);
g_UserCommands[1] = strtok(g_UserCommands[0], delimeters);
g_UserCommands[2] = strtok(g_UserCommands[1], delimeters);
g_UserCommands[3] = strtok(g_UserCommands[2], delimeters);
//Then I print each entry of g_UserCommands.

When I run this thing, it will just print out one one one one...

I can't figure out what I'm doing wrong...

Try:

char *command = "one two three four";
char *g_UserCommands[4];
const char *delimiters = " ";
g_UserCommands[0] = strtok(command, delimiters);
g_UserCommands[1] = strtok(0, delimiters);
g_UserCommands[2] = strtok(0, delimiters);
g_UserCommands[3] = strtok(0, delimiters);

Gregory Pietsch
 
D

Default User

Gregory said:
Try:

char *command = "one two three four";
char *g_UserCommands[4];
const char *delimiters = " ";
g_UserCommands[0] = strtok(command, delimiters);

Undefined Behavior, attempt to modify a string literal. This has been
posted several times over the past day or so.



Brian
 
G

Gregory Pietsch

Default said:
Gregory said:
Try:

char *command = "one two three four";
char *g_UserCommands[4];
const char *delimiters = " ";
g_UserCommands[0] = strtok(command, delimiters);

Undefined Behavior, attempt to modify a string literal. This has been
posted several times over the past day or so.



Brian

Oops ... forgot about that.

#include <string.h>
char command[128];
strcpy(command, "one two three four");

Gregory Pietsch
 
K

Keith Thompson

Gregory Pietsch said:
Default said:
Gregory said:
Try:

char *command = "one two three four";
char *g_UserCommands[4];
const char *delimiters = " ";
g_UserCommands[0] = strtok(command, delimiters);

Undefined Behavior, attempt to modify a string literal. This has been
posted several times over the past day or so.

Oops ... forgot about that.

#include <string.h>
char command[128];
strcpy(command, "one two three four");

Or just:

char command[] = "one two three four";

But as I noted earlier, in a real-world program you're unlikely to
want to apply strtok() to constant data anyway.
 
D

Default User

Keith said:
Gregory Pietsch said:
Default said:
Gregory Pietsch wrote:
Try:

char *command = "one two three four";
char *g_UserCommands[4];
const char *delimiters = " ";
g_UserCommands[0] = strtok(command, delimiters);

Undefined Behavior, attempt to modify a string literal. This has
been >> posted several times over the past day or so.
Oops ... forgot about that.

#include <string.h>
char command[128];
strcpy(command, "one two three four");

Or just:

char command[] = "one two three four";

But as I noted earlier, in a real-world program you're unlikely to
want to apply strtok() to constant data anyway.


Probably so. It's still best to apply some safety measures if using
strtok() or use some other method that doesn't need to modify the input.


Brian
 

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

Similar Threads

strtok ( ) help 13
Using strcmp() after using strtok() 3
strtok problem 5
Problem with codewars. 5
Fibonacci 0
strtok() 13
strtok 7
cannot read after \n using strtok() 10

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top