【问题标题】:implementing a push method of stack in C programming在C编程中实现堆栈的push方法
【发布时间】:2018-06-10 08:06:23
【问题描述】:

开发者! 我对 C 中堆栈的 push() 方法有疑问!

我在 C 中实现了自己的 push() 方法! 但我无法理解结果!

下面是我的堆栈代码

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

#define MAX_SIZE 10

int top = -1;
int array[MAX_SIZE];

void init(){
    top = -1;
}

void push(int array[], int data){

    if(top > MAX_SIZE-1)
        fprintf(stderr, "invalid top %d\n", top+1);
    else{
        array[++top] = data; // top == 9, ++top == 10
        printf("top: %d data: %d\n", top+1, array[top]); // top == 11, top == 10
    }
}
void pop(int array[]){

}
void peek(int array[]){

}

int main() {
   int data = 1;

   for (int i=0; i<MAX_SIZE; i++)
        push(array, data++);
   push(array, 100);
   push(array, 200); // invalid top
   push(array, 300); // invalid top
   return 0;
}

这段代码的结果如下

top: 1 data: 1
top: 2 data: 2
top: 3 data: 3
top: 4 data: 4
top: 5 data: 5
top: 6 data: 6
top: 7 data: 7
top: 8 data: 8
top: 9 data: 9
top: 10 data: 10
top: 11 data: 100
invalid top 11 
invalid top 11

我不明白的是.. 结果,当 top: 11 时,实际上就像 top: top+1。 如果您查看我的 push() 方法中的 else 语句,您会注意到它。

但是,在 else 语句中, 当

printf("top: %d data: %d\n", 11, array[10]);
the result: top: 11 data: 100

,我认为这应该是一个错误。因为我将数组大小声明为 10,即 MAX_SIZE。所以索引大小将是 0 ~ 9。 但是 array[10] 怎么工作??

我真的不明白。

【问题讨论】:

  • C 没有任何边界检查。它不会检查您是否访问了非法内存位置。 array[10] 无效。使用它会调用未定义的行为。基本上任何事情都可能发生,比如崩溃、垃圾值等

标签: c data-structures stack


【解决方案1】:

您可以这样做,因为 C 允许您这样做。但是您不应该这样做,因为在未分配的内存区域中写入是危险的。您的数组已分配 10 个整数长度。分配内存的 10 个整数。您尝试访问的第 11 个整数没有为其分配内存。

如评论中所述,如果您希望代码抛出错误,您想要的功能是绑定检查。这正是您在 push 函数的第一部分所做的。

将您的条件更改为top &gt;= MAX_SIZE - 1 以解决问题。

至于实现堆栈的更好方法,您可以尝试在链表之上实现一个,这样您就可以在不连续的内存区域中管理您的堆栈。

您也可以将unsigned int 用于数组索引,因为那里不需要负数。

【讨论】:

    【解决方案2】:

    您确实需要学习基本的调试。例如,最基本的事情是找出代码中某些点的值。这可以通过调试器或简单的打印语句来完成。

    我这样做了:

    void push(int array[], int data){
        printf("%d\n", top);
    
        if(top > MAX_SIZE-1)
            fprintf(stderr, "invalid top %d\n", top+1);
        else{
            array[++top] = data; // top == 9, ++top == 10
            printf("top: %d data: %d\n", top+1, array[top]); // top == 11, top == 10
        }
    }
    

    得到了这个输出:

    ...
    top: 9 data: 9
    8
    top: 10 data: 10
    9
    top: 11 data: 100
    10
    invalid top 11
    10
    invalid top 11
    

    现在问题出在哪里应该很明显了。

    我认为这应该是一个错误。因为我将数组大小声明为 10,即 MAX_SIZE。所以索引大小将是 0 ~ 9。但是 array[10] 怎么工作??

    它不起作用。它确实“工作”。越界访问会导致未定义的行为。阅读此处了解更多信息:https://stackoverflow.com/a/4105123/6699433

    【讨论】:

      【解决方案3】:

      实际上,在您的代码中,top 是 -1,而与 max_size-1 比较意味着 9,条件为真,直到 top 的值为 9。这意味着 top=-1,0,1,2 的 10 次,3,4,5,6,7,8.因此,直到数组[10]有效。

      试试下面的代码。

        #include <stdio.h>
      #include <stdlib.h>
      
      #define MAX_SIZE 10
      
      int top = -1;
      int array[MAX_SIZE];
      
      void init(){
          top = -1;
      }
      
      void push(int array[], int data){
      ++top;
          if(top > MAX_SIZE-1)
              fprintf(stderr, "invalid top %d\n", top+1);
          else{
              array[top] = data; // top == 9, ++top == 10
              printf("top: %d data: %d\n", top+1, array[top]); // top == 11, top == 10
          }
      }
      void pop(int array[]){
      
      }
      void peek(int array[]){
      
      }
      
      int main() {
         int data = 1;
      
         for (int i=0; i<MAX_SIZE; i++)
              push(array, data++);
         push(array, 100);
         push(array, 200); // invalid top
         push(array, 300); // invalid top
         return 0;
      }
      

      我想这就是你想要的。

      top: 1 data: 1                                                                                                                                                                               
      top: 2 data: 2                                                                                                                                                                               
      top: 3 data: 3                                                                                                                                                                               
      top: 4 data: 4                                                                                                                                                                               
      top: 5 data: 5                                                                                                                                                                               
      top: 6 data: 6                                                                                                                                                                               
      top: 7 data: 7                                                                                                                                                                               
      top: 8 data: 8                                                                                                                                                                               
      top: 9 data: 9                                                                                                                                                                               
      top: 10 data: 10         
      invalid top 11                                                                                                                                                                              
      invalid top 12                                                                                                                                                                              
      invalid top 13  
      

      【讨论】:

      • 嘿,我对你的评论感到困惑。我用过++顶。所以数组[++top] 的开头将是数组[0]。所以会是 array[0] ~ array[9] 不是吗?
      • 哦,对不起!我很困惑!!我现在明白了。谢谢 !! :)
      • 如果你这样做,如果堆栈已满,你必须重置top的值。
      【解决方案4】:

      作为其他答案的补充,我想使用结构向您的堆栈添加更方便的实现。程序的行为发生了一点变化,可能是想要的。

      #include <stdio.h>
      
      #define MAX_SIZE 10
      
      typedef struct Stack Stack;
      void stackPush(Stack* s, int data);
      
      struct Stack{
          unsigned int head;
          int arr[MAX_SIZE];
      
          void(*push)(Stack* s, int data);
      };
      
      void stackPush(Stack* s, int data) {
          if (s->head < MAX_SIZE) {
              s->arr[s->head] = data;  // push to stack
              printf("Head: %d. Data: %d.\n", s->head, s->arr[s->head]); 
              s->head++;  // move forward
          }
      
          else
              fprintf(stderr, "Stack is full! (head at: %d)\n", s->head);
      }
      
      int main() {
          // Initialize the stack
          Stack s;
          s.head = 0;
          s.push = stackPush;
      
          // Push the data
          int data = 1;
      
          int i;
          for (i = 0; i < MAX_SIZE; i++)
              s.push(&s, data++);
      
          s.push(&s, 100); // 
          s.push(&s, 200); // trying to push to a full stack
          s.push(&s, 300); // 
      
          return 0;
      }
      

      哪个会输出

      Head: 0. Data: 1.
      Head: 1. Data: 2.
      Head: 2. Data: 3.
      Head: 3. Data: 4.
      Head: 4. Data: 5.
      Head: 5. Data: 6.
      Head: 6. Data: 7.
      Head: 7. Data: 8.
      Head: 8. Data: 9.
      Head: 9. Data: 10.
      Stack is full! (head at: 10)
      Stack is full! (head at: 10)
      Stack is full! (head at: 10)
      

      【讨论】:

      • 我完全不知道这种方式!很酷。真的感谢。这对我帮助很大。
      猜你喜欢
      • 2020-09-13
      • 2011-05-04
      • 1970-01-01
      • 2010-11-27
      • 1970-01-01
      • 1970-01-01
      • 2021-02-09
      • 1970-01-01
      • 2014-04-22
      相关资源
      最近更新 更多