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
ファイルであり、関数のプロトタイプは、ヘッダに記載されています。
さて、私は2つのインスタンスを作成しますオブジェクト指向言語では、自分のアプリケーションで使用するstack
sを分離したい場合は、C#とOO背景から来ます。しかし、Cで、どのようにこのようなシナリオに対処しますか。
私はそれについて移動する方法を、私は上記のコードで...私のCコードに二つの別々のstack
sを使用したいと?
解決
arr
内部配列struct
を置きます。
struct stack {
int arr[MAX];
...
}
この構造体には、あなたのインスタンスになります。その後、スタック上にそれを宣言することができます:
struct stack mystack;
やmalloc
を使用してヒープ上:
struct stack *mystack = malloc(sizeof(struct stack));
また、インスタンスを操作する任意の関数の最初のパラメータとしてインスタンスへのポインタを渡す必要があります。
他のヒント
はこれを行うには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で行うのかを考えるための最も簡単な方法は、あなたが明示的に「この」パラメータを渡すために必要な方法を書いているということです。
また、あなたはあなたの「オブジェクト」することができ、さらに抽象コンストラクタとデストラクタ、同等のものを持つことができます。
stack* newStack() {
stack* s = malloc(sizeof(stack));
s->counter = 0;
return s;
}
void freeStack(stack* s) {
free(s);
}
それについて行くの一つ(極端に単純化)の方法は、スタックを表し構造体を定義することです。
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;
}
(またYMMV。push()
する意味の戻り値とエラー値を追加しました。)
私はあなたがこの論文が役に立つことを願っ。それは、あなたの質問に複数の回答が得られます)。
単にあなたのthisポインタを明示的に行います。
struct stack* create_stack();
void push(struct stack* mystack, int n);
void pop(struct stack* mystack, int* n);
動的に割り当てられたstructreあたりのインスタンスが行くための正しい方法です。詳細のポイントは - あなたがより一般的に使用されるAPIを書いている場合、おそらくより良い抽象化のためのデータ隠蔽に従事することをお勧めします。
これを行う最も簡単な方法は、Cファイル(またはプライベートヘッダファイル)内の内部構造の定義を維持し、(例えば)「stack_handle_t
」にボイドポインタのtypedefです。それはあなたの「コンストラクタ」から返され、互いに関数に戻され、このタイプです。
int pop(stack_handle_t handle, int* n)
{
stack *p_stack = (stack *)handle;
...
は、これは構造体の(連結された?)リストのいずれかと照合することができ、これらの構造体または単に識別子の配列へのインデックスであるかどうか、代わりに内部的に割り当てられた識別子を使用するよりもさらに良いです。 その唯一のプロジェクトに内部で使用する場合はもちろん、このすべてはそれだけで不必要な仕事をしているような状況にして過剰な合併症、無関係です。