strtok
Tokenizer函数strtok是常用的函数,可以用来对某个字符串分隔成几段,若只是分隔单个串没什么问题,但不当使用会产生意料外的结果。strtok的函数实现风格很C-style,如果不了解一些细节就很难调试
一,
strtok是会修改原字符串的
考虑以下程式,不过就是把str划分两次
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char *token;
char str[] = "This + is + a + line.";
char sp[] = " .\n\t\r";
token = strtok(str, "+");
while (token) {
printf("%s\n", token);
token = strtok(NULL, "+");
}
token = strtok(str, "+");
while (token) {
printf("%s\n", token);
token = strtok(NULL, "+");
}
return 0;
}
预测输出:
This
is
a
line.
This
is
a
line.
实际输出:
This
is
a
line.
This
很明显,strtok在划分原串时,把包含在分隔集内的字符转化成了'\0'(可能是其他字符)
如果想对同一个串多次划分,请保存原串,用复制串去划分
二,
不应在分隔循环内显式或隐式调用strtok
strtok在实现时,可能用到了两个以上的静态指针。很多人在第一次看到strtok的使用例时可能会很费解,为什么开始是strtok(str, sp),而进入while循环则是strtok(NULL, sp)。因为strtok在每次分隔串时,保存上一次分隔的地址到一个静态指针
以str="This is a line"为例,如果分隔符是空格,那么第一次调用strtok(str, sp),This后面的" "被修改为"\0",原串变为"This\0is a line",更新静态指针则指向"is a line",返回旧指针"This"的头地址;
进入while循环后,调用strtok(NULL, sp),则原串变为"This\0is\0a line",更新静态指针指向"a line",返回旧的静态指针:"is"的头地址;
直到静态指针指向原串末尾,strtok(NULL, sp)只能返回NULL,循环结束
这种设计带来的一点不方便,程序在分隔串时,无法进行进一步的分隔,即无法在while循环内调用strtok,除非保存下一次分隔的头地址,在调用结束后恢复strtok的静态指针
考虑如下程序,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int tokenizer(char *line, char *sp, char* tokens[]) {
int i;
char *token;
i = 0;
token = strtok(line, sp);
while (token) {
printf("%s\n", token);
if (tokens) {
tokens[i] = token;
} i++;
token = strtok(NULL, sp);
} if (tokens) tokens[i] = NULL;
return i;
}
int main(void) {
char *token;
char str[] = "This + is + a + line.";
char sp[] = " .\n\t\r";
token = strtok(str, "+");
while (token) {
printf("%s\n", token);
tokenizer(token, sp, NULL);
token = strtok(NULL, "+");
}
return 0;
}
在分隔内又隐含调用了strtok:token = strtok(str, "+");
while (token) {
printf("%s\n", token);
tokenizer(token, sp, NULL); // call strtok
token = strtok(NULL, "+");
}
期待的输出:
This
This
is
is
a
a
line.
line
实际输出:
This
This
不愿熬夜调试程式的话就请读一下加粗字体吧!
相关阅读
android 自定义控件 使用declare-styleable进行配置属
http://blog.csdn.net/vipzjyno1/article/details/23696537最近在模仿今日头条,发现它的很多属性都是通过自定义控件并设定相关的
通过2个表格查询最终的结果,并实现分页效果 最终我们需要查询的所有数据如下: SELECT b.borrow_no, b.borrow_name,
jquery select option 获取下拉框值改变时,选择不同值
有一些场景下,需要有这样一个功能:我们选择下拉框的不同值时,触发函数,该函数可能用到了我们选中的select的value,比如如:需要将该value
求导运算 (sinx)′=cosx (\sin x)'=\cos x (sinx)′=cosx(cosx)′=sinx (\cos x)'=\sin x (cosx)′=sinx(
使用Eclipse导出向导生成jar包可以用jar命令对java项目(project)进行打包(Java自带的命令行式打包软件jar.exe),也可以使用Eclipse导出