【问题标题】:Split string into two strings by delimiter通过分隔符将字符串拆分为两个字符串
【发布时间】:2016-12-10 13:18:32
【问题描述】:

我尝试使用此代码通过分隔符将一个字符串分成两个字符串

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';

谢谢大家

【问题讨论】:

  • 什么错误?而且,顺便说一句,不要投malloc返回。
  • 你正在投射malloc,那不应该是strlen(msg)吗? line 是从哪里来的?
  • 可以查看strtok 吗?始终将指针变量初始化为 NULL 以保持理智。你调试过吗? readMessage 的代码是什么?我认为从函数返回的指针变量正在被破坏,因为它是在函数的堆栈中分配的。

标签: c string split malloc


【解决方案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() 返回其参数字符串中最多但不包括和的字符数。如果字符存在(size_t 类型而不是 int 除外),它返回与 indexOf() 相同的值,如果不存在,它返回字符串的长度,这是你想要的案子。

【讨论】:

  • 检查行是否有':'我在其他代码中有
  • @mardon: 4386427 实际上在 main 函数的片段中发现了一个错误。应该是index = indexOf(line, ':');
【解决方案2】:
index = indexOf(msg, ':');
                ^^^
                line ?

这里

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

您假设该行比 index+2 长。您应该检查以避免在malloc 调用中出现零。换句话说 - 如果分隔符是最后一个字符,你就会遇到问题。

您应该检查malloc返回的值

if (!input)
{
    // Print error message
    exit(1);
}

顺便说一句 - 看看 strdupmemcpystrncpy

【讨论】:

  • @chqrlie - 终止问题是正确的。我不确定任何标准的 C 函数都可以解决这个问题 - 你知道吗?您的链接通过使用 C++ 编写自定义函数来解决它。在 C 中使用 strncpy 做同样的事情
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-06
  • 2013-10-30
  • 1970-01-01
  • 2014-03-02
  • 2011-11-29
  • 1970-01-01
相关资源
最近更新 更多