关于C语言的strtok函数问题的疑问

疯狂的流浪 发布于 2013/12/03 10:49
阅读 754
收藏 0

事先在网上搜索了一下相关问题,但是我觉得还是拿到OSC里面来与大家讨论下比较好

程序代码如下:

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

void print_tokens(char *line);

int main()
{
    char *testline = "this is test, for us.";

    char s[] = "ab-cdef:mnop vwx-yz";
    char *delim = "-: ";
    char *p;
    printf("%s\n", strtok(s, delim));
    while((p = strtok(NULL, delim)))
        printf("%s\n", p);
        printf("\n");

    printf("书中原版的例子:\n");
    print_tokens(testline);
    return 0;
}

//书中原版的分隔函数
void
print_tokens(char *line)
{
    static char whitespace[] = "-: ";
    char *token;

    for(token = strtok(line, whitespace);
        token != NULL;
        token = strtok(NULL, whitespace))
        printf("Next token is %s\n", token);
}
运行结果截图:

如果我把testline的定义改成这样又可以正常运行出结果:
char testline[] = "this is test, for  us.";

运行结果

我勒个去,真的越搞越不明白了

加载中
0
无量神通
无量神通

1、"this@is @test ,@for @us."这里面没有空格吧

2、你的print_tokens函数中不是有调用strtok么,这个函数就会修改源字符串的内容

疯狂的流浪
疯狂的流浪
早上自己手忙脚乱的,也没注意,现在贴图出来,其实还是那个*testline和testline[]的问题,不太明白 那个strtok函数对原字符进行了修改啊。。。
1
无量神通
无量神通

第一个问题:你的 whitespace[] = "-: ";没分割成功是 正常的啊,本来就没这几个字符

第二个问题:strtok会修改源字符串的内容,你直接写成:char *testline = "this is test, for us.";的话,testline指向的字符串是常量,常量是不能被修改的

疯狂的流浪
疯狂的流浪
对于第一个问题,里面有个空格,就是说用空格也可以作为分隔,这个没问题吧应该? 第二个问题,我好像没有修改testline吧?
0
无量神通
无量神通
strtok后字符串的内容已经被改变了,所以你在调用print_tokens后s的内容已经变成了"ab\0cdef\0..."
疯狂的流浪
疯狂的流浪
不好意思额,刚才那个变量没改过来,现在改过来了,你可以再看一下,麻烦了,@无量神通
0
whitepig
whitepig
(第一次玩oschina,好紧张~,有不对的地方还请各大牛修正)

从strtok函数原型 char *strtok(char *str, const char *delim);
可知str所指向的空间会被修改。

再来看char *testline ="this is test, for us.";
"this is test, for us."是字符串字面值,存放在程序的rdata段,只读
testline指向这个只读空间,strtok试图修改该空间,导致段错误。
建议用const char *testline ="this is test, for us.";

最后来看 char testline[] ="this is test, for  us.";
"this is test, for us."是字符串字面值,存放在程序的rdata段,仍是只读。
但给testline数组赋值的指令是将"this is test, for us."的编码(一般是utf-8)存放到testline数组的空间。所以可写。
疯狂的流浪
疯狂的流浪
回复 @whitepig : 对呀
whitepig
whitepig
回复 @疯狂的流浪 : 站长?
whitepig
whitepig
回复 @疯狂的流浪 : 我的意思是: 如果用char *testline1 = "this is test"; 那么, testline1指向的空间只读, 传递给strtok当参数后,程序编译成功,但运行就崩溃了. 如果用 char testline2[] = "this is test"; 那么,testline2的空间可写, 传递给strtok当参数没问题.
疯狂的流浪
疯狂的流浪
测试错误额
疯狂的流浪
疯狂的流浪
不要紧张,红薯老大很关照我们滴,嘿嘿@红薯
下一页
0
水一风云
水一风云

我在VS2010上和TC2.0上分别测试了楼主贴出的案例代码,发现书中的代码应该是C代码而不是C++代码.

在C++代码中char *testline = "this is test, for us."; testline应该为指向一个常量字符串的指针(即相当于const char* testline = "this is test, for us";),作为常量来说是不能修改内容的,所以当对testline指向的内容进行修改时就会报错,但在纯C的环境下却是可以修改testline的内容,因为对C研究不是很深,所以具体的处理机制还没搞懂。

疯狂的流浪
疯狂的流浪
感谢指点,原来是这么回事!
0
水一风云
水一风云

在网上又搜了下相关帖子,补充说明下,书本上的代码是在turbo c环境下编写,可以参见下面的链接

http://blog.csdn.net/andylyc/article/details/2046225

疯狂的流浪
疯狂的流浪
还有这种用法,神奇,学习了,感谢!
0
jungleliu0923
jungleliu0923
linux下这个函数不是线程安全,最好用strtok_r代替。windows不知道
返回顶部
顶部