Реализовать стек с помощью указателя на указатель

#c

#c

Вопрос:

Я реализую небольшую программу для работы с двойными указателями, это основная программа:

 #include <stdio.h>
#include "serial.h"
#include "stack.h"

int main(void) {
    serial_init();  

    /* Array to hold stack entries */
    int stack[10]={0};
    /* Stack pointer */
    int *stack_p = stack;

    /* Code to call the functions */

    push(amp;stack_p, 1); 
    push(amp;stack_p, 2); 
    push(amp;stack_p, 3); 
    push(amp;stack_p, 4); 

    printf("popped value: %drn", pop(amp;stack_p));
    printf("popped value: %drn", pop(amp;stack_p));
    printf("popped value: %drn", pop(amp;stack_p));
    printf("popped value: %drn", pop(amp;stack_p));
}        

void push(int **sp, int value) {
    /*  Implement it */ 
}

int pop(int **sp) {
    /*  Implement it */ 
}
  

Я реализовал функцию push, кажется, все в порядке. Однако всплывающее окно возвращает только последний элемент, а затем 10

 void push(int **sp, int value) {
/* implemented it*/

 int *pt; 
 pt=amp;value; // Store the value to the pointer 

 printf("Push value is is %drn", *pt);
 sp = amp;pt; // associate the pointer to the pointer of pointer
   (*pt);   
}

int pop(int **sp) {
 /* implemented it */
 int value;
 int *pt;
 pt=amp;value;

 sp = amp;pt;
 *pt--;

 return value;
}   
  

Комментарии:

1. Попробуйте (*pt)-- . В противном случае операторы, направленные вправо, обычно привязываются сильнее, чем операторы, направленные влево. Кроме того, где указателю pt присваивается значение?

2. Я отформатировал часть 1 вашего кода. Почему бы вам не нажать Редактировать и аналогичным образом не отформатировать другие части? (Если вы хотите моего внимания, введите @thb и свой вопрос в комментариях. Система отметит меня.)

3. Подсказка: никогда не используйте настоящие табуляции для отступов, а только пробелы. В противном случае у вас возникнут проблемы с форматированием без использования общего доступа к коду code

4. Что заставляет вашу вещь push работать? На самом деле вы никогда ни value чему не присваиваете значение и amp;value является адресом временной копии переданного аргумента. Способ проверить, работает ли какая-либо операция, — это проверить stack массив в main() — используйте отладчик, это будет намного быстрее, чем отправлять вопросы.

Ответ №1:

Ваши функции push и pop чрезмерно сложны и совершенно неправильны:

Вы хотите это:

 void push(int **sp, int value) {
  **sp = value;   // put value onto top of the stack
  (*sp)  ;        // increment stack pointer
}

int pop(int **sp) {
  (*sp)--;        // decrement stack pointer
  return **sp;    // return value which is on nthe op of the stack
}
  

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

 void push(int **sp, int value) {
  int *pt; 
  pt=amp;value; // here you put the pointer to the local variable value
             // into pt, but local variables disappear as soon
             // as the function has finished

  //  the printf is the only thing one more or less correct
  //  but you could just print directly 'value' like this:
  //    printf("Pushed value is %drn", value);
  //
  printf("Push value is is %drn", *pt);

  sp = amp;pt;  // this only assigns the pointer to the local variable pt to 
             // the local variable sp

    (*pt);   // here you increment actually the local variable
             // value which is pointless 
}
  

Кстати: инициализация нулем всего стека не является необходимой, хотя это может помочь в процессе отладки. Таким образом, вы можете написать объявление стека следующим образом:

 int stack[10];  // no initialisation necessary
  

Упражнение для вас:

Объясните точную причину, по которой нет необходимости инициализировать все элементы стека нулем.

Комментарии:

1. Привет, спасибо. Я не знаю почему. Я прочитал и, кажется, лучший способ — инициализировать нулем, чтобы избежать мусора

2. @AntonioArnone да, это правда, но здесь, даже если вы не инициализируете нулем, вы не увидите никакого мусора там, где вы не хотите. Когда вы нажимаете, он перезапишет мусор предварительной обработки введенным значением, а когда вы всплываете, он прочитает ранее введенное значение… никакого мусора не требуется.