Why occur the mistake in runtime about strtok()?

H

hu

hi, everybody!
I'm testing the fuction of strtok(). The environment is WinXP, VC++6.0.
Program is simple, but mistake is confusing. First, the below code can get
right outcome:"ello world, hello dreams."

#include <stdafx.h>
#include <string.h>
#include <stdio.h>

int main()
{
char *pStr = "Hello world, hello dreams.";
char *p = pStr;
p = strtok(pStr, "H");
if (NULL==p)
printf("null__");
else
printf("%s", p);

return (0);
}

Second, Changing the sentence:
p = strtok(pStr, "H");
to
p = strtok(pStr, "Ho");
It can be compiled, but cannot run!

Third, Changing the sentence:
p = strtok(pStr, "H");
to
p = strtok(pStr, "e");
It can be compiled, but cannot run too!

Where is the wrong?
thanks!
 
I

Ian Collins

hu said:
hi, everybody!
I'm testing the fuction of strtok(). The environment is WinXP, VC++6.0.
Program is simple, but mistake is confusing. First, the below code can get
right outcome:"ello world, hello dreams."

#include <stdafx.h>
#include <string.h>
#include <stdio.h>

int main()
{
char *pStr = "Hello world, hello dreams.";
char *p = pStr;
p = strtok(pStr, "H");

This invokes undefined behaviour, you are calling strtok with a string
literal. strtok overwrites the string you pass it, doing this with a
literal is undefined.
 
K

Keith Thompson

hu said:
I'm testing the fuction of strtok(). The environment is WinXP, VC++6.0.
Program is simple, but mistake is confusing. First, the below code can get
right outcome:"ello world, hello dreams."

#include <stdafx.h>
#include <string.h>
#include <stdio.h>

int main()
{
char *pStr = "Hello world, hello dreams.";
char *p = pStr;
p = strtok(pStr, "H");
if (NULL==p)
printf("null__");
else
printf("%s", p);

return (0);
}

Second, Changing the sentence:
p = strtok(pStr, "H");
to
p = strtok(pStr, "Ho");
It can be compiled, but cannot run!

Third, Changing the sentence:
p = strtok(pStr, "H");
to
p = strtok(pStr, "e");
It can be compiled, but cannot run too!

Where is the wrong?

Three things. First, you're using a non-standard header <stdafx.h>.
Second, you're trying to modify a string literal (that's your real
problem). Third, you're you're not telling us how it fails; "cannot
run" wouldn't have given us much information if the actual problem
didn't happen to be obvious.
 
H

hu

the strtok() declaration:
char * strtok(char *p1, const char*p2);
The strtok() can overwrite *p1? And what it overwirte the content of p1
with?

thanks!
 
P

pete

hu said:
the strtok() declaration:
char * strtok(char *p1, const char*p2);
The strtok() can overwrite *p1?
And what it overwirte the content of p1 with?

You seem to have no idea of what strtok does.

N869
7.21.5.8 The strtok function
Synopsis
[#1]
#include <string.h>
char *strtok(char * restrict s1,
const char * restrict s2);
Description
[#2] A sequence of calls to the strtok function breaks the
string pointed to by s1 into a sequence of tokens, each of
which is delimited by a character from the string pointed to
by s2. The first call in the sequence has a non-null first
argument; subsequent calls in the sequence have a null first
argument. The separator string pointed to by s2 may be
different from call to call.
[#3] The first call in the sequence searches the string
pointed to by s1 for the first character that is not
contained in the current separator string pointed to by s2.
If no such character is found, then there are no tokens in
the string pointed to by s1 and the strtok function returns
a null pointer. If such a character is found, it is the
start of the first token.
[#4] The strtok function then searches from there for a
character that is contained in the current separator string.
If no such character is found, the current token extends to
the end of the string pointed to by s1, and subsequent
searches for a token will return a null pointer. If such a
character is found, it is overwritten by a null character,
which terminates the current token. The strtok function
saves a pointer to the following character, from which the
next search for a token will start.
[#5] Each subsequent call, with a null pointer as the value
of the first argument, starts searching from the saved
pointer and behaves as described above.
[#6] The implementation shall behave as if no library
function calls the strtok function.
Returns
[#7] The strtok function returns a pointer to the first
character of a token, or a null pointer if there is no
token.
[#8] EXAMPLE 1
#include <string.h>
static char str[] = "?a???b,,,#c";
char *t;
t = strtok(str, "?"); // t points to the token "a"
t = strtok(NULL, ","); // t points to the token "??b"
t = strtok(NULL, "#,"); // t points to the token "c"
t = strtok(NULL, "?"); // t is a null pointer
 
H

hu

I said "can not run", I mean that when I start the program, WindowsXP pop a
illegal operation dialog box.

thanks a lot.
 
C

Chris Dollin

hu said:
I said "can not run", I mean that when I start the program, WindowsXP pop a
illegal operation dialog box.

(a) Please don't top-post.

(b) So, by "can not run", you mean "did run, and broke", or just "crashed".
 
C

CBFalconer

hu said:
I said "can not run", I mean that when I start the program,
WindowsXP pop a illegal operation dialog box.

Please do not top-post, especially in technical newsgroups. Your
answer belongs after (or possibly intermixed with) the quoted (and
snipped) material to which you reply.

See the following links for further information

--
Some informative links:
http://www.geocities.com/nnqweb/
http://www.catb.org/~esr/faqs/smart-questions.html
http://www.caliburn.nl/topposting.html
http://www.netmeister.org/news/learn2quote.html
 
J

John Bode

hu said:
hi, everybody!
I'm testing the fuction of strtok(). The environment is WinXP, VC++6.0.
Program is simple, but mistake is confusing. First, the below code can get
right outcome:"ello world, hello dreams."

#include <stdafx.h>
#include <string.h>
#include <stdio.h>

int main()
{
char *pStr = "Hello world, hello dreams.";

This is your problem. The strtok() function has to be able to modify
the string being tokenized; it will overwrite each delimiter it finds
with the nul character. Unfortunately, string literals may not be
writable, so attempting to write to a string literal may invoke
undefined behavior. The results of invoking undefined behavior may
include running as expected, crashing outright, or something more
subtle and difficult to debug.

The easiest way to fix the problem is to change the above declaration
to

char pStr[] = "Hello world, hello dreams.";

Instead of creating a pointer to a non-writable string literal, you've
created an array that can be written to, and the array contents are
initialized with a copy of the string literal.

Grab your handy C reference manual and read up on string literals,
arrays, and strtok().

[snip remainder]
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top