C:你如何模拟'实例'?

时间:2009-08-07 10:29:21

标签: c stack oop instance

假设我在C中有以下代码表示堆栈:

#define MAX 1000

int arr[MAX];
static int counter = 0;
isstackempty()
{
    return counter <= 0;
}
void push(int n)
{
    if (counter >= MAX) {
        printf("Stack is full.  Couldn't push %d", n);
        return;
    }
    arr[counter++] = n;
}

int pop(int* n)
{
    if(isstackempty() || n == 0) {
        printf("Stack is empty\n");
        return 0;
    }
    *n = arr[--counter];
    return 1;
}

以上代码位于stack.c文件中,函数原型位于标题中。


现在,来自C#和OO背景,如果我想将stack分开以在我的应用程序中使用,那么在OO语言中我将创建两个实例。但在C语言中,你如何处理这种情况呢?

说我想在我的C代码中使用两个单独的stack ...使用上面的代码,我将如何处理它?<​​/ p>

7 个答案:

答案 0 :(得分:10)

将数组arr放入struct

struct stack {
    int arr[MAX];
    ...
}

此结构成为您的实例。然后,您可以在堆栈中声明它:

struct stack mystack;

或使用malloc在堆上:

struct stack *mystack = malloc(sizeof(struct stack));

您还需要将指向实例的指针作为操作实例的任何函数的第一个参数传递。

答案 1 :(得分:7)

执行此操作的C方法是将“对象”的所有状态包装到结构中,然后将其显式传递给所有在堆栈上运行的函数,因此它应该是:

typedef struct _stack {
  int arr[MAX];
  int counter;
} stack;

int isstackempty(stack *s)
{
    return s->counter <= 0;
}

int push(stack *s, int n)
{
    if (s->counter >= MAX) {
        printf("Stack is full.  Couldn't push %d", n);
        return -1;
    }
    arr[s->counter++] = n;
    return 0
}

int pop(stack *s, int *n)
{
    if(isstackempty(s) || n == 0) {
        printf("Stack is empty\n");
        return -1;
    }
    *n = arr[--s->counter];
    return 0;
}

你的例子的问题是你正在编写函数定义,就像我们有一个基于类的对象结构,C没有。考虑如何在C中完成它的最简单的方法是你正在编写需要你明确传入'this'参数的方法。

此外,您可以拥有等效的构造函数和析构函数,这可以进一步抽象您的“对象”。

stack* newStack() {
    stack* s = malloc(sizeof(stack));
    s->counter = 0;
    return s;
}

void freeStack(stack* s) {
    free(s);
}

答案 2 :(得分:3)

一种(非常简单)的方法是定义一个表示堆栈的结构:

typedef struct {
    int arr[MAX];
    int counter = 0;
} myStack;

然后重写push()pop()以对myStack的实例进行操作:

int push(myStack *s, int n)
{
    if (s->counter >= MAX) {
        printf("Stack is full.  Couldn't push %d", n);
        return -1;
    }
    s->arr[(s->counter)++] = n;
    return s->counter;
}

int pop(myStack *s, int* n)
{
    if(0 == s->counter || 0 == n) {
        printf("Stack is empty\n");
        return -1;
    }
    *n = s->arr[--(s->counter)];
    return 1;
}

(还向push()添加了有意义的返回值和错误值.YMMV。)

答案 3 :(得分:1)

只需明确指出'this'指针:

struct stack* create_stack();
void push(struct stack* mystack, int n);
void pop(struct stack* mystack, int* n);

答案 4 :(得分:1)

我希望你觉得这篇论文很有用。它为您的问题提供了多个答案:)

  

Sixteen Ways to Stack a Cat

答案 5 :(得分:0)

我的answer to this other question有一个C的OO数据缓冲结构的完整工作示例。

答案 6 :(得分:0)

动态分配的每个实例的structre是正确的方法。详细点 - 如果您正在编写更常用的API,那么为了更好的抽象而进行数据隐藏可能是个好主意。 最简单的方法是在C文件(或私有头文件)中保留内部结构的定义,并键入一个指向(例如)“stack_handle_t”的void指针。这种类型是从“构造函数”返回的,并传回给其他函数。 实现意识到句柄的值实际上是指向结构的指针,并且在每个函数的开头只是这样:

int pop(stack_handle_t handle, int* n)
{
    stack *p_stack = (stack *)handle;
    ...

更好的是使用内部分配的标识符,这是否是这些结构数组的索引,或者只是一个可以与(链接的?)结构列表之一匹配的标识符。 显然所有这些都是无关紧要的,只要它只用于你的项目内部,在这种情况下它只是做了不必要的工作和过度复杂。