2016-05-08 3 views
1

Я занимаюсь школьным заданием, я столкнулся с двумя проблемами. Я должен имитировать стеки с массивами. Мой текущий код выглядит следующим образом: (! Пусто (myStack))C: Элемент стека, перезаписанный вызовом функции

#include <stdlib.h> 
#include <stdio.h> 

typedef struct { 
    int capacity; 
    int * array; 
    int size; 
} stack_tt; 
int pop(stack_tt * stack_p); 
void push(stack_tt * stack_p, int value); 
int top(stack_tt * stack_p); 
stack_tt * newStack(void); 
int empty(stack_tt * stack_p); 

int main() { 
    stack_tt * myStack = newStack(); 
    push(myStack, 123); 
    push(myStack, 99); 
    push(myStack, 4444); 
    while (!empty(myStack)) { 
     int value; 
     value = pop(myStack); 
     printf("popped: %d\n", value); 
    } 
    return 0; } 

stack_tt * newStack(){ 
    stack_tt * newS = malloc(sizeof(stack_tt) * 20); 
    (*newS).capacity = 1; 
    (*newS).size = 0; 
    return newS; 
} 

void push(stack_tt * stack_p, int value){ 
    if ((*stack_p).size >= (*stack_p).capacity) { 
     (*stack_p).capacity*=2; 
     //realloc(stack_p, stack_p->capacity * sizeof(stack_tt)); 
    } 
    (*stack_p).array = &value; 
    (*stack_p).size++; 
} 

int pop(stack_tt * stack_p){ 
    (*stack_p).size--; 
    int fap = *(*stack_p).array; 
    return fap; 
} 

int empty(stack_tt * stack_p){ 
    if ((*stack_p).size >= 1) 
     return 0; 
    return 1; 
} 

Кулак, когда я называю линии время Он изменяет значение в моем массиве к 1.

во-вторых я m не может изменять отдельные значения в моем массиве, всякий раз, когда я пробую такие вещи: (* stack_p) .array [0] = значение; Он не знает, где в памяти смотреть. Я надеюсь, что кто-то может помочь мне :)

ответ

0

Там нет необходимости выделять место для 20 структур типа stack_tt, вам нужно только выделить пространство для одного:

stack_tt * newS = malloc(sizeof(stack_tt)); 

однако вам нужно выделять пространство для элементов массива структурных элементов:

newS->array = malloc(sizeof(int)*20); 
newS->size = 0; 
newS->capacity = 20; 

Теперь вы можете использовать элемент массива.


Когда вы нажимаете значение в «стек», вы не должны перезаписать элемент массива с адресом локальной переменной, которая не имеет смысла и приведет к непредсказуемому поведению в добавлении расторгнув ранее выделенная память. Вместо того, чтобы просто присвоить значение члену array, в функции push:

stack_p->array[stack_p->size] = value; 
stack_p->size++; 

Аналогично, когда вы поп элемент, возьмите текущий элемент из элемента array:

stack_p->size--; 
int fap = stack_p->array[stack_p->size]; 

Остальная функций и кода должны быть установлены таким же образом.

+0

Я попробовал это, я даю мне ошибку: 'Тема 1: EXC_BAD_ACCESS (код = 1, адрес = 0x0)' – Klopper

+0

@ Клоппер. Конечно, примеры, которые я указал, не единственные проблемы. Невозможно указать каждую ошибку, потому что код неверен на концептуальном уровне. Весь проект придется переписать. Используйте примеры, которые я привел в качестве руководства. – 2501

+1

Спасибо, сейчас я вижу :) Это была отличная помощь! – Klopper

1

Есть пара проблем с кодом, который я вижу.

Позволяет взять функцию push где вы

(*stack_p).array = &value; 

Это сделает точку члена array структуры к местной переменной value, и после того, как функция возвращает переменную перестают существовать оставив вас с шальной указатель и использование этого указателя приведет к неопределенного поведения.

Вторая проблема с этим кодом заключается в том, что ваш стек будет указывать (нелегально) на последний добавленный элемент.

Вы должны выделить память явно для array и использовать capacity, чтобы отслеживать, сколько памяти выделено. Использование size в качестве индекса в выделенный массив для нажатия и выскакивания.Что-то вроде

stack_tt * newStack(){ 
    stack_tt * newS = malloc(sizeof(stack_tt)); // Only allocate *one* structure 
    newS->capacity = 0; // Start with zero capacity 
    newS->size = 0; 
    newS->array = NULL; 
    return newS; 
} 

void push(stack_tt * stack_p, int value){ 
    if (stack_p->size + 1 > stack_p->capacity){ 
     // Increase capacity by ten elements 
     int new_capacity = stack_p->capacity + 10; 
     int * temp_array = realloc(stack_p->array, new_capacity * sizeof(int)); 
     if (temp_srray == NULL) 
      return; 

     stack_p->capacity = new_capacity; 
     stack_p->array = temp_array; 
    } 

    stack_p->array[stack_p->size++] = value; 
} 

int pop(stack_tt * stack_p){ 
    if (stack_p->size > 0) 
     return stack_p->array[--stack_p->size]; 
    return 0; 
} 

int empty(stack_tt * stack_p){ 
    return stack_p->size == 0; 
} 
+0

Не могли бы вы быть любезны принять следующее редактирование в 'int pop()': 'if (stack_p-> size> 0)'. Иначе он продолжает висит в бесконечном цикле 'popped: 0'. Мне не хватает репутации, чтобы это сделать. Спасибо – user3078414

0

Вы код хороший, но, вероятно, вы не поняли использование realloc:

//realloc(stack_p, stack_p->capacity * sizeof(stack_tt)); 

This function returns a pointer to the newly allocated memory, or NULL if the request fails.

realloc (как функция предполагает) принимает указал память по указателю, который вы передаете, и копии этот блок памяти в новом и измененном размере. Так что правильный код должен быть.

stack_p->array = realloc(stack_p->array, stack_p->capacity * sizeof(stack_tt)); 

Это другая линия неправильно:

(*stack_p).array = &value; 

Изменить его:

stack_p->array[stack_p->size] = value; 

Еще немного внушения, каждый (*stack_p). можно заменить stack_p->, более элегантно.

В newStack() вы - malloc Входящие 20 структур, которые бесполезны. Вам просто нужен он.

Тогда вы должны malloc массива в первый раз:

newS->array = malloc(sizeof(int)); 
newS->capacity = 1; 
+0

Что не так с '(* stack_p) .' и почему он должен использовать' stack_p-> '? В чем преимущество последнего? – Michi

+0

Это просто более элегантный код. Элегантный код == более читаемый код и легко понять – NoImaginationGuy

+0

Когда указатели участвуют, нет различий между элегантными и читаемыми. Как вы их понимаете. – Michi