【问题标题】:(C) - First element in array of strings is becoming garbage(C) - 字符串数组中的第一个元素正在变成垃圾
【发布时间】:2015-10-08 19:53:42
【问题描述】:

我用 C 语言编写了以下函数来尝试对字符串进行标记。 该函数接受一个要标记的字符串(char * string),以及用于将标记彼此分隔的一串分隔符(char * delimiters)。

char ** tokenize(char * string, char * delimiters)
{
    int num_of_tokens = 0;
    int itr = 0;

    char ** tokens = NULL;

    while (string[itr] != '\0')
    {
        if (!isDelimiter(string[itr], delimiters))
        {
            num_of_tokens++; /*if char is not a delimiter, we have found a new token*/

            int temp_token_count = num_of_tokens - 1;

            tokens = realloc(tokens, num_of_tokens);
            tokens[temp_token_count] = malloc(STRING_SIZE * sizeof(char));

            while(!isDelimiter(string[itr], delimiters) && string[itr] != '\0')
            {
                appendChar(tokens[temp_token_count], string[itr]);
                itr++;
            }
        }

        itr++;
    }
    return tokens;
}

在 main 函数中,tokenize 函数的调用如下所示:

int main()
{
    char * string = "This would,,,,be";
    char * delim = ",.:;*& ";

    char ** tokens = tokenize(string, delim);

    int x = 0;

    while(x<3)
    {
        printf("%s\n", tokens[x]);
        x++;
    }

    return 0;
}

我希望这个调用产生的输出:

This
would
be

然而,这是输出:

 L@?
would
be

考虑到如果我使用“This”作为输入字符串调用标记化函数,这似乎特别奇怪,我收到的结果也完全符合我的预期:

This

我不知道发生了什么,任何帮助将不胜感激,感谢您的宝贵时间!!

编辑:这是 isDelimiter 函数

int isDelimiter(char test_char, char * delimiters)
{
    int itr = 0;

    while (delimiters[itr] != '\0')
    {
        if (test_char == delimiters[itr]) return 1;
        itr++;
    } 

    return 0;
}

【问题讨论】:

  • 显示你的函数 isDelimiter 。
  • tokens = realloc(tokens, num_of_tokens); 应该是tokens = realloc(tokens, num_of_tokens*sizeof(char*));
  • 关于调用 malloc、calloc 和 realloc: 1) 始终检查 (!=NULL) 返回值以确保操作成功。 2)调用realloc时,不要将返回值直接放入目标指针中。因为,如果重新分配失败,那么原始指针会丢失(用 NULL 覆盖),从而导致内存泄漏。 IE。始终将返回的指针保存在 void * 中,检查 NULL,如果不是 NULL,则保存到目标指针。 3)调用malloc时,参数永远不需要'sizeof(char)',因为它总是1所以没有效果并且代码混乱
  • 关于这一行:'tokens = realloc(tokens, num_of_tokens);'要分配的字节数实际上是 'num_of_tokens 乘以 sizeof (char *)' 所以发布的代码没有分配足够的内存
  • 变量 'itr' 经常增加一次,因此循环顶部的测试错过了检查字符串结尾或分隔符的字符。强烈建议使用调试器(如 gdb)来单步执行代码,tokenize() 函数可能更好地编写为两状态机。 1) 不在令牌中 2) 在令牌中。那么逻辑会更清晰,更容易发现问题。

标签: c string malloc realloc


【解决方案1】:

这是不正确的:

tokens = realloc(tokens, num_of_tokens);

由于tokens被用作指针数组,你需要为num_of_tokens指针分配空间:

tokens = realloc(tokens, num_of_tokens * sizeof(char *));

此外,当您找到一个标记时,您会在另一个 while 循环中遍历该字符串,直到找到一个分隔符或一个 NULL。这很好,但是您随后在外部while 循环的底部再次增加itr。如果您在内循环结束时发现 NULL,则此增量会将 inde 移动到字符串范围之外,从而导致未指定的行为。

如果你没有找到分隔符,你应该只在外循环中增加:

while (string[itr] != '\0')
{
    if (!isDelimiter(string[itr], delimiters))
    {
        ...
    }
    else
    {
        itr++
    }
}

【讨论】:

  • 感谢您的回答和帮助,现在一切正常!
猜你喜欢
  • 2013-02-07
  • 1970-01-01
  • 1970-01-01
  • 2010-11-22
  • 1970-01-01
  • 1970-01-01
  • 2012-04-28
  • 1970-01-01
  • 2013-01-10
相关资源
最近更新 更多