[蛋疼的总结]各种语言取子字符串总结

前段时间碰到一个代码review,其中一个bug是关于java的substring的。java的substring作为一个String类下的函数,对于Java的熟练工来说,应当是了如指掌的,可是在我的记忆中生生地搞错了substring原来是不允许越界的。

我必须要为满脑袋浆糊的原因做出一个解释,那就是我发现substring函数,也就是取子字符串函数,虽是一个几乎所有语言都会提供的基本得不能再基本的库函数,但有趣的是,各家对于这个函数的设计差别很大,在一些语言中,利用一些基本类型的差别,很巧妙地解决了这个问题。

在java中,取子字符串的方法是

"abc".substring(1,2); //输出b,通过给定区间的方法,而且是左闭右开的区间,也就是区间的末端的字符是不取的。
"abc".substring(1); //输出bc,可以省略第二个参数,这通常意味着将从begin参数开始之后的字符全部输出
"abc".substring(1,4); //error,越界了!,显然"abc"没有第3(从0开始标号)个字符

而在传统的C++中,取子字符串函数的第二个参数就变成了要去的字符串的长度

string("abc").substr(1,2); //输出bc,你看不一样了吧
string("abc").substr(1); //输出bc,这个一样
string("abc").substr(1,4); //error,越界了!,字符'b'之后没有4个字符。

在很多新兴的语言(新吗?小众吗?非主流吗?)眼中,前面两种语言无疑是太老土了。在脚本和函数式语言中,经常会有向量、列表之类的概念,字符串就变成了一种特殊的向量或列表,这时候可以通过使用向量和列表的方法来获取子字符串,以下举两个例子

%Matlab
str='pumpkin';
s1=str(2:3) %second and third element
s2=str(3:6) % 3rd-6th element
s3=str(1:2:end) % odd elements
s4=str(end:-1:1) %reverse order
s5=str(randperm(3)) % three random elements
s5=str(kron([1 1],[1:7])) % get two pumpkins out of one
//Groovy
String s = “CU soon!”
assert s[-1..0] == “!noos UC”

下面对各种语言的取字符串方法做一个总结,鉴于偶水品极为有限,错误在所难免,谢谢指正。

语言 函数原型 取值方法 越界 类似函数
C char *strncpy(char *dest, const char *src, int length) 长度 dest多余尾部填0,会非法访问。
length为负则不复制。
strcpy
memcpy
C++ string string::substr(size_t pos =0, size_t length=npos) const 长度 pos: out_of_range异常
n:只到结尾
Java String String.substring(int beginIndex [, int endIndex]) 左闭右开 IndexOutOfBoundsException subSequence
C#/.net string string.Substring(int  startIndex [, int length]) 长度 ArgumentOutOfRangeException
VB mid(string,start [,length]) 长度 越界后输出到结尾
但Start <= 0 or Length < 0 时ArgumentException(错误5)
left、right
PHP string substr(string $str,int $start [,int $length]) 长度 正负均可,尽量输出 mb_substr
Python MyStr[a:b](a、b可省略) 左闭右开 正负均可,尽量输出
Ruby MyStr[begin, length] 长度 length负时为nil越界后输出到结尾
MyStr[begin..end] 双闭区间 begin>length为nil
begin不越界时最多到结尾
都越界时输出nil
JavaScript String.substr(start [, length ]) 长度 length负时为空
越界后输出到结尾
String.substring(start, end) 左闭右开
Pascal Copy(S: String; Index: Integer; Count: Integer): String 长度 越界后输出到结尾
T-SQL SUBSTRING ( expression ,start , length ) 长度 length负时报错越界后
输出到结尾
PL/SQL SUBSTR( source_string, start_position, [ length ] ) 长度 length负时为NULL
越界后输出到结尾
Lua strsub (s, i, [j])
string.sub (s, i [, j])
双闭区间 越界后输出到结尾
Matlab MyStr(MatlabRange) Matlab区间或向量 不合法的Range或Range中元素越界则报错
SAS SUBSTR(SOURCE, POSITION, LENGTH) 长度 报错Invalid argument
Bash ${string:position[:length]} 长度 (不知道,待补充)
R substr(x, start, stop)
substring(text, first, last = 1000000L)
双闭区间 (不知道,待补充)
Erlang substr(String, Start[, Length]) 长度 (不知道,待补充)
Common Lisp subseq STRING begin end 左闭右开 (不知道,待补充)
Groovy MyStr[begin..end]MyStr[begin] 双闭区间 支持正负和逆区间段
总能得到一个输出

 

[1] 各大语言的官方文档,oh,这个太多了,不写了
[2] http://www.mathworks.com/matlabcentral/newsreader/view_thread/100236/
[3] http://grooovygeorge.wordpress.com/2012/03/20/groovy-no-need-to-use-substring/

fuzzytalker

国内某综合类学校85后。常年戴啤酒瓶底。除写代码、听音乐和睡觉外无不良嗜好。积极友情置身工坊工作。

More Posts

3 Responses

Leave a Reply