c - 字符串数组中的最后一个字符串(从 strtok 解析)有垃圾

标签 c arrays string strtok

我在这里有点困惑。主要内容:

int main() {
    char **symbols = (char **) malloc(3 * sizeof(char *)); // allocate 3 (char *)'s
    for (int i = 0; i < 3; i++)
        symbols[i] = (char *)malloc(3); // allocate string of length 3

}

然后用户在一行中输入三个字符串符号,以空格分隔:

111 010 101

然后我将这个缓冲的字符串解析为一个字符串数组:

void parseSymbols(char *line, int k, char **symbols) {
    // k == 3
    // Ignore leading spaces
    while (*line != '\0' && is_whitespace(*line))
            line++;

    char *p = strtok(line, " ");
    int cnt = 0;
    symbols[cnt++] = p;
    while (p) {
            p = strtok(NULL, " \n");
            symbols[cnt++] = p;
    }

    // Let's call this FOOBAR
    //for (int i = 0; i < k; i++)
    //        printf("%d. %s\n", i, symbols[i]);

回到 main,当我打印 symbols 中的 3 个字符串时,我得到了这个:

0. '111'
1. '010'
2. ' s'

但是当我取消注释掉最后两行 parseSymbols 时,我得到:

0. '111'
1. '010'
2. '101'

为什么 FOOBAR block “修复”了我的字符串数组,更重要的是,我怎样才能让 parseSymbols 正常工作而不必在屏幕上打印一些东西? symbols[2] 是否需要以'\0'结尾? (但是 strtok 不是为我做的吗?)

最佳答案

您的第一个问题是您通过将 strtok 的结果指针分配给符号表而导致内存泄漏。这是因为您只是复制对标记下一个开头的引用,而不是复制这些行中的结果字符串:symbols[cnt++] = p;

接下来,您应该通过将结果分配给您的符号表来确保您没有超过 k。您的代码总是在符号表的最后位置写入 NULL。一旦解析 3 个符号,您将写入未分配的内存,导致未定义的行为。

我建议先纠正这些问题,然后再试一次。

请注意,strtok 通过将标记末尾的分隔符替换为“\0”来修改您的原始缓冲区,因此无需复制字符串。另请注意,strtok 会跳过其中一个定界符的连续出现。因此,您的第一个循环可以替换为检查第一个标记的长度是否 >0(或者换句话说,结果字符串的第一个字节是 != '\0'

请注意,C 字符串总是需要比您要存储的空间多 1 个字节的空间。这个额外的字节用于 '\0' 终止。在您的示例中,您正在解析 3 个字节的 block ,同时每个 block 仅分配 3 个字节(应该是 4 个):symbols[i] = (char *)malloc(3);//分配长度为 3 的字符串

关于c - 字符串数组中的最后一个字符串(从 strtok 解析)有垃圾,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14545407/

相关文章:

c - 通过函数返回数组时出错

java - 为什么这个 String.equals() 方法总是返回 false?

c - 将数据提供给需要文件名的 C API

c++ - Windows命令提示符中的彩色文本一行

python - 根据另一个数组更改列的值

php - MySQL/PHP 从多列中仅选择唯一值并将它们放入单独的数组中

regex - SQLite 从列中的文本中提取字符串

c - 为什么 mblen() 总是返回 1?

c# - 了解 cmp(比较器函数)如何用作另一个函数的参数

java - 如何使用 Java 中的多线程实现 2D 方阵乘法?