【问题标题】:How to split with multiple delimiters in C如何在C中使用多个分隔符进行拆分
【发布时间】:2021-11-17 10:23:48
【问题描述】:

我有这行文字:

32+-#3#2-#3#3

我需要将数字彼此分开。所以基本上结果是这样的:

3
2+-
3
2-
3
3

这是我的代码,但它不能正常工作,因为我有两位数字:

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

int main(void) {
    char string[50] = "32-#3#2-#3#3";
    // Extract the first token
    char *token = strtok(string, "#");
    // loop through the string to extract all other tokens
    while (token != NULL) {
        printf(" %s\n", token); //printing each token
        token = strtok(NULL, "#");
    }
    return 0;
}

【问题讨论】:

  • 那你为什么不一次读一个字符然后跳过分隔符呢?
  • 所以“32”不被认为是“三十二”?然后我会用“数字”而不是“数字”来表达。
  • “这是我的代码,但它不能正常工作,因为我有两位数字” 我们无法猜测“不能正常工作”是什么意思。您能否至少指定一个示例输入和结果输出,并清楚地解释为什么输出与您想要的不同?另见:What do you mean "It doesn't work?"

标签: c algorithm split strsplit


【解决方案1】:

strtok() 不是适合您的工具...事实上,strtok() 很少是适合任何用途的工具,因为它具有复杂的语义和副作用。

一个简单的循环就可以了:

#include <stdio.h>

int main(void) {
    char string[50] = "32+-#3#2-#3#3";

    for (char *p = string; *p; p++) {
        if (*p == '#')
            continue;
        putchar(*p);
        while (p[1] == '+' || p[1] == '-')
            putchar(*++p);
        putchar('\n');
    }
    return 0;
}

【讨论】:

    【解决方案2】:

    有一种简单的方法可以实现这一点,但在C 中有点复杂,因为我们没有vector 那样在C++ 中,但我可以建议一个纯C 实现,可以改进:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void split_ss(const char* src,const char* pattern, char** outvec, size_t* outsize)
    {
        const size_t  pat_len = strlen(pattern);
        char* begin = (char*) src;
        const char* next = begin;
        if ((begin = strstr((const char*)begin, pattern)) != 0x00) {
            unsigned int size = begin - next;
            *outvec = malloc(sizeof(char) * size);
            memcpy(*outvec , next, size);
            outvec++;
            (*outsize)+=1;
            split_ss(begin+pat_len, pattern, outvec, outsize);
        } else {
            unsigned int size = &src[strlen(src)-1] - next + 1;
            *outvec = malloc(sizeof(char) * size);
            memcpy(*outvec, next, size);
            (*outsize) += 1;
        }
    }
    
    
    int main()
    {
        char* outdata[64] = {0};
        size_t size, i=0;
        split_ss("32+-#3#2-#3#3", "#", outdata, &size);
        for(i=0; i < size; i++) {
            printf("[%s]\r\n", outdata[i]);
        }
    
        // make sure to free it
    
        return 0;
    }
    

    strstr 用于按字符串而不是字符进行分割。输出也是一个可怜的 2D 数组,它的大小超出了迭代它的大小,不要忘记释放它。

    【讨论】:

      【解决方案3】:

      你不能用strtok(单独)来做,因为你想分割的数字之间没有分隔符。没有strtok 会更容易,只需打印您想要打印的内容并添加分隔符,除非属于令牌的字符如下:

      #include <stdio.h>
      
      int main()
      {
          char string[] = "32+-#3#2-#3#3";
          for (char *token = string; *token; ++token)
              if ('0'<=*token && *token<='9' || *token=='+' || *token=='-')
              {
                  putchar(*token);
                  if (token[1]!='+' && token[1]!='-') putchar('\n');
              }
      }
      

      如果您认为这太简单了,您可以使用正则表达式来匹配标记:

      #include <stdio.h>
      #include <regex.h>
      
      int main()
      {
          char *string = "32+-#3#2-#3#3";
          regex_t reg;
          regcomp(&reg, "[0-9][+-]*", 0);
          regmatch_t match = {0};
          while (regexec(&reg, string+=match.rm_eo, 1, &match, 0) == 0)
              printf("%.*s\n", (int)(match.rm_eo-match.rm_so), string+match.rm_so);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-05
        • 2018-04-20
        • 2016-11-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多