strtok() 函数 2种方法的指针实现

发布时间 2023-05-22 15:20:13作者: 濠梁有鱼

//Lvxin4 - 1 strtok.cpp //strtok()函数的实现 2种方法

//下面的函数实现考虑一下3种极端情况:
//"- This, a sample string" 无行尾标志
//"- This, a sample string-" 有一个行尾标志
//"- This, a sample string- - - - --” 有多个行尾标志

define _CRT_SECURE_NO_WARNINGS

include <stdio.h>

include <string.h>

//方法1 纯指针实现
char* StringSplit(char* str, const char* s)
{
static char* last = NULL;
if (!str)//if(str == NULL) //记忆上次输出字符串的下个位置
str = last;
if (!str)
return NULL;

while (*str)
{
    char c = *str;
    const char* q = s;
    while (*q != c && *q)  //循环找到str串中第一个字符c
        ++q;
    if (*q == '\0')   //找到每个字符串的入口
    {
        char* p = str;//strpbrk(str, s);
        while (c = *p) //在str串中首个找到的位置开始循环,直到结束‘\0’,逐个找字符串
        {
            q = s; //str中的每个字符逐个和s串进行比较
            while (c != *q && *q) //如果*q==c ,就是c为s中字符,*q不为0,结束循环,为进入if条件
                ++q;
            if (*q)//代表发现尾部的分隔符  //找到s中的相关字符
            {
                *p = '\0'; //把找到的第一个至为0
                last = p + 1;//记录下一个位置,未下次循环str的起始位置
                return str;//返回str串的首个位置,打印找到的str串              
            }
            ++p;
        }

        if (c == '\0') //这两行老师程序里没有,导致程序出现bug。当出现"- This, a sample ++string"时,*q为0,直接返回str最后一个字符串string,last没有记录,导致下次出现是last还是在上个位置,last记录为+string的+号位置,打印出现死循环。
        {
            last = NULL;
            return str;
        }

        return str;
    }
    ++str;
}

last = NULL;  //str每个字符都循环完毕后,把静态变量的last置空,干活要利落!!,其实不置空也行。
return NULL;

}

//方法2 用含有strchr() strpbrk() 函数的方法实现
char* StringSplit(char* str, const char* s)
{
static char* last = NULL;
if (!str)//if(str == NULL)
str = last;
if (!str)
return NULL; //此语句对应列子如"- This, a sample string" 这种情况 ,行尾无对应
if (str == '\0')
return NULL; // 此语句对应列子如"- This, a sample string-" 这种情况,行尾有1个对应,当下方语句为while(
str)时,也可省率此句

while (*str)
{
    if (!strchr(s, *str))  //找到子串的入口
    {
        char* p = strpbrk(str, s);  //找到str串中子串的第一个s串的字符
        if (p)  //把第一个子串结尾的s字符置为0,记录下一个位置
        {
            *p = '\0';
            last = p + 1;
        }

        if (p == NULL)
            last = NULL;  // 这两行老师程序里没有,导致程序出现bug。当str末尾没有对应的s字符,也就是 "- This, a sample string" 这种情况,只有行结束标志‘\0’,打印会出现死循环。因为当p指向最后一个单词的行尾,没有对应的s字符,会给p返回一个空指针,打印完最后一个str后,last还在上个位置停留,再次调用时,不停打印str最后一个字符创,出现死循环。 

        return str;
    }
    ++str;
}
last = NULL;//此语句我看来可以省去,写上此句后可使全局变量区清理干净,干活利落!!
return NULL;

}

//主函数main()入口
int main()
{
char str[] = "- This, a sample string.";
const char* pch;
printf("Splitting string "%s" into tokens:\n", str);
pch = StringSplit(str, " ,.-");
while (pch != NULL)
{
printf("%s\n", pch);
pch = StringSplit(NULL, " ,.-");
}
return 0;
}