基本上所有主流的编程语言都有String的标准库,因为字符串操作是我们每个程序员几乎每天都要遇到的。想想我们至今的代码,到底生成和使用了多少String!标题上所罗列的语言,可以看成是一脉相承的,它们的String类库基本上也是一脉相承下来的,但是,在关于String的类库设计中却可以充分看出面向过程和面向对象,以及面向对象语言的抽象程度这些区别,也是我们认识这些语言之间区别的一个很好的入口。
首先从C语言和C++开始。
C语言几乎是现在程序员的程序入门语言,当然,也有不少人不是,比如说我,倒是先从JAVA开始,C语言大学时候基本上没怎么学。。。言归正传,C语言是最伟大的语言之一,在它的基础上诞生了很多主流的面向对象语言,像是C++和JAVA等,并且直到现在,世界上有多少设备至今仍在运行C语言!!
字符串String,究其本质而言,就是字符序列。学习C语言的字符串,我们可以从归约和整体来思考。归约就是关注数据表示的内部细节,像是理解字符在计算机中的内存中是如何存储的,这些字符序列如何被存储为一个字符串,以及200个字符的字符串如何放入保存两个字符的字符串的变量中这些和内存存储相关的问题,这就是自下而上的思考方法。而整体,就是理解如何将字符串作为一个逻辑单位来操作,通过关注字符串的抽象行为,我们可以学会如何有效的使用它,而不必沉溺于细节问题,这就是自顶而下的思考方法。
对于面向对象编程的程序员来说,自顶而下的思考方法才能发挥面向对象的真正威力,通过抽象,我们可以在编码的一开始就已经构建好整个框架,这样有利于我们工作进度的把握和测试。但自下而上的思考方法也是有它的可取之处,像是一些代码设计,更多是与底层打交道,我们更多的时间是花在底层上的话,自下而上也是不错的选择,但总体而言,自顶向下更加能够锻炼程序员的抽象能力,这在接口设计中非常重要,而接口的设计就充分体现了面向对象程序员的价值。
所以我们这里将会从整体的角度上来看待C语言和C++的字符串,之所以放在一起讲,是因为C语言定义了String的存在,而C++提供了完善的String类库。也许我这里的知识已经严重落后了,因为我的C和C++的基础知识还是好几年前(虽然现在我还是准大四生),现在有关String这方面肯定已经大大完善了。
首先是从String的基本概念,也就是从归约的角度开始下手。
在计算机内部,字符串被表示为字符数组,只要我们将一个字符串存储到内存中,这个字符串中的字符就都被分配到连续的字符中。但是,这还不够,因为我们需要知道这些连续字节的内存空间到底什么时候结束,也就是确定字符串的结尾,因为像是这样的字符串:"hello"和"world",如果我们无法确定字符串的结尾,那么这两个字符串在内存中将会是连续的,就会变成"helloworld",但是我们要的明明是两个字符串啊!所以,C语言编译器会在字符串的结尾放一个空字符作为结尾标记,也就是 ,ASCI码为0。这是非常重要的,因为很多入门者都会遗忘这个事实,认为"hello"这个字符串的长度只有5,实际上是6。
以数组表示字符串,在C++中被称为C-风格字符串,所以我们可以像是这样来声明一个string:
char s[] = "hello";
于是我们可以使用数组选择符号来从一个字符串中选出字符,像是s[0]表示的是'h'。
我们可以使用strlen()函数来获得字符串的长度,但这里有个让入门者非常苦恼的问题:strlen("hello")得到的竟然是5!明明"hello"在内存中的真正长度是6!!这样的事实简直难以相信,但是想到strlen()函数的内部实现,就会发现这是必然的。
我们之所以会在字符串的末尾添加空字符,是为了方便我们检测字符串的结束,那么,在strlen()的内部实现中,会是这样子的:
int i, index; for(i = 0; s[i] != '