字符动态数组 c语言,用C语言实现一个动态数组

2023年7月13日10:08:23

上两篇文章给出了词法分析的完整代码:

用C语言实现一个真正的词法分析器

用C语言写一个真正的词法分析器,细节代码

它只需要动态字符串和双向链表,这两个基础数据结构就可以。

接下来,是比较有难度的语法分析。

在说语法分析之前,先说一个基础的数据结构:动态数组。

动态数组,也就是C++的STL模板类中的vector。

C语言没有自带的vector,需要自己做个简单的实现。

动态数组,首先是一个数组,它的所有元素都可以通过数组索引访问,随机访问的效率是O(1)。

其次,它与通常的固定数组一样,可以使用索引正向或反向遍历。例如:

for (i = 0; i < vec->size; i++);

for (i = vec->size - 1; i >= 0; i--);

vec为动态数组的结构体指针,vec->size为它当前存储的元素个数。

再就是,它可以存储多种数据类型,即可以作为基础数据结构使用,而与所存储的数据类型无关。

最后,与固定数组不同,它可以随着元素的增加或删除,动态地改变大小。

它的所有元素,自然是顺序存储的,而且每个元素的大小一致。

在C语言中,一个可行的办法就是,只让它存储void*类型的指针:如果存储复杂的结构体类型,那么只存储结构体的指针;如果存储数字,因为指针的大小是机器的字长,数字的大小不会超过这个值,所以可以把数字当作void*类型存储。

具体定义如下图:

数据部分是二级指针void** data,它的每个元素都是void*类型。

capacity表示当前的最大容量,size表示当前的元素个数。

在最大容量不够时,每次增加16个位置,这样可以减少realloc()的次数。

字符动态数组 c语言,用C语言实现一个动态数组

上图为scf_vector_alloc()和scf_vector_clone()函数,

下图为scf_vector_add()和scf_vector_del()函数。

字符动态数组 c语言,用C语言实现一个动态数组

因为要保持元素的连续存储,删除的复杂度与双链表不一样,需要移动后半部分的元素,这个复杂度不是O(1),而是O(N)。

如果删除元素之后,空闲的内存过多,则执行realloc()从新分配小一点的内存,把不用的部分及时还给系统。

下图是scf_vector_find()、scf_vector_find_cmp()、scf_vector_qsort(),分别用于查找元素,根据传入的cmp函数指针查找元素,以及给元素排序。

字符动态数组 c语言,用C语言实现一个动态数组

再就是提供两个函数scf_vector_clear()和scf_vector_free()。

字符动态数组 c语言,用C语言实现一个动态数组

scf_vector_clear(),如果需要在销毁动态数组之前释放所存储的元素的内存,可以先调用这个函数(需要传入释放元素内存的free函数指针),然后再调用scf_vector_free()。

如果所存储的元素没有占用额外的内存,例如是个被当作void*存储的数字,就可以直接调用scf_vector_free()。

动态数组的实现还是比较简单的,因为都是一些小函数,直接static inline写在头文件里了。

最后,使用这个动态数组实现一个数据结构:栈。

栈,在语法分析时使用的比较多,因为语法分析存在大量的复杂递归,需要栈来保存上下文。

栈,也是个动态数组,区别就是只从最后一个元素添加、删除、访问。

字符动态数组 c语言,用C语言实现一个动态数组

scf_stack_push(),用于压栈。

scf_stack_pop(),用于出栈。

scf_stack_top(),用于访问栈顶元素,它与scf_stack_pop()的区别就是它不会把栈顶元素弹出,不会改变栈的大小。

字符动态数组 c语言,用C语言实现一个动态数组

下一篇,说一下有限自动机的实现,使用它来分析语法。

举报/反馈

  • 作者:weixin_39942785
  • 原文链接:https://blog.csdn.net/weixin_39942785/article/details/117035941
    更新时间:2023年7月13日10:08:23 ,共 1446 字。