C 中没有标准函数来获取字符串,并在空格处将其分解 或其他分隔符,并一步创建一个指向
char
的指针数组。
如果你想做那种事,你也必须自己做
完全手动,或通过致电,例如strspn
和 strpbrk
循环,
或者循环调用 strtok
,或者循环调用 strsep
。
我不是在问如何做到这一点。我知道该怎么做, 并且有大量 其他 问题 在 Stackoverflow 上 关于如何去做。我要问的是是否有任何充分的理由为什么 没有这个功能
我当然知道两个主要原因:“因为没有主流编译器/库 曾经有过一个”和“因为 C 标准也没有指定一个(因为 它喜欢标准化现有的做法)。”但是还有其他原因吗? (是否有人认为这样的函数是一个非常糟糕的主意?)
我知道,这通常是一个蹩脚且毫无意义的问题。在这种情况下 我很关注它,因为方便的拆分非常有用 手术。我在第一年就编写了自己的字符串分割器 我认为 C 程序员,这对我来说是一个巨大的生产力提升者 自从。这里每天都会有几十个关于 SO 的问题,可能是 如果有的话,很容易回答(或者甚至不必问) 标准分割功能,大家可以使用参考。
需要明确的是,我想象的函数会有一个像
这样的签名int split(char *string, char **argv, int maxargs, const char *delim)
它将把
string
分解成最多maxargs
子字符串,从delim
中拆分出一个或多个字符,将指向子字符串的指针放入argv
中,并在此过程中修改string
。
为了避免争论,我相信有人会提出:虽然这是标准的,但我不认为
strtok
是一个有效的解决方案。 strtok
,坦白说,很糟糕。说“你不需要 split 函数,
因为 strtok
存在”很像说“你不需要 printf
,
因为puts
存在。”这不是一个关于理论上的问题
使用给定的工具集是可能的;这是关于什么是有用和方便的。越多
我想这里的根本问题涉及所涉及的不可言喻的权衡
选择具有杠杆作用和提高生产力的工具
“付钱”。 (我认为很明显,一个封装得很好的
字符串分割函数会带来丰厚的回报,但也许
这就是我。)
我会尝试回答。我确实同意这样的功能很有用。它在拥有它的语言中通常非常有用。
基本上,您建议围绕
strtok()
或 strtok_r()
构建一个非常简单的内置包装器。这将是一个功能较弱的版本(因为我们在处理时无法更改分隔符),但在某些情况下仍然有用。
我看到的是,这些案例也与
scanf()
家庭功能用例以及 getopt()
或 getsubopt()
家庭功能用例重叠。
实际上我不确定剩下的真实用例是否那么常见。
在现实生活中的重要情况下,您需要一个真正的解析器或正则表达式库,在特殊的常见情况下,您已经拥有
scanf()
或 getopt()
甚至 strtok()。
还有功能修改他们的输入字符串,如
strtok()
或你的现在或多或少已被弃用(经验表明它们很容易导致麻烦)。
大多数提供拆分功能的语言都具有真正的字符串类型,通常是不可变的类型,并且通过创建许多单独的子字符串同时保持原始字符串完整来支持它。
沿着该路径将导致一些不基于零分隔字符串(可能带有起始指针和结束指针)的其他 API,或者带有分配的字符串副本(例如使用
strdup()
时)。都不太令人满意。
最后,如果你加起来在现实生活中不那么常见,编写起来很简单,API也不是那么简单或直观,那么这样的函数没有包含在strandard 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。
但是,如果您认为它对您来说更简单,当然欢迎您使用和编写您的。