字符串是各类语言中一种非常重要的数据结构,事实上大部分的代码都是基于字符串的操作,各个语言对字符串的处理方式,也是我们评价各个语言的一个重要方面。
因为C++库中并没有提供字符串这个数据类型,所以我们以STL中提供的string来进行对比。这里不选择char*进行对比,是因为char*在功能上和其它两种语言差距实在是太大了,基本上不具有对比性,之前一直使用的都是STL,所以这里直接选用STL来对比了。
JAVA中选用String及其周边类,它们会作为一个整体进行对比;
而python中的string是一个内置的数据类型,直接用于对比。
1、存储的方式
在STL中string类实现中,是直接申请内容空间,来存放对应的char数组,但是string类自身接管了这些内存的生命周期,不需要开发者做处理;在JAVA中String类的实现,也是通过char[]来存储字符串内容,JAVA中所有对象的生命周期,都是有虚拟机来管理的,同样不需要开发者对其做处理;在Python中,String本身就是一种基本的数据类型,不需要靠其他的数据类型来对其进行存储
2、支持的操作
以Python为标准,对比在字符串操作上几种语言的异同。
功能描述 | Python | Java | STL |
是否包含子串 |
str1 in str; 2str1 not in str2; |
str2.contains(str1); |
str2.find(str1) |
字符串相加 | str1+str2 | str1+str2 | str1+str2 |
倍数复制 | str1*2 | 不支持 | 不支持 |
下标取值 | str1[0] | 不支持 | str1[0] |
下标范围取值 |
str1[0:2]; str1[0:5:2] |
不支持 | 不支持 |
取字符串长度 | len(str1) | str1.length() |
str1.length(); str1.size() |
去最小/大字符 |
min(str1); max(str1) |
不支持 | 不支持 |
获取子串出现的第一个位置 |
str1.index(str2); str1.find(str2); str1.find(str2,5,10) str1.rfind(str2) |
str1.indexOf(str2); str1.indexOf(str2,10); str2.lastIndexOf(str2) |
str2.find(str1); str2.find(str1,10) str2.rfind(str1) |
获取子串出现的次数 |
str1.count(str2); str1.count(str2,10,15) |
不支持 | 不支持 |
字符串首字母大写,其他字母小写 | str1.capitalize() | 不支持 | 不支持 |
字符串居中显示,其它用指定字符填充 |
str1.center(80,"*") str1.ljust(4,"*") str1.rjust(4,"*") str1.zfill(4) |
不支持 | 不支持 |
是否以某子串结尾 |
str1.endswith(str2 ) str1.startwith(str2) |
str1.endsWith(str2) | 不支持 |
把tab转换为空格 | str1.expandtabs(4) | 不支持 | 不支持 |
格式化字符串 | str1.format(str2) | String.format(str1,str2,d1) | 不支持,需要借用sprintf |
是否仅是字符\数字 |
str1.isalnum() str1.isalpha() str1.isdigit() |
不支持 | 不支持,系统提供isalnum(c),isalpha(c),isdigit(c),仅能判断单个字符; |
是否全是大写/小写 |
str1.islower() str1.isupper() |
不支持 | 不支持,系统提供islower(c),isupper(c),仅能判断单个字符 |
是否是空格 | str1.isspace() | 不支持 | 不支持,系统提供isspace(c),仅能判断单个字符 |
是否是标题:即只有单词首字母大写 |
str1.istitle() str1.title() |
不支持 | 不支持 |
以自身为分隔符,把list中的内容连接起来,返回一个String | str1.join(l1) | 不支持 | 不支持 |
转换为小写 |
str1.lower() str1.swapcase() str1.upper() |
str1.toLowCase() | 不支持 |
去掉开头的指定字符 |
str1.lstrip("abc" ) str1.rstrip("123") str1.strip(str2) |
不支持 |
不支持 |
字符串拆分 |
str1.partition("str2") str1.rpartition("str2") str1.split("str2") str1.rsplit("str2") |
str1.split(str2) | 不支持 |
字符串替换 | str1.replace("old","new") |
str1.replaceAll(regex,new) str1.replace(regex,new) str1.replaceFirst(regex,new) |
str1.replace() |
字符串复杂替换 | str1.translate | 不支持 | 不支持 |
3、对汉字的支持(有关字符集的处理)
在STL中,对string的处理是不带任何编码方式的,仅仅是保存对应的char的取值。假如中文的“你好”,当前采用UTF-8进行编码,取值为“E4 BD A0 E5 A5 BD”,那么通过string保存的内容的取值即为“E4 BD A0 E5 A5 BD”,如果我们想正常的把这部分内容读取出来,那我们首先要知道它是以UTF-8的方式进行存储的,必须要按照UTF-8的方式,进行解码。
而在java中,String类统一存储的是字符的unicode编码,“你好”对应的unicode编码为“4F 60 59 7D”,这个才是真正存储在String的char数组中的内容。JAVA中采用unicode对所有字符统一编码,正好和其char的长度为2个字节对应,因为unicode中所有字符都是用2个字节来进行编码的。当我们往String中赋值的时候,JAVA会根据当前字符对应的编码方式,转换为unicode进行存储;当我们从String中获取内容时,JAVA会根据需要的编码方式,把转换后的结果返回给我们。从入到出,始终是有一个编码的转换过程。即使在获取bytes的时候,没有指定编码方式,并不意味着取出来的是unicode编码方式,而是意味着以java虚拟机默认的编码方式获取。所以,对于涉及到中文的操作,最好能够指定相应的编码,以免在运行时因为环境的不同而出错。
Python中的string对象,和C++中一样,并不对存储的内容做特殊的编码转换,什么样编码方式存入,就得以同样正确的编码方式读取出来。这样的实现,存在的问题是显而易见的。我们对于字符串的读取,是基于字节的,而不是真正基于字符的。如果存储的是中文,很有可能读取出来的结果就是半个字符,非常不利于进行字符的操作。所以,Python从2.0开始,增加了ustring的支持,也就是说,python默认这种string中存储的是unicode编码的字符串,每两个字节,代表一个字符,基于字符的操作,也是以两个字节为单位的,由此就不会出现半个字符的问题。但是,和JAVA强制的内在转换不同,Python并不对其进行转换,开发者自己保存标识为ustring的内容,的确是unicode编码的,如果不是,那么处理的结果就是乱码。例如,当开发者获取到以UTF8方式编码的字符串时,首先,要调用unicode(str,"utf8")把其转换为unicode string,经过处理后,再把处理后的unicode string通过encode("utf8")转换为utf8的方式存储或者是发送出去。当然,如果你对字符的操作不涉及截取、查找等,直接用普通的string存储,不经过编解码的转换,也没有太大问题。从这里可以看出来,python其实是集合了c++和java的处理,采取了一个较为折中的方式。
4、和数值的相互转换
Python中的数据类型只有整数和浮点数这两种,从string转换为int或者是float时,通过int、float系统函数,进行转换即可。而从int、float转化为string,只需要通过str函数进行转换即可
int -> float/string a=123 b=float(a) c=str(a)
float -> int/string a=123.5 b=int(a) c=str(a)
string ->int/float a="123.3" b=int(a) c=float(a)
C++中的数据类型转换:
JAVA中的数据类型转换:JAVA为String提供了valueOf函数,支持所有数据对象转换为String;而针对每一种数据类型,都提供的parse函数,把String转换为对应的数据类型。
int a = 123;
float b = 123.3f;
String a1 = String.valueOf(a);
String b1 = String.valueOf(b);
int a2 = Integer.parseInt(a1);
float b2 = Float.parseFloat(b1);