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

C:如何模拟';实例';?,c,stack,oop,instance,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; } ar

假设我有以下表示堆栈的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;
}
#定义最大1000
int-arr[MAX];
静态整数计数器=0;
isstackempty()
{
返回计数器=最大值){
printf(“堆栈已满。无法推送%d”,n);
返回;
}
arr[计数器++]=n;
}
int-pop(int*n)
{
if(isstackempty()| | n==0){
printf(“堆栈为空\n”);
返回0;
}
*n=arr[--计数器];
返回1;
}
上面的代码位于
stack.c
文件中,函数原型位于标题中


现在,来自C#和OO背景,如果我想分离
堆栈
s以在我的应用程序中使用,我将使用OO语言创建两个实例。但在C语言中,如何处理这种情况


假设我想在我的C代码中使用两个独立的
堆栈
s…对于上面的代码,我将如何操作?

将数组
arr
放在
结构

struct stack {
    int arr[MAX];
    ...
}
此结构将成为您的实例。然后可以在堆栈上声明它:

struct stack mystack;
或者在堆上使用
malloc

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

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

将数组
arr
放入
结构中

struct stack {
    int arr[MAX];
    ...
}
此结构将成为您的实例。然后可以在堆栈上声明它:

struct stack mystack;
或者在堆上使用
malloc

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

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

只需将“this”指针显式:

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

只需将“this”指针显式化:

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

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


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


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实现这一点的方法是将“对象”的所有状态包装到一个结构中,然后显式地将其传递到所有在堆栈上操作的函数中,因此它应该是:

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;
}
一种(非常简单的)方法是定义一个表示堆栈的结构:

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]添加了一个有意义的返回值和错误值。)

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

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添加了一个有意义的返回值和错误值。)

My在C中有一个OO数据缓冲区结构的完整工作示例。

My在C中有一个OO数据缓冲区结构的完整工作示例。

每个实例动态分配的结构是正确的选择。一个细节问题——如果您正在编写一个更普遍使用的API,那么最好进行数据隐藏以实现更好的抽象。 最简单的方法是将内部结构的定义保留在C文件(或私有头文件)中,并键入一个指向(例如)“
stack\u handle\t
”的空指针。正是这种类型从“构造函数”返回,并传递回其他函数。 实现知道句柄的值实际上是一个指向结构的指针,在每个函数的开头,它只是执行以下操作:

int pop(stack_handle_t handle, int* n)
{
    stack *p_stack = (stack *)handle;
    ...
甚至比这更好的是使用内部分配的标识符,不管它是这些结构数组的索引,还是仅仅是可以与一个(链接的?)结构列表匹配的标识符。
显然,所有这些都是不相关的,如果它只是在项目内部使用,那么在这些情况下,它只是做了不必要的工作,而且过于复杂。

每个实例动态分配结构是正确的选择。一个细节问题——如果您正在编写一个更普遍使用的API,那么最好进行数据隐藏以实现更好的抽象。 最简单的方法是将内部结构的定义保留在C文件(或私有头文件)中,并键入一个指向(例如)“
stack\u handle\t
”的空指针。正是这种类型从“构造函数”返回,并传递回其他函数。 实现知道句柄的值实际上是一个指向结构的指针,在每个函数的开头,它只是执行以下操作:

int pop(stack_handle_t handle, int* n)
{
    stack *p_stack = (stack *)handle;
    ...
甚至比这更好的是使用内部分配的标识符,不管它是这些结构数组的索引,还是仅仅是可以与一个(链接的?)结构列表匹配的标识符。
显然,如果这只是在项目内部使用,那么所有这些都是无关紧要的。在这种情况下,这只是做了不必要的工作,过于复杂。

@01,让我的标题保持原样吧。我需要指定我的问题是两个:@Dreas Grech:问题的标签不必在标题中重复。实际上,我更多地将标签视为对问题进行分组和分类的一种方式。我支持Dreas的观点-我喜欢在标题中看到语言。@01,保持我的标题原样。我需要说明我的问题是重复的:@Dreas Grech:问题的标签不需要在标题中重复。实际上,我认为标签更多的是一种对问题进行分组和分类的方式。我在这一点上支持Dreas-我喜欢看到标题中的语言。但是请使用正确的类型而不是void。但是请使用正确的类型而不是void。更好的是,使用typedef来命名问题struct@Jesper真正地我从未见过有这种观点的人。他有什么反对意见?更好的办法是,用typedef来命名struct@Jesper