1

stack を表す 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、自分のアプリケーションで使用する s を分離したい場合は、OO 言語で 2 つのインスタンスを作成します。しかし、C では、このようなシナリオをどのように処理しますか?

Cコードで2つの別々の を使用したいとしstackます...上記のコードでは、どうすればよいでしょうか?

4

7 に答える 7

10

配列arrを a の中に入れstructます。

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

この構造体がインスタンスになります。その後、スタックで宣言できます。

struct stack mystack;

またはヒープ上でmalloc

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

また、インスタンスを操作する関数の最初のパラメーターとして、インスタンスへのポインターを渡す必要があります。

于 2009-08-07T10:33:27.013 に答える
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);
}
于 2009-08-07T10:42:07.527 に答える
3

1 つの (非常に単純な) 方法は、スタックを表す構造体を定義することです。

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 に追加しました。)

于 2009-08-07T10:43:05.530 に答える
1

「this」ポインターを明示的にするだけです。

struct stack* create_stack();
void push(struct stack* mystack, int n);
void pop(struct stack* mystack, int* n);
于 2009-08-07T10:34:28.993 に答える
1

このペーパーがお役に立てば幸いです。それはあなたの質問に複数の答えを与えます:)

猫を積み重ねる16の方法

于 2009-08-07T10:35:20.397 に答える
0

動的に割り当てられた structre-per-instance が正しい方法です。詳細点 - より一般的に使用される API を作成している場合は、抽象化を向上させるためにデータ隠蔽を行うことをお勧めします。これを行う最も簡単な方法は、内部構造の定義を C ファイル (またはプライベート ヘッダー ファイル) に保持し、(たとえば) ' stack_handle_t' への void ポインターを typedef することです。「コンストラクター」から返され、他の各関数に渡されるのはこの型です。実装は、ハンドルの値が実際には構造体へのポインターであることを認識しており、各関数の開始時に次のことを行うだけです。

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

それよりもさらに優れているのは、代わりに内部的に割り当てられた識別子を使用することです。これは、これらの構造体の配列へのインデックスであろうと、構造体の (リンクされた?) リストの 1 つと照合できる単なる識別子であろうと。プロジェクトの内部でのみ使用する場合、明らかにこれはすべて無関係です。そのような状況では、不必要な作業と過度の複雑さを生み出しているだけです。

于 2009-08-08T13:02:08.563 に答える
0

この他の質問に対する私の回答には、C での OO データ バッファー構造の完全な動作例があります。

于 2009-08-08T02:56:17.990 に答える