第四章、串
1、C语言内存管理(内存分区)
C语言经过编译之后将内存分为以下几个区域:
- (1)栈(stack)区:由编译器进行管理,自动分配和释放,存放函数调用过程中的各种参数、局部变量、返回值以及函数返回地址。操作方式类似数据结构中的栈。
- (2)堆(heap)区:用于程序动态申请和释放空间。
C
语言中的malloc
和free
,C++
中的new
和delete
均是在堆中进行的。正常情况下,程序员申请的空间在使用结束后应该释放,若程序员没有释放空间,则程序结束时系统自动回收。注意:这里的堆并不是数据结构中的堆。 - (3)全局(静态)存储区:分为
DATA
段和BSS
段。DATA
段(全局初始化区):存放已初始化的全局变量和静态变量(用static
关键字修饰);BSS
段(全局未初始化区):存放未初始化的全局变量和静态变量;- 其中
BSS
段在程序执行之前会被系统自动清0
,所以未初始化的全局变量和静态变量在程序执行之前已经为0
; - 程序结束时自动释放。
- (4)文字常量区:存放常量字符串,程序结束后由系统释放。
- (5)程序代码区:存放程序的二进制代码。
全局变量和静态变量保存在内存的全局存储区中,占用静态的、永久性的存储单元;
局部变量保存在栈中,只有所在函数被调用时才由系统动态在栈中分配临时性的存储单元。
2、知识框架
3、串的定义
- 字符串简称串,计算机上非数值处理的对象基本都是字符串数据。
- 串(string) :是由零个或多个字符组成的有限序列。一般记为:
S = 'a1a2 · · · an'
(n ≥ 0) - 其中
S
是串名,单引号括起来的字符序列是串的值,ai
可以是字母、数字或其他字符; - 串中字符的个数
n
称为串的长度,n = 0
时的串称为空串 (用∅
表示); - 由一个或多个空格(空格是特殊字符)组成的串称为空格串 (注意:空格串不是空串),其长度为串中空格字符的个数。
- 串中任意多个连续的字符组成的子序列称为该串的子串,包含子串的串称为主串 。
- 某个字符在串中的序号称为该字符在串中的位置。
- 子串在主串中的位置以子串的第一个字符在主串中的位置来表示。
- 当两个串的长度相等且每个对应位置的字符都相等时,称这两个串是相等的。
例如:有串A = 'China Beijing'
,B = 'Beijing'
,C = 'China'
,则它们的长度分别为13、7和5。B
和C
是A
的子串,B
在A
中的位置是7,C
在A
中的位置是1。
- 串的逻辑结构和线性表极为相似,区别仅在于串的数据对象限定为字符集。
- 线性表的基本操作主要以单个元素作为操作对象,如查找、插入或删除某个元素等,而串的基本操作通常以子串作为操作对象,如查找、插入或删除一个子串等。
4、串的存储结构
(1)定长顺序存储表示
- 类似于线性表的顺序存储结构
- 用一组地址连续的存储单元存储串值的字符序列
- 为每个串变量分配一个固定长度的存储区,即定长数组
#define MAXLEN 255 //预定义最大串长为255
typedef struct {
char ch[MAXLEN]; //为每个分量存储一个字符
int length; //串的实际长度
} SString;
- 串的实际长度只能小于等于
MAXLEN
,超过预定义长度的串值会被舍去,称为截断。 - 串长有两种表示方法:
- 一是如上述定义描述的那样,用一个额外的变量
length
来存放串的长度; - 二是在串值后面加一个不计入串长的结束标记字符
\0
,此时的串长为隐含值。
- 一是如上述定义描述的那样,用一个额外的变量
- 在一些串的操作(如插入、联接等)中,若串值序列的长度超过上界
MAXLEN
,约定用“截断”法处理。
(2)堆分配存储表示
- 以一组地址连续的存储单元存放串值的字符序列
- 但存储空间是在程序执行过程中动态分配得到的
typedef struct {
char *ch; //按串长分配存储区,ch指向串的基地址
int length; //串的长度
} HString;
- 在C语言中,存在一个称之为“堆”的自由存储区,并利用
malloc
和free
来完成动态存储管理。 - 利用
malloc
为每个新产生的串分配一块实际串长所需的存储空间,若分配成功,则返回一个指向起始地址的指针,作为串的基地址,这个串由ch
指针来指示;若分配失败,则返回NULL
。 - 已分配的空间可使用
free
来释放掉。
(3)块链存储表示
- 类似于线性表的链式存储结构
- 由于串的特殊性(每个元素只有一个字符),在具体实现时,每个结点既可以存放一个字符,也可以存放多个字符。
- 每个结点称为块,整个链表称为块链结构。
- 下图是结点大小为4(即每个结点存放4个字符)的链表,最后一个结点占不满时通常用
#
补上: - 下图是结点大小为1的链表:
5、串的基本操作
StrAssign(&T, chars)
:赋值操作。把串T
赋值为chars
StrCopy(&T, S)
:复制操作。由串S
复制得到串T
StrEmpty(S)
:判空操作。若S
为空串,则返回TRUE
,否则返回FALSE
StrCompare(S, T)
:比较操作。若S
>T
,则返回值 > 0;若S
=T
,则返回值 = 0;若S
<T
,则返回值 < 0StrLength(S)
:求串长。返回串S
的元素个数SubString(&Sub, S, pos, len)
:求子串。用Sub
返回串S
的第pos
个字符起长度为len
的子串Concat(&T, S1, S2)
:串联接。用T
返回由S1
和S2
联接而成的新串Index(S, T)
:定位操作。若主串S
中存在与串T
值相同的子串,则返回它在主串S
中第一次出现的位置;否则函数值为0
ClearString(&S)
:清空操作。将S
清为空串DestroyString(&S)
:销毁串。将串S
销毁
在上述定义的操作中,串赋值StrAssign</