从strtok中一次只获取一个标记

3
考虑以下包含两个不同字符串的情况:
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()不会返回空字符串(我希望如此)。相反,它会读取字符串直到第一个与分隔符"-"不匹配的字符,从而忽略了字符串中值的存在。
有没有可能仅按分隔符拆分字符串一次?

1
MyNumber的值缺失”--您是不是指“MyNumber2的值缺失”? - Spikatrix
2
这是预期的行为。如果您想要处理空标记,您必须编写自己的strtok函数。查找一些strtok源代码并根据您的需求进行修改。 - Jabberwocky
@CoolGuy 确实,我已经编辑了这个问题。谢谢。 - Mikel Urkia
1
使用 strsep 替代 strtok - BLUEPIXY
2个回答

4

我认为你应该使用标准函数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", ... 添加到输出原点以增加清晰度。 - chux - Reinstate Monica

0

Strtok 无法对分隔符之间的空值进行标记化。 要获取原因,请查看此处的第一个答案

我曾经和你一样处于同样的情况。我使用 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

1
memset(token,'\0',sizeof(token));是不好的写法。sizeof(token)返回的是指针的大小,而不是已分配内存的大小。建议改用*token = '\0'; strncat(token,str1,(delimiter_index-previous_delimiter_index)+1);来代替memset(token,'\0',sizeof(token)); strncpy(...); - chux - Reinstate Monica
没错,感谢您的纠正。您提出的方法完全可行,但我用更简单的方式进行了修改:将memset(token,'\ 0',sizeof(token));替换为memset(token,'\ 0',sizeof(delimiter_index-previous_delimiter_index+1)); - Gajendra Bagali
sizeof(delimiter_index-previous_delimiter_index+1) 的大小也不是需要清零的缓冲区的大小。尝试使用不同的输入并注意 sizeof(delimiter_index-previous_delimiter_index+1) 始终相同。 - chux - Reinstate Monica
糟糕..不应该有 sizeof。它应该只是 delimiter_index-previous_delimiter_index+1。我希望现在没有混淆了。 - Gajendra Bagali

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接