【问题标题】:String split function with delimiters in CC中带分隔符的字符串拆分函数
【发布时间】:2014-03-27 05:38:10
【问题描述】:

我在编写带分隔符的字符串拆分函数时遇到问题。我的功能基于此处的主要功能:http://www.cplusplus.com/reference/cstring/strtok/

当我通过 main 测试它时,我只能传递 char[],但不能传递 char*。传递 char* 时,程序段出错。

即通过 str_split 传递一些 char str[] 有效,但不是一些 char* str。任何帮助将不胜感激。

char** str_split(char* str, const char* delim)
{
  char* tmp;

  char** t = (char**)malloc(sizeof(char*) * 1024);
  char** tokens = t;

  tmp = strtok(str, delim);

  while(tmp != NULL)
  {
    *tokens = (char*)malloc(sizeof(char) * strlen(tmp));
    *tokens = strdup(tmp);
    tokens++;
    tmp = strtok(NULL, delim);
  }

  return t;
}

【问题讨论】:

    标签: c string split


    【解决方案1】:

    这两行给你两个不同的问题:

    *tokens = (char*)malloc(sizeof(char) * strlen(tmp));
    *tokens = strdup(tmp);
    

    第一行会分配strlen(tmp)字节,但问题是字符串有一个额外的字符来终止字符串,所以你真的需要分配strlen(tmp) + 1字节。

    第二行覆盖你从malloc得到的原始指针,导致内存泄漏。

    另外,在 C 中你 should not cast the return of malloc.

    哦,还有一个注意事项:sizeof(char) 被指定为始终返回 1,无论 char 类型的实际位大小如何。


    至于你的段错误,我猜你是用字符串文字调用你的函数,例如

    some_var = str_split("hello world", " ");
    

    或者可能

    char *string = "hello world";
    some_var = str_split(string, " ");
    

    这将导致未定义行为,因为字符串文字实际上是一个指向常量字符数组的指针,而strtok修改细绳。未定义的行为可以说是最常见的崩溃原因。

    如果您在构建时启用更多警告,您会收到关于此的警告,或者您可能确实收到警告但忽略了它,或者使用强制转换来摆脱它。来自编译器的警告通常可以很好地表明你做了一些你不应该做的事情,例如隐藏它。投射只会使警告静音,但不能解决问题。


    您的代码还存在一些其他问题。一种是如果您传递给函数的“句子”中只有一个“单词”/“令牌”,那么您会浪费 40928184 字节(取决于 32 位或 64 位平台)分配。您可能希望首先执行单独的标记化循环(在字符串的临时副本上),以找出输入中“标记”或“单词”的确切数量。

    进行这种计数还可以解决另一个问题:如果有更多超过 1024 个标记/单词怎么办?在这种情况下,您的循环将幸福地写出边界。

    这两种情况都是极端情况,您的标准用例可能更适合您当前的代码,但仍然需要考虑。

    【讨论】:

    • 谢谢,这有帮助。我能够修复程序中的错误并找出内存泄漏。我将尝试提出一个单独的标记化循环,谢谢您的建议
    【解决方案2】:

    您可能在声明时为 char * 赋值

    char *str="abcdef";
    

    或者您可能没有为char * str 指向的字符串分配内存。在这两种情况下,strtok() 将导致segmentation fault

    【讨论】:

      【解决方案3】:

      当我通过 main 测试它时,我只能传递 char[],但不能传递 char*。传递 char* 时,程序段出错。

      上述可能性是您没有在main 中为您的char * 分配内存,或者您正在传递字符串文字。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多