简体   繁体   English

经过一定程度的有意溢出和最高自动清除后,C语言中的多堆栈程序显示了错误的元素

[英]Multiple stack program in C Language shows incorrect element after a certain amount of intentional overflows and toppermost autoremovals

Here's the C program I'm working on right now, which should let users to handle up to 5 stacks at a go and it will autoremove the toppermost item before adding the user-specified number if the stack in question is full. 这是我现在正在使用的C程序,该程序应允许用户一次最多处理5个堆栈,并且如果有问题的堆栈已满,它将在添加用户指定的编号之前自动删除最上面的项目。 However it's been plagued by a kraken in which after 3 or more distinct stacks are intentionally overflowed and thus triggering the autoremoval function, the "show all elements at all stacks" function would begin to display incorrect results instead. 但是,它一直受到海妖的困扰,其中有意溢出3个或更多不同的堆栈并触发自动删除功能后,“显示所有堆栈中的所有元素”功能将开始显示错误的结果。

Either I've missed something or a poltergeist kraken at play. 我要么错过了什么,要么在玩耍时狂妄自大。

Source code: 源代码:

#include <stdio.h>
#include <malloc.h>
#define MAX 4
int stack[MAX], topA = -1;
int stackb[MAX], topB = -1;
int stackc[MAX], topC = -1;
int stackd[MAX], topD = -1;
int stacke[MAX], topE = -1;

void pushA(int val)
{
    if (topA == MAX)
    {
        int vala = val;
        printf("\n Bin 0 full! Removing the toppest one and proceeds to add the specified item");
        val = 0;
        val = stack[topA];
        topA--;
        stack[topA + 1] = vala;
        topA++;
        vala = 0;
    }
    else
    {
        stack[topA + 1] = val;
        topA++;
    }
}

int popA()
{
    int val;
    if (topA == -1)
    {
        printf("\n Underflow");
    }
    else
    {
        val = stack[topA];
        topA--;
    }
    return val;
}

void display_stackA()
{
    int i;
    if (topA == -1)
        printf("\n Stack A is empty");
    else
    {
        for (i = topA; i >= 0; i--)
            printf("\t %d", stack[i]);
    }
}

void pushB(int val)
{
    if (topB == MAX)
    {
        int valb = val;
        printf("\n Bin 1 full! Removing the toppest one and proceeds to add the specified item");
        val = 0;
        val = stackb[topB];
        topB--;
        stackb[topB + 1] = valb;
        topB++;
        valb = 0;
    }
    else
    {
        stackb[topB + 1] = val;
        topB++;
    }
}

int popB()
{
    int val;
    if (topB == -1)
    {
        printf("\n Underflow");
    }
    else
    {
        val = stackb[topB];
        topB--;
    }
}

void display_stackB()
{
    int i;
    if (topB == -1)
        printf("\n Stack B is Empty");
    else
    {
        for (i = topB; i >= 0; i--)
            printf("\t %d", stackb[i]);
    }
}

void pushC(int val)
{
    if (topC == MAX)
    {
        int valc = val;
        printf("\n Bin 2 full! Removing the toppest one and proceeds to add the specified item");
        val = 0;
        val = stackc[topC];
        topC--;
        stackc[topC + 1] = valc;
        topC++;
        valc = 0;
    }
    else
    {
        stackc[topC + 1] = val;
        topC++;
    }
}

int popC()
{
    int val;
    if (topC == -1)
    {
        printf("\n Underflow");
    }
    else
    {
        val = stackc[topC];
        topC--;
    }
}

void display_stackC()
{
    int i;
    if (topC == -1)
        printf("\n Stack C is Empty");
    else
    {
        for (i = topC; i >= 0; i--)
            printf("\t %d", stackc[i]);
    }
}

void pushD(int val)
{
    if (topD == MAX)
    {
        int vald = val;
        printf("\n Bin 3 full! Removing the toppest one and proceeds to add the specified item");
        val = 0;
        val = stackd[topD];
        topD--;
        stackd[topD + 1] = vald;
        topD++;
        vald = 0;
    }
    else
    {
        stackd[topD + 1] = val;
        topD++;
    }
}

int popD()
{
    int val;
    if (topD == -1)
    {
        printf("\n Underflow");
    }
    else
    {
        val = stackd[topD];
        topD--;
    }
}

void display_stackD()
{
    int i;
    if (topD == -1)
        printf("\n Stack D is Empty");
    else
    {
        for (i = topD; i >= 0; i--)
            printf("\t %d", stackd[i]);
    }
}

void pushE(int val)
{
    if (topE == MAX)
    {
        int vale = val;
        printf("\n Bin 4 full! Removing the toppest one and proceeds to add the specified item");
        val = 0;
        val = stacke[topE];
        topE--;
        stacke[topE + 1] = vale;
        topE++;
        vale = 0;
    }
    else
    {
        stacke[topE + 1] = val;
        topE++;
    }
}

int popE()
{
    int val;
    if (topE == -1)
    {
        printf("\n Underflow");
    }
    else
    {
        val = stacke[topE];
        topE--;
    }
}

void display_stackE()
{
    int i;
    if (topE == -1)
        printf("\n Stack E is Empty");
    else
    {
        for (i = topE; i >= 0; i--)
            printf("\t %d", stacke[i]);
    }
}

int main()
{
    int option, options, val;
    val = 0;
    do
    {
        printf("\n -----Menu----- ");
        printf("\n 1. PUSH a element");
        printf("\n 2. POP a element");
        printf("\n 3. Display all items");
        printf("\n 4. Exit");
        printf("\n Enter your choice");
        scanf("%d", &option);
        if (option == 1)
        {
            printf("\n Select ID no (0-4)");
            scanf("%d", &options);
            printf("\n Enter the value to push on your selected id:");
            scanf("%d", &val);
            if (options == 0)
            {
                pushA(val);
            }
            if (options == 1)
            {
                pushB(val);
            }

            if (options == 2)
            {
                pushC(val);
            }

            if (options == 3)
            {
                pushD(val);
            }

            if (options == 4)
            {
                pushE(val);
            }
        }

        if (option == 2)
        {
            printf("\n Select ID no (0-4) to pop");
            scanf("%d", &options);
            if (options == 0)
            {
                printf("\n Toppest item popped from ID 0");
                popA();
            }

            if (options == 1)
            {
                printf("\n Toppest item popped from ID 1");
                popB();
            }

            if (options == 2)
            {
                printf("\n Toppest item popped from ID 2");
                popC();
            }

            if (options == 3)
            {
                printf("\n Toppest item popped from ID 3");
                popD();
            }

            if (options == 4)
            {
                printf("\n Toppest item popped from ID 4");
                popE();
            }
        }

        if (option == 3)
        {
            printf("\n The contents of ID 0 are :\n");
            display_stackA();
            printf("\n The contents of ID 1 are :\n");
            display_stackB();
            printf("\n The contents of ID 2 are :\n");
            display_stackC();
            printf("\n The contents of ID 3 are :\n");
            display_stackD();
            printf("\n The contents of ID 4 are :\n");
            display_stackE();
        }
    } while (option != 4);
    return 0;
}

Output: 输出:

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)0

 Enter the value to push on your selected id:1

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)0

 Enter the value to push on your selected id:2

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)0

 Enter the value to push on your selected id:3

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)0

 Enter the value to push on your selected id:4

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)0

 Enter the value to push on your selected id:5

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice3

 The contents of ID 0 are :
         5       4       3       2       1
 The contents of ID 1 are :

 Stack B is Empty
 The contents of ID 2 are :

 Stack C is Empty
 The contents of ID 3 are :

 Stack D is Empty
 The contents of ID 4 are :

 Stack E is Empty
 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)0

 Enter the value to push on your selected id:6

 Bin 0 full! Removing the toppest one and proceeds to add the specified item
 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice3

 The contents of ID 0 are :
         6       4       3       2       1
 The contents of ID 1 are :

 Stack B is Empty
 The contents of ID 2 are :

 Stack C is Empty
 The contents of ID 3 are :

 Stack D is Empty
 The contents of ID 4 are :

 Stack E is Empty
 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)1

 Enter the value to push on your selected id:1

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)1

 Enter the value to push on your selected id:2

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)1

 Enter the value to push on your selected id:3

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)1

 Enter the value to push on your selected id:4

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)1

 Enter the value to push on your selected id:5

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)1

 Enter the value to push on your selected id:6

 Bin 1 full! Removing the toppest one and proceeds to add the specified item
 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice3

 The contents of ID 0 are :
         6       4       3       2       1
 The contents of ID 1 are :
         6       4       3       2       1
 The contents of ID 2 are :

 Stack C is Empty
 The contents of ID 3 are :

 Stack D is Empty
 The contents of ID 4 are :

 Stack E is Empty
 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)2

 Enter the value to push on your selected id:1

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice3

 The contents of ID 0 are :
         6       4       3       2       1
 The contents of ID 1 are :
         6       4       3       2       1
 The contents of ID 2 are :
         1
 The contents of ID 3 are :

 Stack D is Empty
 The contents of ID 4 are :

 Stack E is Empty
 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)2

 Enter the value to push on your selected id:2

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)2

 Enter the value to push on your selected id:3

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice3

 The contents of ID 0 are :
         6       4       3       2       1
 The contents of ID 1 are :
         6       4       3       2       1
 The contents of ID 2 are :
         3       2       1
 The contents of ID 3 are :

 Stack D is Empty
 The contents of ID 4 are :

 Stack E is Empty
 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)2

 Enter the value to push on your selected id:4

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)2

 Enter the value to push on your selected id:5

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)2

 Enter the value to push on your selected id:6

 Bin 2 full! Removing the toppest one and proceeds to add the specified item
 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice3

 The contents of ID 0 are :
         6       4       3       2       1
 The contents of ID 1 are :
         6       4       3       2       6
 The contents of ID 2 are :
         6       4       3       2       1
 The contents of ID 3 are :

 Stack D is Empty
 The contents of ID 4 are :

 Stack E is Empty
 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)3

 Enter the value to push on your selected id:1

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)3

 Enter the value to push on your selected id:2

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)3

 Enter the value to push on your selected id:3

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)3

 Enter the value to push on your selected id:4

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)3

 Enter the value to push on your selected id:5

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)3

 Enter the value to push on your selected id:6

 Bin 3 full! Removing the toppest one and proceeds to add the specified item
 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice3

 The contents of ID 0 are :
         6       4       3       2       6
 The contents of ID 1 are :
         1       4       3       2       6
 The contents of ID 2 are :
         6       4       3       2       1
 The contents of ID 3 are :
         6       4       3       2       1
 The contents of ID 4 are :

 Stack E is Empty
 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)4

 Enter the value to push on your selected id:1

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)4

 Enter the value to push on your selected id:2

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)4

 Enter the value to push on your selected id:3

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)4

 Enter the value to push on your selected id:4

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)4

 Enter the value to push on your selected id:5

 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice1

 Select ID no (0-4)4

 Enter the value to push on your selected id:6

 Bin 4 full! Removing the toppest one and proceeds to add the specified item
 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice3

 The contents of ID 0 are :
         6       4       3       2       6
 The contents of ID 1 are :
         1       4       3       2       6
 The contents of ID 2 are :
         6       4       3       2       6
 The contents of ID 3 are :
         6       4       3       2       1
 The contents of ID 4 are :
         6       4       3       2       1
 -----Menu-----
 1. PUSH a element
 2. POP a element
 3. Display all items
 4. Exit
 Enter your choice

As Jonathan says, a table declared with a size of 4 elements can only use the indices of 0 to 3. It's my day of goodness, I give you a condensed version with functions common to 5 stacks. 正如Jonathan所说,声明为4个元素的表只能使用0到3的索引。这是我的天,我为您提供了5个堆栈具有通用功能的精简版本。 I have not tested completely, but it will do you a good exercise to understand it and correct it with the recommendations of Jonathan. 我还没有完全测试过,但是通过Jonathan的建议,它可以帮助您理解和更正它。 This code can still be improved. 此代码仍可以改进。 Your turn ! 轮到你了 !

#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <assert.h>
#define STACK_QTY   5
#define MAX         4

int stack[STACK_QTY][MAX];
int top[STACK_QTY];

void push(int index, int val)
{
    assert(index < STACK_QTY);

    if(top[index] == (MAX - 1)) {
        printf("\n Bin %d full! Removing the toppest one and proceeds to add "
               "the specified item", index);
        stack[index][top[index]] = val;
    }
    else {
        stack[index][++top[index]] = val;
    }
}

int pop(int index)
{
    assert(index < STACK_QTY);

    int val = -1;

    if(top[index] == -1) {
        printf("\n Underflow");
    }
    else {
        val = stack[index][top[index]--];
    }

    return val;
}

void display_stack(int index)
{
    assert(index < STACK_QTY);

    int i;
    if(top[index] == -1) {
        printf("\n Stack %c is empty", index + 'A');
    }
    else {
        for(i = top[index]; i >= 0; i--) {
            printf("\t %d",stack[index][i]);
        }
    }
}

void option1(void)
{
    unsigned int index = -1;
    int value;

    printf("\n Select ID no (0-%d)", STACK_QTY - 1);
    scanf("%u",&index);
    if (index < STACK_QTY){
        printf("\n Enter the value to push on your selected id:");
        scanf("%u",&value);

        push(index, value);
    }
    else {
        printf("error");
    }
}

void option2(void)
{
    unsigned int index;

    printf("\n Select ID no (0-%d) to pop", STACK_QTY - 1);
    scanf("%u",&index);
    if (index < STACK_QTY){
        printf("\n Toppest item popped from ID %d", index);

        printf("\nvalue = %d\n", pop(index));
    }
    else {
        printf("error");
    }
}

void option3(void)
{
    int i;

    for (i = 0; i < STACK_QTY; ++i) {
        printf("\n The contents of ID %d are :\n", i);
        display_stack(i);
    }
}

int main()
{
    int option;

    for (int i = 0; i < STACK_QTY; ++i) {
        top[i] = -1;
    }

    do {
        printf("\n -----Menu----- ");
        printf("\n 1. PUSH a element");
        printf("\n 2. POP a element");
        printf("\n 3. Display all items");
        printf("\n 4. Exit");
        printf("\n Enter your choice");
        scanf("%d", &option);
        switch(option)  {
            case 1: option1(); break;
            case 2: option2(); break;
            case 3: option3(); break;
        }
    }
    while(option != 4);

    return 0;
}

Your stacks can only hold 4 items (because of #define MAX 4 and int stackN[MAX]; ) but you don't protect properly against overflow. 您的堆栈只能容纳4个项目(由于#define MAX 4int stackN[MAX]; ),但是您不能适当地防止溢出。 For example, if you manipulate stack A and push 37, topA is 0; 例如,如果您操纵堆栈A并推入37,则topA为0; topAtopA为0。 push 41 and topA is 1; 推41, topA为1; push 43 and topA is 2; 推43, topA为2; push 47 and topA is 3 (and the stack is full), but when you push 51, you don't hit the topA == MAX condition, so you overflow your stack — overwriting who knows what! 推动47, topA为3(堆栈已满),但是当您推动51时,您没有达到topA == MAX条件,因此您的堆栈溢出了—覆盖谁知道! (It might be one of the topN values; it might be part of another stack; neither is good, and neither is what you intended.) (它可能是topN值之一;它可能是另一个堆栈的一部分;都不是好事,也不是您想要的。)

I've got a web site for you — Stack Overflow ! 我为您提供了一个网站-Stack Overflow

The simplest fix is probably to change the semantics of topN so that it is initialized to 0 instead of -1 . 最简单的解决方法可能是更改topN的语义,以便将其初始化为0而不是-1 You then have to adjust the edge conditions in all the functions. 然后,您必须在所有功能中调整边缘条件。

You really need to avoid having so many functions (5 copies of each of 3 functions). 您确实需要避免拥有太多功能(3个功能中的每个功能有5个副本)。 That's a more major rewrite. 这是一个更主要的重写。 You should also use a structure to describe each stack. 您还应该使用一种结构来描述每个堆栈。 You're excused if you've not learned structures yet (but then you should use an array of top values a 2D array for the stack data. That would make the fixes needed much easier; you'd have 1/5th as many places to edit systematically. 如果您还没有学习过结构,那么您会被原谅(但是您应该使用一个top值数组和一个用于堆栈数据的2D数组。这将使所需的修复更加容易;您所需要的位置将是原来的1/5进行系统编辑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM