2009-08-07 4 views
1

のは、私は、スタックを表しCに次のコードを持っているとしましょう: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背景から来て、私は2つのインスタンスを作成しますオブジェクト指向言語では、自分のアプリケーションで使用するstack Sを分離したい場合。しかし、Cでは、どのようにこのようなシナリオを扱いますか?

は、上記のコードで、私はそれについてどのように行くだろう...私は私のCコードに二つの別々の stack Sを使用したいと?

+1

@ 01、私のタイトルはそのままです。私は私の質問は、C –

+0

重複を指定する必要があります:http://stackoverflow.com/questions/674722/struggling-with-c-coming-from-object-oriented-land –

+0

@ドレスグレッチ:質問は、 **タイトルで繰り返される**はありません。 –

答えて

10

struct内の配列arrを置きます。

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

この構造体はインスタンスになります。あなたは、スタック上でそれを宣言することができます。

struct stack mystack; 

mallocを使用してヒープ上:

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

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

+1

より良いですが、構造体に名前をつけるためにtypedefを使用してください。 –

+0

@Neil:あなたは正しいと思いますが、誰もがそうは思いません。 – JesperE

+0

@Jesper Really?私はその意見で誰も会ったことがない。 –

1

単にあなたのthisポインタを明示的に:

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

しかし、voidの代わりに適切なタイプを使用してください。 – JesperE

1

を私はあなたがこの論文が役に立つことを願っ。これは、あなたの質問に複数の回答を提供します:)

Sixteen Ways to Stack a Cat

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'パラメータを明示的に渡す必要があるメソッドを記述することです。

また、コンストラクタとデストラクタに相当するものを持つことができます。コンストラクタとデストラクタは、オブジェクトをさらに抽象化することができます。

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

、次いでmyStackのインスタンス上で動作するようにpush()pop()を書き換える:それについて行くの

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

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

あなたのtypedefで_stackをスキップすることができます: 'typedef struct {...} stack;' – JesperE

+0

ああ、本当です。習慣の力は私が自己引用構造体を定義するのに慣れていたからです。しかし、これを省略するのは少し洗練されたものでしょう。 – Falaina

3

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

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。)

0

マイanswer to this other questionは、動的に割り当てられたstructreあたりのインスタンスが移動するための正しい方法であるC.

0

におけるOOデータバッファ構造の完全な実施例を有しています。詳細な点 - より一般的に使用されているAPIを作成している場合は、データを隠蔽してよりよい抽象化を行うことをお勧めします。 これを行う最も簡単な方法は、Cファイル(またはプライベートヘッダファイル)の内部構造の定義を保持し、voidのポインタ(例えば、 'stack_handle_t')をtypedefします。これはあなたの 'コンストラクタ'から返され、それぞれの関数に返されるこの型です。すなわちかどうか、代わりに内部的に割り当てられた識別子を使用するよりも

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

さらに良い: 実装では、ハンドルの値が実際にある構造に、各関数の先頭にポインタが単にないことを認識していますこれは、これらの構造体の配列へのインデックスか、単に構造体のリスト(リンクされた?)のリストと照合できる識別子です。 明らかに、プロジェクトの内部でのみ使用する場合は、不要な作業や複雑な作業をしているだけであれば、これは無関係です。

関連する問題