在C中拆分带分隔符的字符串 - 错误计数,不能正确拆分

时间:2014-04-24 18:52:12

标签: c string delimiter

我想用给定的分隔符分割单词的字符串(行)。我在下面写了这段代码:

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

unsigned int countWords(char *stringLine)
{
    unsigned int count = 0;
    char* tmp = stringLine;
    char* last = 0;
    const char delim = '/';

    while (*tmp)
    {
        if (delim == *tmp)
        {
            count++;
            last = tmp;
        }
        tmp++;
    }
    return count-1;
}

char **getWordsFromString(char *stringLine)
{
    char** sizeNames = 0;
    unsigned int count = 0;
    const char *delim = "/";

    count = countWords(stringLine);

    sizeNames = malloc(sizeof(char*) * count);
    if(sizeNames == NULL)
    {
        return NULL;
    }

    if (sizeNames)
    {
        size_t idx  = 0;
        char* token = strtok(stringLine, delim);
        while (token)
        {
            if(idx < count)
            {
                exit(-1);
            }
            *(sizeNames + idx++) = strdup(token);
            token = strtok(0, delim);
        }
        if(idx == count - 1)
        {
            exit(-1);
        }
        *(sizeNames + idx) = 0;
    }

    return sizeNames;
}

void showWords(char *stringLine)
{
    unsigned int size = countWords(stringLine), i = 0;
    char** sizeNames = getWordsFromString(stringLine);
    for(i=0; i<size; i++)
    {
        printf("%s\n", sizeNames[i]);
    }
}

int main()
{
    char words[] = "hello/world/!/its/me";

    int c = countWords(words);
    printf("c = %d\n", c);
    showWords(words);
    return 0;
}

问题是我的代码无法正常工作。它在字符串中显示了适当数量的单词但不拆分它们,只给出了255个返回码。我该如何改进呢?

2 个答案:

答案 0 :(得分:2)

这里:

size_t idx  = 0;
char* token = strtok(stringLine, delim);
while (token)
{
    if(idx < count)
    {
        exit(-1);
    }

鉴于您将idx设置为0,只要count大于零,您就会始终exit()。可能你想要一个不同的if条件。您的系统上的退出代码可能未签名,因此-1才会转换为255

答案 1 :(得分:1)

我个人更喜欢用strtok使用for循环表示法......我会像这样编写核心循环:

if (sizeNames)
{                                                                                                                       
    size_t idx  = 0;
    char *token;
    for( token = strtok(stringLine, delim);
         token && idx<count;
         token = strtok(NULL, delim), idx++)
    {
        *(sizeNames + idx) = strdup(token);
    }
    *(sizeNames + idx) = NULL;
}

但是,由于你在最后一个单词之后是NULL终止,所以请确保在下面使用count + 1,否则上面的行*(sizeNames + idx) = NULL;可能会出现段错误:

sizeNames = malloc(sizeof(char*) * (count+1));

PS ...你的countWords例程也会返回错误的答案。可能想要替换:

return count-1;

使用:

if( (last+1)==tmp )
   return count;                                                                                                        

return count+1;

此外,使用strdup()分配的内存永远不会在任何地方释放,因此如果通过valgrind运行,则会出现泄漏错误。

注意,您不必使用strdup(),因为strtok()会将NUL留在源字符串中找到分隔符的位置,因此您可以写一下:

*(sizeNames + idx) = token;

位于for循环的核心。由于这种破坏性行为,strtok()有时仅在要分析的缓冲区副本上运行。