3

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

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,当我 printf 符号中的 3 个字符串时,我得到了这个:

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

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

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

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

4

1 回答 1

1

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

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

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

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

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

于 2013-01-27T08:20:20.923 回答