【问题标题】:Can't figure out how strchr works in C无法弄清楚 strchr 在 C 中是如何工作的
【发布时间】:2021-02-03 23:20:09
【问题描述】:

我有这段代码假设根据分隔符拆分字符串。当分隔符为 '\0' (空字符)时,它似乎有效,但是当我尝试使其与 '\n' (换行符)一起工作时,我最终得到了一个我无法解释的奇怪结果。代码如下:

  char **results = malloc(*nb_delimiter * sizeof(char *));

  // Separate result with delimiter
  char *next;
  char *pointer = "1\n2\n3\n4";
  for (int i = 0; i < *nb_delimiter; ++i)
  {
    next = strchr(pointer, delimiter);
    results[i] = pointer;
    pointer = next + 1;
  }
  printf("%s\n", results[0]);

例如:当我运行它时,它给了我:

  • 结果[0]:1\n2\n3\n4
  • 结果[1]:2\n3\n4
  • 结果[2]:3\n4
  • 结果[3]:4

代替:

  • 结果[0]:1
  • 结果[1]:2
  • 结果[2]:3
  • 结果[3]:4

我真的不明白,当我在 C 中寻找拆分数组的方法时,大多数人推荐使用 strchr()。我不明白为什么我会遇到这个问题。

谢谢

【问题讨论】:

  • "...大多数人推荐 strchr()" - 有趣,因为我经常看到 vast 多数人推荐 strtok_r 。无论如何,您的代码中没有任何地方(a)复制字符串,也没有(b)通过在分隔符上硬写 nullchar 值来窃取现有的字符串数据(在这种情况下,您无论如何都不能,因为您会正在修改文字,所以即使strtok_r 也会被禁止)。
  • 您不会在找到的换行符上写入空字节,因此字符串在换行符之后继续。使用strtok()strtok_r()strtok_s(),分隔符被一个空字节所取代,所以换行符会得到更短的字符串。 strtok() 例程的缺点是,如果有多种可能性,您不知道哪个字符被删除——当只有一个(例如换行符)时,没有问题。

标签: arrays c string split strchr


【解决方案1】:

对于 char* 字符串,表示非常原始:它只是内存中连续的字符序列,空字符\0(零字节)表示字符串的结束位置。没有其他信息可以说明字符串长度是多少。 (参见维基百科上的null-terminated string。)

您的结果“1\n2\n3\n4”、“2\n3\n4”等按预期指向字符串的开头,但它们并未在应有的位置结束。您需要将空字符写入原始字符串,替换分隔符,以便将其拆分为多个部分。

但是,源字符串是文字,因此尝试修改它是 UB。所以要正确地做到这一点,首先制作一个字符串的副本(例如,通过strcpy'ing 到足够大小的缓冲区中),然后操作该副本。

【讨论】:

  • 但是你不能写空字符,因为它是一个文字......
  • @AnttiHaapala 谢谢,我错过了。我更新了我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-19
  • 2013-11-05
  • 2018-04-05
  • 1970-01-01
  • 2020-08-28
相关资源
最近更新 更多