通过分隔符将字符串拆分为两个字符串

时间:2016-12-10 13:18:32

标签: c string split malloc

我尝试使用此代码

通过分隔符将字符串拆分为两个字符串
int indexOf(char *msg, char c) {
    int i;
    for (i = 0; msg[i] != '\0'; i++) {
        if (msg[i] == c)
            return i;
    }
    return -1;
}

char *substring(char *msg, int startIndex, int endIndex) {
    int length = endIndex - startIndex;
    char *input = (char *)malloc(length * sizeof(char) + 1);

    int i;
    for (i = startIndex; i != endIndex; i++) {
        input[i - startIndex] = msg[i];
    }
    input[endIndex] = '\0';

    return input;
}

main我有:

index = indexOf(msg, ':');

first = substring(line, 0, index - 1);
second = substring(line, index + 2, strlen(line));

当我用valgrind测试它时,此代码产生正确的输出。在第二个变量中分配的子字符串会产生错误。

此功能的问题在哪里?还有另一种方法将字符串拆分成两个字符串吗?

char *msg = readMessage(stdin);
index = indexOf(msg, '\n');
char *line, *first, *second; 

line = substring(msg, 0, index);

结束valgrind Address 0x5203a52 is 5 bytes after a block of size 13 alloc'd

编辑

还有另一个错误
index = indexOf(line, ':');

现在,valgrind错误位于input[endIndex] = '\0';行的子字符串中:

Invalid write of size 1

编辑:我的代码解决方案有两个错误

中的

index = indexOf(msg, ':');

应该是

index = indexOf(line, ':');

和子字符串

input[endIndex] = '\0';

应该是

input[length] = '\0';

感谢所有

2 个答案:

答案 0 :(得分:1)

index = indexOf(msg, ':');
                ^^^
                line ?

下面

second = substring(line, index+2, strlen(line));

您认为该行长于索引+ 2。你应该检查一下以避免malloc电话中的零。换句话说 - 如果分隔符是最后一个字符,则会遇到问题。

您应该添加malloc

返回的值的检查
if (!input)
{
    // Print error message
    exit(1);
}

顺便说一句 - 看看strdupmemcpystrncpy

答案 1 :(得分:1)

您的代码中存在一些问题:

  • input[endIndex] = '\0';使用错误的索引。它应该是input[length] = '\0';

  • main()
  • ,您不应对indexOf的返回值做出隐含的假设。如果在:中找不到line,则发布的代码会调用未定义的行为:

这是一个更安全的版本:

int index = indexOf(line, ':');
if (index >= 0) {
    // found the `:` separator
    char *first = substring(line, 0, index);
    if (line[index + 1] == ' ') {
        index++;  // skip the space after the :
    }
    char *second = substring(line, index + 1, strlen(line));
    ...
}

您可以使用strcspn()代替indexOf来提取测试次数较少的部分:

char *msg = readMessage(stdin);
size_t index = strcspn(msg, "\n");
char *line = substring(msg, 0, index);
...

strcspn()返回字符数,但不包括其参数字符串中的字符数。如果字符存在,则返回与indexOf()相同的值(size_t类型而不是int除外),如果字符串不是,则返回字符串的长度,这就是你想要的。