【问题标题】:How to use multiple data types within the same ADT in C?如何在 C 中的同一个 ADT 中使用多种数据类型?
【发布时间】:2017-12-11 01:38:22
【问题描述】:

例如,如果我在 C 中定义了 Stack ADT,通常我的类型定义 - 使用基于数组的实现 - 是这样的:

typedef char StackEntry;

typedef struct stack {
    int top;
    StackEntry entry[MAXSTACK];
} Stack;

我怎样才能使我的堆栈,以便我可以有一个堆栈用于字符和另一个堆栈 - 在同一个程序中 - 例如处理整数?

【问题讨论】:

  • 听起来你在谈论泛型。它们在 C 中不存在,但您可以通过宏在某种程度上模拟它们。
  • 您必须使用宏来实现类似 C++ 模板之类的东西(因为这是 C 支持的唯一元编程工具)。
  • 您可以为泛型类型实现它,只要它们具有相同的大小。 (非异构,即。或者:我们的指针和智能联合)
  • 在创建特定的 ADT 实例时,通常通过提供所需的操作(以函数指针的形式)来完成,如赋值、比较、分配、释放等。
  • @melpomene 通用数据结构绝对可以在不使用宏的情况下在 C 中实现。

标签: c data-structures struct


【解决方案1】:

您可以使用一个堆栈结构,该结构使用元素的大小进行初始化,并以字节为单位保留一个内存块来存储元素:

typedef struct stack {
    int top;
    size_t size;
    size_t maxElems;
    char content[];
} Stack;

Stack *createStack(size_t size, size_t maxElems) {
    Stack *result = malloc(sizeof(Stack)+size*maxElems);
    result->top=0;
    result->size=size;
    result->maxElems=maxElems;
    return result;
}

int push(Stack *stack, void *elem) {
    if (stack->top == stack->maxElems)
        return -1;

    memcpy(stack->content + stack->top * stack->size, elem, stack->size);
    stack->top++;
    return stack->top;
}

int pop(Stack *stack, void *elem) {
    if (stack->top == 0)
        return -1;

    stack->top--;
    memcpy(elem, stack->content + stack->top * stack->size, stack->size);
    return stack->top;
}

int main() {

    Stack *charStack = createStack(sizeof(char), 10);
    for (int i=0; i<10; i++) {
        char c = 'A'+i;
        push(charStack, &c);
    }
    char c;
    while (pop(charStack, &c) >= 0) {
        printf("%c\n", c);
    }
    free(charStack);

    Stack *intStack = createStack(sizeof(int), 10);
    for (int i=0; i<10; i++) {
        push(intStack, &i);
    }
    int i;
    while (pop(intStack, &i) >= 0) {
        printf("%d\n", i);
    }
    free(intStack);
}

【讨论】:

    【解决方案2】:

    使用宏,例如

    #define STACK_TYPE(type) struct { int top; type entry[MAXSTACK]; }
    

    您很可能最终也会使用宏来进行堆栈操作,例如 push/pop:

    #define STACK_PUSH(stack, value) \
        do { if ( (top) < MAXSTACK ) (stack).entry[(stack).top++] = (value); } while (0)
    

    在大多数情况下,您不需要将堆栈类型作为宏参数传递,因为相同的语法适用于所有堆栈。

    示例用法:

    STACK_TYPE(int) mystack = { 0 };
    STACK_PUSH(mystack, 5);
    

    显然有很多不同的方法可以处理细节。

    【讨论】:

      猜你喜欢
      • 2021-09-06
      • 1970-01-01
      • 2021-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多