Question

Disons que je le code suivant dans C qui représente une pile:

#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;
}

Le code ci-dessus est dans un fichier stack.c et les prototypes de fonction sont dans un en-tête.


Maintenant, provenant d'un C # et fond OO, si je voudrais séparer stacks à utiliser dans ma demande, dans un langage OO Je voudrais créer deux instances. Mais en C, comment gérez-vous un tel scénario?

Dire que je veux utiliser deux stacks séparés dans mon code C ... avec le code ci-dessus, comment pourrais-je aller à ce sujet?

Était-ce utile?

La solution

Placez le arr tableau dans un struct.

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

Ce struct devient votre instance. Vous pouvez ensuite déclarer sur la pile:

struct stack mystack;

ou sur le tas en utilisant malloc:

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

Vous devez également passer un pointeur à l'instance comme premier paramètre à une fonction manipulant l'instance.

Autres conseils

La façon C de le faire est d'envelopper tout l'état de votre « objet » dans un struct, puis passer explicitement dans toutes les fonctions qui fonctionnent sur piles, il devrait donc être:

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;
}

Le problème avec votre exemple vous écrivez les définitions de fonctions que nous avons une structure d'objet de classe, laquelle C n'a pas. La meilleure façon de penser à la façon dont il est fait en C est que vous écrivez des méthodes que vous avez besoin de passer explicitement dans le paramètre « this ».

En outre, vous pouvez avoir l'équivalent des constructeurs et destructeurs, ce qui peut encore abstrait votre « objet ».

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

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

Une façon (très simpliste) d'aller à ce sujet est de définir une structure qui représente une pile:

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

puis réécrire push() et pop() pour fonctionner sur une instance de 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;
}

(a également ajouté une valeur significative du rendement et de la valeur d'erreur à push(). YMMV).

J'espère que vous trouverez ce document utile. Il donne plus d'une réponse à votre question:)

  

Seize façons de Empilez un chat

Il suffit de faire votre pointeur 'ce' explicite:

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

Mon réponse à cette autre question a un exemple de travail complet d'un OO structure de mémoire tampon de données en C.

Un structre-per instance allouée dynamiquement la bonne façon de procéder. Un point de détail - si vous écrivez une API utilisée de façon plus générale, il est probablement une bonne idée de se livrer à cacher des données pour une meilleure abstraction. La façon la plus simple de le faire est de garder la définition de la structure interne dans le fichier C (ou un fichier d'en-tête privé) et typedef un pointeur vide pour (par exemple) « stack_handle_t ». Il est ce type qui est retourné de votre « constructeur » et est repassée pour l'autre fonction. La mise en œuvre est consciente que la valeur de la poignée est en fait un pointeur vers une structure et au début de chaque fonction simplement:

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

Même mieux que cela consiste à utiliser un identificateur alloué à l'intérieur à la place, que ce soit un index dans un tableau de ces structs ou simplement un identifiant qui peut être appariés l'un d'un (reliée?) La liste des structs. Il est évident que tout cela est sans objet si son seul pour un usage interne à votre projet, dans ces circonstances, il est juste faire le travail inutile et trop de complications.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top