strtok

Parse S into tokens separated by characters in DELIM.  If S is NULL, the saved pointer in SAVE_PTR is used as the next starting point.  作用于字符串s,以包含在delim中的字符为分界符,将s切分成一个个子串;如果,s为空值NULL,则函数保存的指针SAVE_PTR在下一次调用中将作为起始位置。

#include<stdio.h>
#include<string.h>
#define MAPSIZE 32
/*
*功能:作用于字符串_String,以包含在_Delimiter中的字符为分界符,将_String切分成一个个子串;
如果,_String为空值NULL,则函数保存的static指针SAVE_PTR在下一次调用中将作为起始位置。
参数: _String:指向欲分割的字符串;在第一次调用时,strtok()必需给予参数_String字符串,往后的调用则将参数_String设置成NULL;
	   _Delimiter:为分隔符字符(如果传入字符串,则传入的字符串中每个字符均为分割符)。
特点:strtok函数会破坏待分解字符串的完整性,调用前和调用后的_String已经不同。
*/						
char* __cdecl MyStrtok(char * _String, const char * _Delimiter)	
{
	//ASCII值是[0,255];故而要进行无符号类型的强转。
	unsigned char *str;
	const unsigned char *ctrl = (const unsigned char *)_Delimiter;
	static unsigned char* SAVE_PTR = NULL; //如果_String为空值NULL,则函数保存的指针SAVE_PTR在下一次调用中将作为起始位置
	unsigned char map[MAPSIZE];	
	
	memset(map, 0, sizeof(char)*MAPSIZE);	//初始化标记数组
	do {
		//所有_Delimiter中包含的字符都会被做记号   或等于
		map[*ctrl >> 3] |= (1 << (*ctrl & 7)); //*ctrl>>3等效于*str/8;*ctrl&7等效于*ctrl%8。
	} while (*ctrl++);

	if (_String != NULL)
		str = (unsigned char *)_String;		//第一次才满足if条件。
	else
		str = (unsigned char *)SAVE_PTR;
    
    //讨论:str ?= NULL,如果出现为NULL时,必定是else语句中的SAVE_PTR==NULL导致的;
    //SAVE_PTR始终指向上一次切割好的子串的结束符'\0'的下一位置,
    //如果SAVE_PTR == NULL,说明,主串遍历结束
    //警告:对空指针进行解引用是会崩溃的!!!
    //下行出现的if循环正常情况下并不起眼,
    //strtok函数到底调用几次是使用者控制的,如果字符串切割完成之后还继续调用呢???
    //必须终止!!!
    if(NULL == str) return NULL;

	//所有_Delimiter中包含的字符都会被滤掉,并将被滤掉的地方设为一处分割的节点。
	while ( (map[*str >> 3] & (1 << (*str & 7))) && *str )		
		str++;
	_String = (char *)str;//_String指向不包含在_Delimiter中的首个字符出现的位置----精华之处

	for (; *str; str++)
	{
		if ( map[*str >> 3] & (1 << (*str & 7)) )//扫描过程中发现_Delimiter中包含的分割字符时,则会将该字符改为'\0' 
		{
			*str++ = '\0';	//后续读取的时,遇到'\0'就停止;意味着破坏_String指向的字符串是不可避免的,充当结束符的角色
			break;
		}
	}
	SAVE_PTR = str;		//记下又一次出现_Delimiter中包含的字符的起始位置;

	return  _String;
}

int main()
{
	char str[] = { "192.168.0.10" };
	char *res[4] = { '\0'};
	res[0] = MyStrtok(str, ".");
	for (int i = 1; i < 4; ++i)
		res[i] = MyStrtok(NULL, ".");

	for (int i = 0; i < 4; ++i)
		printf("%s  ", res[i]);
	printf("\n");
	return 0;
}
图1  VS2017下运行结果

 

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页