为什么C中没有split函数?[已关闭]

laik7k3q  于 2022-12-03  发布在  其他
关注(0)|答案(1)|浏览(285)

已关闭。此问题为opinion-based。当前不接受答案。
**想要改进此问题吗?**请更新问题,以便editing this post可以使用事实与引用来回答.

四年前就关门了。
Improve this question
在C语言中没有标准函数可以在一个步骤中获取一个字符串,在空格或其他分隔符处将其分解,并创建一个指向char的指针数组。如果你想做这类事情,你必须自己完成,要么完全手工完成,要么在循环中调用例如strspnstrpbrk,或者在循环中调用strtok。或者通过在循环中调用strsep来执行。
我不是问如何做这个。我know how to do this,并且在Stackoverflow上有plentyotherquestions关于如何做这个。我问的是是否有任何好的理由 * 为什么 * 没有这样的函数。
我当然知道两个主要原因:“因为没有一个主流的编译器/库曾经有过一个”和“因为C标准也没有指定一个(因为它喜欢标准化现有的实践)。”但是还有其他的原因吗?(是否有争论说这样的函数是一个非常糟糕的想法?)
我知道,这通常是一个蹩脚的、毫无意义的问题。在这个例子中,我之所以专注于它,是因为方便的拆分是一个非常有用的操作。我想,我在成为C程序员的第一年就编写了自己的字符串拆分器。从那时起,它对我来说是一个巨大的生产力提高器。每天在SO上有几十个问题可以很容易地回答如果有一个每个人都可以使用和引用的标准split函数,那么这个问题就不存在了。
为了清楚起见,我想象的函数应该有一个签名

int split(char *string, char **argv, int maxargs, const char *delim)

它会将string分解为最多maxargs个子字符串,从delim中拆分一个或多个字符,将指向子字符串的指针放置到argv中,并在此过程中修改string
为了避免争论,我相信有人会说:虽然strtok是标准的,但我并不认为它是一个有效的解决方案。坦率地说,strtok很糟糕。说“您不需要split函数,因为strtok存在”很像说“您不需要printf,因为puts存在”。这不是一个关于给定工具集在理论上可能实现什么的问题;我想,这里更基本的问题是,在挑选可利用、可提高生产率和“有价值”的工具时,涉及到难以言喻的权衡。(我认为很明显,一个封装得很好的字符串拆分函数会有很大的价值,但也许这只是我的看法。)

polhcujo

polhcujo1#

我会尝试一个答案。我确实同意这样的函数会很有用。它在有这样一个函数的语言中经常很有用。
基本上,你是在建议一个内置的非常简单的strtok()strtok_r() Package 器。这将是一个功能较弱的版本(因为我们不能在处理时更改分隔符),但在某些情况下仍然有用。
我看到的是,这些用例还与scanf()系列函数用例以及getopt()getsubopt()系列函数用例重叠。
实际上,我不确定剩下的真实的用例是否那么常见。
在真实的生活中,你需要一个真正的解析器或正则表达式库,在特殊的常见情况下,你已经有了scanf()getopt(),甚至strtok()。
此外,像strtok()或yours这样的函数 * 修改 * 它们的输入字符串,这些天或多或少都被弃用了(经验表明,它们很容易导致麻烦)。
大多数提供拆分功能的语言都有一个真实的的字符串类型,通常是不可变的,并且通过创建许多单独的子字符串而保持原始字符串不变来支持它。
遵循该路径将导致其他一些不基于零分隔字符串的API(可能带有起始指针和结束指针),或者带有分配的字符串副本(如使用strdup()时)。
最后,如果你加起来在真实的生活中不那么常用,写起来相当简单,也不那么简单或直观的API,难怪这样的函数没有包括在标准libc中。
基本上我会这样写:

#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。
当然,如果你认为这对你来说更简单,欢迎你使用和编写你的。

相关问题