为什么C中没有拆分功能?

时间:2018-03-19 20:50:59

标签: c string split

C中没有标准函数来获取字符串,在空格中将其分解 或其他分隔符,并在一步中创建指向char的指针数组。 如果你想做那种事情,你也必须自己做 完全用手,或通过呼叫,例如循环中strspnstrpbrk, 或者在循环中调用strtok,或者在循环中调用strsep

我不是在问这个怎么做。我know how to do this, 并且有plentyother questions 在Stackoverflow上 关于如何做到这一点。我问的是,是否有任何好的理由为什么 没有这样的功能。

我知道两个主要原因,当然:“因为没有主流的编译器/库 曾经有一个“和”因为C标准没有指定一个(因为 它喜欢标准化现有的做法。“但还有其他原因吗? (有这样的论据认为这样的功能是一个积极的坏主意吗?)

我知道,这通常是一种蹩脚而毫无意义的问题。在这种情况下 我很注意它,因为方便的分裂是非常有用的 操作。我在第一年内写了自己的字符串分割器 我认为C程序员,对我来说这是一个巨大的生产力提升器 以来。每天都有很多关于SO的问题 如果有的话,很容易回答(或者甚至不需要问) 标准分割功能,每个人都可以使用和参考。

要清楚,我想象的功能会有像

这样的签名
int split(char *string, char **argv, int maxargs, const char *delim)

它会将string分解为最多maxargs个子字符串,从delim分割一个或多个字符,将指针放入argv,并修改{ {1}}在此过程中。

为了阻止一个论点,我相信有人会做出来:尽管它是标准的,我不会考虑 string是一个有效的解决方案。坦率地说,strtok很糟糕。说“你不需要拆分功能, 因为strtok存在“很像是说”你不需要strtok, 因为printf存在。“这不是一个关于什么是理论上的问题 可以使用给定的工具集;这是有用和方便的。更多 我想,这里的根本问题涉及所涉及的不可言喻的权衡 选择可以提高利用率和提高生产力的工具 “付钱”。 (我认为很明显是一个很好的封装 字符串分割功能会很好地付出代价,但也许 那只是我。)

1 个答案:

答案 0 :(得分:1)

我会尝试一个答案。我确实同意这样的功能是有用的。 通常在有一个语言的语言中非常有用。

基本上,您建议在strtok()strtok_r()周围使用内置非常简单的包装器。它将是一个功能较弱的版本(因为我们无法在处理时更改分隔符),但在某些情况下仍然有用。

我看到的是,这些案例也与scanf()家庭功能用例和getopt()getsubopt()家庭功能用例重叠。

实际上,我不确定剩下的真实用例是那么常见。

在现实生活中,你需要一个真正的解析器或正则表达式库,在专门的常见情况下你已经有scanf()getopt()甚至strtok()。

还可以修改他们的输入字符串,例如strtok(),或者你的这些日子或多或少被弃用(经验说它们容易导致麻烦)。

大多数提供拆分功能的语言都有一个真正的字符串类型,通常是不可变的,并且通过创建许多单独的子字符串来保持原始字符串完整而支持它。

遵循该路径将导致某些其他API非基于零分隔字符串(可能具有开始指针和结束指针),或者使用分配的字符串副本(如使用strdup()时)。两者都不令人满意。

最后,如果你在现实生活中加起来并不常见,编写起来非常简单,而不是那么简单或直观的API,毫无疑问这样的功能并没有包含在libard中。

基本上我会写这样的东西:

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

int split(char *string, char **argv, int maxargs, const char *delim){
    char * saveptr = 0;
    int x = 0;
    argv[x++] = strtok_r(string, delim, &saveptr);
    while(argv[x-1] && (x <= maxargs)){
        argv[x++] = strtok_r(0, delim, &saveptr);
    }
    return x-1;
}

int main(){
    char * args[10];
    {
        char * str = strdup("un deux trois quatre cinq six sept huit neuf dix onze");
        int res = split(str, args, sizeof(args)/sizeof(char*), " ");
        printf("res = %d\n", res);
        for(int x = 0; x < res ; x++){
            printf("%d:%s\n", x, args[x]);
        }
    }

    {
        char * str = strdup("un deux trois quatre cinq");
        int res = split(str, args, sizeof(args)/sizeof(char*), " ");
        printf("res = %d\n", res);
        for(int x = 0; x < res ; x++){
            printf("%d:%s\n", x, args[x]);
        }
    }
}

我看到的代码是使用strtok()编写所需函数非常简单...并且使用结果的调用站点几乎与函数本身一样复杂。因此,在这种情况下,我宁愿在调用网站上内联函数而不是调用libc。

但是如果您认为对您来说更简单,那么欢迎您使用并撰写您的文章。