strtok_r 函数使用说明

        函数原型:char *strtok_r(char *str, const char *delim, char **saveptr); 头文件<string.h>,使用man就可以查看其用法。那函数的功能就是根据分隔符delim,将str进行分割,返回值是第一个分割出来的子串,而 saveptr 则指向剩余的子串。

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

void cmd_scan(const char *arg);
void cmd_connect(const char *arg);
void usage(const char *app);

static const struct {
	const char *cmd;
	const char *arg;
	void (*func)(const char *arg);
	const char *description;
}cmd_table[] = {
	{"scan", "<on/off>", cmd_scan, "scan bluetooth device"},
	{"connect", "mac", cmd_connect, "connect the bluetooth device"},
	{NULL, NULL, NULL, NULL},
};

int main(int argc, char *argv[])
{
	int i = 0;
	char *cmd = NULL;
	char *arg = NULL;
	if(argc < 3)
	{
		usage(argv[0]);
		return -1;
	}
	
	/* snprintf(char *str, size_t size, const char *format, ...) 只会拷贝size-1个字符 */
	int len = 0;
	char cmdLine[64] = {0};
	for(i = 1; i < argc; i++)
	{
		len = snprintf(cmdLine + len, strlen(argv[i]) + 2, "%s ", argv[i]);
	}
	
	/**/
	cmd = strtok_r(cmdLine, " ", &arg);
	if(cmd == NULL)
	{
		printf("invalible command\n");
		return -1;
	}
	
	if(arg) 
	{
		int len = strlen(arg);
		if (len > 0 && arg[len - 1] == ' ')
			arg[len - 1] = '\0';
	}

	for(i = 0; cmd_table[i].cmd; i++)
	{
		if(strcmp(cmd, cmd_table[i].cmd))
		{
			continue;
		}
		
		if(cmd_table[i].func)
		{
			cmd_table[i].func(arg);
		}
		break;
	}
	return 0;
}

void cmd_scan(const char *arg)
{
	printf("%s scan device\n", strcmp("on", arg)?"stop":"start");
}

void cmd_connect(const char *arg)
{
	printf("start connect device %s\n", arg);
}

void usage(const char *app)
{
	int i = 0;
	printf("Usage: %s", app);
	for(i = 0; cmd_table[i].cmd; i++)
	{	
		if(i > 0)
		{
			printf("\t\t");
		}
		printf("\t%s\t", cmd_table[i].cmd);
		printf("%s\t", cmd_table[i].arg);
		printf("%s\n", cmd_table[i].description);
	}
}

strtok_r() 是 strtok() 的可重入版本,可重入版本其实就是线程安全的函数。不可重入函数可能引发的问题,可以参考之前的一篇文章 这里

strtok_r() 最主要的用途就是分割字符串,那我们常操作的就是分割一串字符串,然后获取到想要的所有子串,man 手册里也说明了,如果是针对同一个字符串进行一系列的分割动作,则从第二次调用strtok_r() 开始,第一个参数则需要传递 NULL:

The  strtok()  function  breaks a string into a sequence of zero or more nonempty tokens.  On the first call to strtok(), the string to be parsed should be specified in str.  In each subsequent call that should parse the same string, str must be NULL.

如下的例子:

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


int main(int argc, char *argv[])
{
    char *day = NULL;
    char *arg = NULL;
	char cmdLine[128] = {0};
	strncpy(cmdLine, "Monday Tuesday Wednesday Thursday Friday Saturday Sunday", sizeof(cmdLine));
	
    /* 第一次调用传非NULL */
	day = strtok_r(cmdLine, " ", &arg);
	printf("day: %s\n", day);

	while(day)
	{
        /* 解析同一个字符串时,参数传 NULL */
		day = strtok_r(NULL, " ", &arg);
		if(day)
		{
			printf("day: %s\n", day);
		}
	}

	return 0;
}

 那为什么解析同一个字符串时,除第一次调用外都要传 NULL 呢? 我们可以看一下源码:

从源码上就可以很清楚地看到,如果第一个参数是NULL,则要解析的字符串的指针指向了 save_ptr,而 save_ptr 就是指向了第一次解析后剩余的子串, 所以多次解析同一个字符串,第二次开始必须传 NULL。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值