使用strsep在C语言中解析字符串(替代方法)

7

我想解析一个字符串,我使用strsep函数:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{

  char str[] = "Marco:Q:2F7PKC";
  char *token1, *token2, *token3;
  char *r = malloc(30);

  strcpy(r, str);

  token1 = strsep(&r, ":");
  token2 = strsep(&r, ":");
  token3 = strsep(&r, ":");

  printf("tok1 = %s\n", token1);
  printf("tok2 = %s\n", token2);
  printf("tok3 = %s\n", token3);

  free(r);

  return 0;

}

这个函数完成了它的工作,但是如果我启动 valgrind,分配的字符串 char * r 没有被正确释放 (definitely lost: 30 bytes in 1 blocks)。

我想知道为什么会出现这种情况,以及是否有其他方法可以完成相同的任务,也许不需要调用 strsep

我使用 valgrind --tool=memcheck --leak-check=full --show-reachable=yes ./a.out 命令来调用 valgrind。

3个回答

24

strsep会覆写第一个参数(指向指针的指针),因此您将失去对malloc分配的缓冲区基址的指针。实际上,如果在free之前放置printf("%p\n", r);,您会发现您正在释放一个空指针,这没有任何效果。

简单的解决方案是引入一个额外的变量来保存指针,并在完成操作后使用free释放它。惯用用法如下:

char *r = strdup("Marco:Q:3F7PKC");
// check for errors

char *tok = r, *end = r;
while (tok != NULL) {
    strsep(&end, ":");
    puts(tok);
    tok = end;
}

free(r);

4

我想简单概括一下Fred Foo的好回答:

char *end, *r, *tok;

r = end = strdup("Marco:Q:3F7PKC");
assert(end != NULL);

while ((tok = strsep(&end, ":")) != NULL) {
    printf("%s\n", tok);
}

free(r);

它的结果是相同的。但值得一提的是,strsep(3) 将定界符后面的下一个值存储到 end 变量中,并返回当前值(存储在 tok 变量中)。

2

strsep函数会更新它的第一个参数(使其指向它发现的标记之后)。你需要将malloc返回的值存储在一个单独的变量中,并释放这个变量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接