必威体育Betway必威体育官网
当前位置:首页 > IT技术

使用C分隔函数strtok的两个细节

时间:2019-08-10 16:42:24来源:IT技术作者:seo实验室小编阅读:70次「手机版」
 

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最近在模仿今日头条,发现它的很多属性都是通过自定义控件并设定相关的

mysql中分页效果的实现(limit的使用技巧)

通过2个表格查询最终的结果,并实现分页效果 最终我们需要查询的所有数据如下: SELECT b.borrow_no, b.borrow_name,

jquery select option 获取下拉框值改变时,选择不同值

有一些场景下,需要有这样一个功能:我们选择下拉框的不同值时,触发函数,该函数可能用到了我们选中的select的value,比如如:需要将该value

三角函数公式总结

求导运算 (sin⁡x)′=cos⁡x (\sin x)&#x27;=\cos x (sinx)′=cosx(cos⁡x)′=sin⁡x (\cos x)&#x27;=\sin x (cosx)′=sinx(

使用Eclipse导出向导生成jar包

使用Eclipse导出向导生成jar包可以用jar命令对java项目(project)进行打包(Java自带的命令行式打包软件jar.exe),也可以使用Eclipse导出

分享到:

栏目导航

推荐阅读

热门阅读