【问题标题】:C string nested splittingC字符串嵌套拆分
【发布时间】:2017-06-03 09:37:54
【问题描述】:

我是 C 的初学者,但我遇到了一个简单的问题。就是这样:
我有一个格式如下的字符串: "first1:second1\nsecond2\nfirst3:second3" ... 等等。
从示例中可以看出,第一个字段是可选的 ([firstx:]secondx)。
我需要得到一个只包含第二个字段的结果字符串。像这样:“second1\nsecond2\nsecond3”。

我在这里对堆栈 (string splitting in C) 做了一些研究,我发现 C 中有两个主要的字符串拆分函数:strtok(已过时)和 strsep .
我尝试使用这两个函数(加上 strdup)编写代码,但没有成功。大多数时候我会得到一些不可预测的结果。

更好的想法?
提前致谢

编辑:
这是我的第一次尝试

int main(int argc, char** argv){
    char * stri = "ciao:come\nva\nquialla:grande\n";
    char * strcopy = strdup(stri); // since strsep and strtok both modify the input string
    char * token;
    while((token = strsep(&strcopy, "\n"))){
        if(token[0] != '\0'){ // I don't want the last match of '\n'
            char * sub_copy = strdup(token);
            char * sub_token = strtok(sub_copy, ":");
            sub_token = strtok(NULL, ":");
            if(sub_token[0] != '\0'){
                printf("%s\n", sub_token);
            }
        }
        free(sub_copy);
    }
    free(strcopy);
}

预期输出:“come”、“si”、“grande”

【问题讨论】:

  • 向我们展示您的代码。 strtok() 没有过时!
  • @JohnZwinck 应该是 :p,strtok_r() 要好得多。
  • @Stargateur:更好的是:strspn() / strcspn()
  • main()函数的参数不使用时,使用签名:int main( void )
  • 调用strdup()时,一定要检查(!=NULL)返回值以保证操作成功

标签: c string split


【解决方案1】:

这是strcspn的解决方案:

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

int main(void) {
    const char *str = "ciao:come\nva\nquialla:grande\n";
    const char *p = str;
    while (*p) {
        size_t n = strcspn(p, ":\n");
        if (p[n] == ':') {
            p += n + 1;
            n = strcspn(p , "\n");
        }
        if (p[n] == '\n') {
            n++;
        }
        fwrite(p, 1, n, stdout);
        p += n;
    }
    return 0;
}

我们计算不包含:\n 的初始段的大小。如果后面跟着:,我们跳过它并获取下一个不包含\n 的段。

如果后面跟着\n,我们会在段中包含换行符。然后我们只需要输出当前段并更新p 以继续以相同的方式处理字符串的其余部分。

*p'\0' 时,即到达字符串末尾时,我们停止。

【讨论】:

  • @Stargateur 我不明白那个评论。您建议的替换仍然输出\n
  • 我想说的是,您的示例并不容易理解,OP 可能希望令牌成为“单独的字符串”。在这里打印它而不删除字符串的原始'\n'。也许这样做会更好,例如当然rextester.com/BLS46506。但无论如何,没关系,算了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-26
  • 1970-01-01
  • 1970-01-01
  • 2017-06-16
相关资源
最近更新 更多