C封装字符串、字符串数组对象
字符串(String)
github源码
计算机上的非数值处理的对象基本上是字符串数据。字符串(String)是由零个或you’x多个字符组成的有限序列,一般记为:
s = “a1a2…an” (n>=0)
其中s是串的名,引号内是字符串的值;
ai可以是字母、数字或其他字符;
串中字符数目n称为串的长度,0个字符的串称为空串,它的长度为0;
串中任意个连续的字符组成的子序列称为该串的子串;
包含子串的串相应的称为主串;
字符在序列中的序号称为该字符在串中的位置;
子串在主串中的位置则以子串的第一个字符在主串中的位置来表示;
称两个串相等,当且仅当两个串的长度相等,并且各个对应位置的字符都相等时才相等。
串的逻辑结构和线性表极为相似,区别仅在于串的数据对象约束为字符集。然而,串的基本操作和线性表有很大差别。在线性表的基本操作中,大多以“单个元素”作为操作对象,例如在线性表中查找某个元素、求取某个元素、在某个位置上插入一个元素和删除一个元素等;而在串的基本操作中,通常以“串的整体”作为操作对象,例如在串中查找某个子串、求取一个子串、在串的某个位置上插入一个子串以及删除一个子串等。
字符串有3种机内表示方法:
方法一:定长顺序存储表示
类似于线性表的顺序存储结构,用一组地址连续的存储单元存储串值的字符序列。在串的定长顺序存储结构中,按照预定义的大小,为每个定义的串变量分配一个固定长度的存储区,则可用定长数组如下描述之。
1 | #define MAXSTRLEN 255 //最大串长不超过255 |
串的实际长度可在这预定义长度的范围内随意,超过预定义长度的串值则被舍去,称之为“截断”。
对串长有两种表示方法:一是如上述定义描述的那样,以下标为0的数组分量存放串的实际长度;二是在串值后面加一个不计入串长的结束标记字符,如在C语言中以“\0”表示串值的终结。此时的串长为隐含值。
定长顺序存储表示的缺点在于,出现字符串长度超过上界MAXSTRLEN时,一般用截尾法处理,但是这种情况不仅在求联接字符串时可能发生,在串的其他操作中,如插入、置换也可能发生。克服这个弊病惟有不限定串长的最大长度,即动态分配串值的存储空间。
方法二:堆分配存储表示
这种存储表示的特点是,仍以一组地址连续的存储单元存放串值字符序列,但它们的存储空间是在程序执行过程中动态分配而得。在C语言中,存在一个称之为“堆”的自由存储区,并由C语言的动态分配函数malloc()和free()来管理。利用函数malloc为每个新产生的串分配一块实际串长所需的存储空间,若分配成功,则返回一个指向起始地址的指针,作为串的基址,同时,为了以后处理方便,约定串长也作为存储结构的一部分。
本章封装的字符串对象即用堆分配存储方法存储
定义如下:
1 | typedef struct MyString{ |
这种存储结构表示时的串操作仍是基于“字符序列的复制”进行的。
方法三:串的块链存储表示
和线性表的链式存储结构相类似,也可以采用链表方式存储串值。由于串结构的特殊性——结构中的每个数据元素是一个字符,则用链表存储字符串值时,存在一个“结点大小”的问题,即每个结点可以存放一个字符,也可以存放多个字符。
由于在一般情况下,对串进行操作时,只需要从头向尾顺序扫描即可,则对串值不必建立双向链表。
为了便于串的操作,当以链表存储串值时,除头指针外还可以附设一个尾指针指示链表中的最后一个结点,并给出当前串的长度。
在链式存储方式中,结点大小的选择和顺序存储方式的格式选择一样都很重要,它直接影响着串处理的效率。在各种串的处理系统中,所处理的串往往很长或很多,这要求我们考虑串值的存储密度。存储密度可定义为:
存储密度 = 串值所占的存储位 / 实际分配的存储位
显然,存储密度小(如结点大小为1时),运算处理方便,然而,存储占用量大。如果在串处理过程中需要进行内、外存交换的话,则会因为内外存交换操作过多而影响处理的总效率。
应该看到,串的字符集的大小也是一个重要因素,一般的,字符集小,则字符的机内编码就短,这也影响串值的存储方式的选区。
串值的链式存储结构对某些串操作,如联接操作等有一定方便之处,但总的来说不如另外两种存储结构灵活,它占用存储量大且操作复杂。
本章封装的字符串数组对象即用块链存储方法存储
定义如下:
1 | typedef struct MyStringArray_P |
目前实现了的字符串操作函数有:
1 | MyString *myStringAssign(char *str); |
MyString.c文件
1 | #include <stdio.h> |
MyString.h文件
1 | /* Define to prevent recursive inclusion -------------------------------------*/ |
MyStringArray.c文件
1 | #include <stdio.h> |
MyStringArray.h文件
1 | /* Define to prevent recursive inclusion -------------------------------------*/ |
testMyStringArray.c文件
1 | #include <stdio.h> |
编译testMyStringArray.c文件:
1 | gcc MyString.c MyString.h MyStringArray.c MyStringArray.h testMyStringArray.c -o testMyStringArray |
执行testMyStringArray:
1 | MyStringArray is empty:1 |
编译testMyString.c文件:
1 | gcc MyString.c MyString.h MyStringArray.c MyStringArray.h testMyString.c -o testMyString |
执行testMyString:
1 | str_a :hello , length :6 |
本文标题:C封装字符串、字符串数组对象
文章作者:Mr Bluyee
发布时间:2018-09-05
最后更新:2019-07-15
版权声明:The author owns the copyright, please indicate the source reproduced.