你好,我正在尝试学习和构建c中的数据结构,我想在堆栈中逐步存储整数。我的结构是这样的:
typedef struct STACK_NODE_s *STACK_NODE;
typedef struct STACK_NODE_s{
STACK_NODE forward;
void *storage;
} STACK_NODE_t;
typedef struct L_STACK_s{
STACK_NODE top;
} L_STACK_t, *L_STACK;
在while循环中,我想读取并存储整数形式的字符。
//assume that str is an proper string
//assume that we have a linked stack called LS
int i=0;
int temp;
while(str[i]!=' '){
tmp=str[i]-'0';
push(LS,(void *)&tmp);
}
我知道这不会正常工作,因为我们一次又一次地存储同一个变量的地址。我需要分配一个辅助数组来存储它们吗?或者有更好的方法吗?
答案必须解决问题的两个独立方面:如何组织一些项目集合,以及从哪里获得内存。
第一个代码段/链表格式
第一个代码片段就是这样。它建立了一个链接列表,有其优点和缺点,但如果您事先不知道项目的数量,如果您希望能够快速删除或插入列表中间的某个项目,如果您不介意在列表中查找某个特定项目需要付出O(N(的努力,则效果非常好。
对于类似于泛型库的实现。。。
。。。void*
和ANSI C一样好。例如,在C++中,您可以创建一个模板,打开存储在列表中的类型(或者更好的是,您可以直接在类forward_list<int>
中重用众所周知的STL实现(。遗憾的是,ANSI C没有可比性。一种解决方案是您选择的,创建int
对象并将它们的地址挂接到void*
列表中。泛型库实现的另一个解决方案是为类型使用预编译器宏,并在包含泛型实现的头文件上方定义此宏。这试图类似于干净的C++解决方案,但对于预编译器来说,它不是类型安全的,因此这种方法并不美观,并且存在一些风险。
第二个代码段/内存分配
使用void*
而不是int
(或任何非指针类型(创建列表需要在列表旁边分配更多内存。也就是说,不仅要分配每个列表项(=类型为STACK_NODE_t
的变量(,还要分配实际的条目值(例如,*(int*)(LS->storage)
(。
这意味着您必须以比堆栈寿命更长的其他方式分配/取消分配数据。在大多数系统上,可以使用malloc
/free
,并且只需要考虑可用于malloc
的堆的大小和去/分配所需的时间。如果该列表应实现实时要求或在嵌入式系统上,您可能没有malloc
,也可能不被允许使用。然后,您必须为列表分配并实现自己的堆(=storage
项的内存池(。如何实现这样一个具有所需属性的内存池是一个单独的问题,它将带我们走到这里。
在任何情况下,都不能使用指向堆栈变量的指针(就像函数中的局部变量一样(,因为一旦函数退出,该变量后面的内存将不会保留用于此目的,同时内存可能会用于其他用途。然而,第二个代码片段显然就是这样做的。正如你注意到的那样,走这条路。。。
我们一次又一次地存储同一个变量的地址。
重复使用同一列表的另一个条目的内存位置是上述风险的极端情况。
我像预期的那样使用辅助数组解决了这个问题。如果有人提出一个更好的解决方案,那将是非常受欢迎的。