【问题标题】:Get only one token from strtok at a time一次只能从 strtok 获取一个令牌
【发布时间】:2015-10-06 22:33:58
【问题描述】:

考虑以下两个不同字符串的场景:

Row1: MyID-MyName-MyAddress-MyNumber-MyNumber2-MyAlias
Row2: MyID-MyName-MyAddress-MyNumber--MyAlias

在第二个示例中,MyNumber2 的值缺失。我需要使用strtok() 提取每个属性。到目前为止,这是我的代码:

MyID      = strtok (str,  "-"); //where 'str' is the full string
MyName    = strtok (NULL, "-");
MyAddress = strtok (NULL, "-");
MyNumber  = strtok (NULL, "-");
MyNumber2 = strtok (NULL, "-");
MyAlias   = strtok (NULL, "-");

第一个示例运行良好,我可以将每个 属性 存储在变量中。但是,在第二个示例中,我遇到了麻烦:

进入变量MyNumber2 时,strtok() 不会返回空字符串(如我所愿)。相反,它会读取字符串直到第一个字符与分隔符"-" 不匹配,从而忽略字符串中 empty 值的存在。

是否有可能每个分隔符只拆分一次字符串?

【问题讨论】:

  • "MyNumber 的值缺失" -- 你的意思是MyNumber2 的值缺失
  • 这是预期的行为。如果要处理空令牌,则必须编写自己的 strtok 函数。找到一些 strtok 源并根据您的需要进行修改。
  • @CoolGuy 事实上,我已经编辑了这个问题。谢谢。
  • 使用strsep 而不是strtok

标签: c token strtok


【解决方案1】:

我认为您应该改用标准函数strchr。例如

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

int main( void )
{
    char s[] = "MyID-MyName-MyAddress-MyNumber--MyAlias";

    for ( char *p = s, *q = s; p != NULL; p = q )
    {
        q = strchr( p, '-' );
        if ( q )
        {            
            printf( "\"%*.*s\"\n", ( int )(q - p ), ( int )( q - p ), p );
            ++q;
        }
        else
        {
            printf( "\"%s\"\n", p );
        }
    }
}    

程序输出是

"MyID"
"MyName"
"MyAddress"
"MyNumber"
""
"MyAlias"

【讨论】:

  • 建议if (q) { printf("1) \"%*.*s\"\n", ... } else { printf("2) \"%s\"\n", ... 增加输出源的清晰度
【解决方案2】:

Strtok 不能标记分隔符之间的空值。 想知道原因,Please check the first answer here

我和你的情况一样。我用strstr 做了同样的事情,如下所示:

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

void main(void)
{
    char str[] = "MyID-MyName-MyAddress-MyNumber--MyAlias";
    char * str1, * token;
    int i = 0;
    int parsed_buffer_length = 0;
    char * previous_delimiter_index = str;
    char * delimiter_index = str;
    for(;;)
    {
            str1 = str+parsed_buffer_length;
            delimiter_index = strstr(str1,"-");
            if(delimiter_index==NULL)
            {
                    printf("%s",str1);  //prints last token
                    break;
            }
            token = malloc(delimiter_index-previous_delimiter_index+1);
            memset(token,'\0',delimiter_index-previous_delimiter_index+1));
            strncpy(token,str1,(delimiter_index-previous_delimiter_index));

            printf("%s\n",token);

            parsed_buffer_length = (int)(parsed_buffer_length+delimiter_index-previous_delimiter_index+1);
            previous_delimiter_index = delimiter_index+1;
            free(token);
    }
}

它给出了输出:

MyID
MyName
MyAddress
MyNumbers

MyAlias

【讨论】:

  • memset(token,'\0',sizeof(token)); 不好。 sizeof(token) 是指针的大小,而不是分配的内存大小。而不是memset(token,'\0',sizeof(token)); strncpy(...);,建议*token = '\0'; strncat(token,str1,(delimiter_index-previous_delimiter_index)+1);
  • 是的,没错。感谢您的指正。建议您的方式完全正常,但我以非常简单的方式对其进行了更改:将 memset(token,'\0',sizeof(token)); 替换为 memset(token,'\0',sizeof(delimiter_index-previous_delimiter_index+1));
  • sizeof(delimiter_index-previous_delimiter_index+1) 也不是需要归零的缓冲区的大小。尝试各种输入,注意sizeof(delimiter_index-previous_delimiter_index+1) 总是一样的。
  • 糟糕.. 不应该有sizeof。它应该只是delimiter_index-previous_delimiter_index+1。我希望现在没有混乱
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-29
  • 1970-01-01
相关资源
最近更新 更多