【问题标题】:How do you split a string in C?你如何在C中拆分字符串?
【发布时间】:2012-01-29 17:42:23
【问题描述】:

如果我有这样的字符串:

const char* mystr = "Test Test Bla Bla \n Bla Bla Test \n Test Test \n";

如何使用换行符“\n”将字符串拆分为字符串数组?

我正在尝试在 C 中完成,string.Split() 在 C# 中所做的事情或 boost 的字符串算法 split 在 C++ 中所做的事情。

【问题讨论】:

  • C# 还是 C?您的问题的标题要求提供 C 解决方案,但您的回答暗示(排除语法错误)您需要 C# 解决方案。 Strtok() C 和 C# 都有 String.split()
  • @DarkStar1 C,对不起,我打字很匆忙。 :)

标签: c string algorithm


【解决方案1】:

尝试使用strtok 函数。请注意,它会修改源内存,因此您不能将其与字符串文字一起使用。

char *copy = strdup(mystr);
char *tok;

tok = strtok(copy, "\n");
/* Do something with tok. */
while (tok) {
    tok = strtok(NULL, "\n");
    /* ... */
}

free(copy);

【讨论】:

  • @IntermediateHacker 添加。没测试过,如有错误欢迎指出。
  • 手册和例子here
  • @user411313 但可以使用mallocstrcpy 轻松实现。
【解决方案2】:

在 C 语言中拆分字符串的最简单方法是使用 strtok(),但是它附带了一个关于其使用的注意事项列表:

  1. 它具有破坏性(破坏输入字符串),您不能在上面的字符串上使用它。
  2. 它不是可重入的(它在调用之间保持其状态,并且您一次只能使用它来标记一个字符串......更不用说如果您想将它与线程一起使用)。一些系统提供可重入版本,例如strtok_r()。您的示例可能会被拆分为:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main (void) {
      char mystr[] = "Test Test Bla Bla \n Bla Bla Test \n Test Test \n";
      char *word = strtok(mystr, " \n");
    
       while (word) {
          printf("word: %s\n", word);
          word = strtok(NULL, " \n");
       }
    
       return 0;
    }
    

注意你的字符串声明的重要变化——它现在是一个数组并且可以修改。当然,可以在不破坏字符串的情况下对字符串进行标记,但作为标准库的一部分,C 并未提供简单的解决方案。

【讨论】:

  • 仅供参考,如果代码示例在列表中,则必须缩进 8 个 个空格。
  • 感谢您的提示!为什么它不起作用,我的思绪瞬间融化了,所以我在一个 hline 中通过:)。
【解决方案3】:

请记住,C 语言让您手动完成所有内存分配。还要记住,C 并没有真正的字符串,只有字符数组。此外,字符串文字是不可变的,因此您需要复制它。首先复制整个内容会更容易。

所以,像这样(完全未经测试):

char *copy = xstrdup(mystr);
char *p;
char **arry;
size_t count = 0;
size_t i;

for (p = copy; *p; p++)
  if (*p == '\n')
    count++;

arry = xmalloc((count + 1) * sizeof(char *));

i = 0;
p = copy;
arry[i] = p;
while (*p)
{
  if (*p == '\n')
  {
    *p = '\0';
    arry[i++] = p+1;
  }
  p++;
}

return arry; /* deallocating arry and arry[0] is 
                the responsibility of the caller */

【讨论】:

    【解决方案4】:

    在上述反应中,我只看到 while(){} 循环,恕我直言,for(){} 循环更紧凑。

    cnicutar:

    for(tok = strtok(copy, "\n");tok; tok = strtok(NULL, "\n") {
        /* ... */
    }
    

    致命错误:

    char *word;
    for ( word = strtok(mystr, " \n");word; word = strtok(NULL, " \n") {
       printf("word: %s\n", word);
    }
    

    扎克:

    for (arry[i=0]=p=copy; *p ; p++)
    {
      if (*p == '\n')
      {
        *p = '\0';
        arry[i++] = p+1;
      }
    }
    

    [最后一个例子的清晰度是有争议的]

    【讨论】:

    • 我专门使用了一个while循环,因为我认为当你需要初始化一大堆变量时,for循环更难阅读。我的意思是,伙计,您将变量初始化放在数组索引中
    • 这确实值得怀疑。但是,将所有循环机制集中在 for() 行中比在循环体末尾分散 p++ 或 i++ 更具可读性,恕我直言。
    【解决方案5】:

    您可以使用下面提到的库。它还有许多其他有用的功能。

    http://www.boost.org/doc/libs/1_48_0/libs/tokenizer/index.html

    或者你可以使用strtok函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-15
      • 2020-11-29
      • 1970-01-01
      • 2021-08-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多