我使用指针实现了堆栈。我一直试图将它概括为与任意数据类型一起使用。我已经尝试但无法弄清楚错误数据被压入堆栈的原因。
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum action {START, PUSH, POP, TOP, LENGTH, QUIT, END};
enum status {SUCCESS, FAILURE};
typedef struct node {
void *data;
struct node *lower;
} stack_node;
typedef struct stack {
size_t elem_size;
size_t stack_size;
stack_node *top;
} stack_struct;
void clear_screen(void)
{
system("cls");
}
static enum action get_user_action(void)
{
int choice = START;
do {
clear_screen();
printf("%d Push data\n"
"%d Pop Data\n"
"%d See the top of the stack\n"
"%d See the length of the stack\n"
"%d Exit\n\n"
"Enter your choice -> ", PUSH, POP, TOP, LENGTH, QUIT);
scanf("%d", &choice);
} while (!(START < choice && choice < END));
return (enum action) choice;
}
enum status stack_create(stack_struct **stack, size_t elem_size)
{
(**stack).elem_size = elem_size;
(**stack).stack_size = 0;
(**stack).top = NULL;
return SUCCESS;
}
enum status push(stack_struct **stack, void *data)
{
stack_node *node = malloc(sizeof(node));
if (node == NULL) {
return FAILURE;
}
node->data = malloc(sizeof((**stack).elem_size));
if (node->data == NULL) {
return FAILURE;
}
memcpy(node->data, data, (**stack).elem_size);
if ((**stack).top == NULL) {
node->lower = NULL;
} else {
node->lower = (**stack).top;
}
(**stack).top = node;
(**stack).stack_size += 1;
return SUCCESS;
}
enum status pop(stack_struct *stack, void *data)
{
if (stack->top == NULL) {
return FAILURE;
}
stack_node *node = stack->top;
memcpy(data, node->data, stack->elem_size);
stack->top = node->lower;
free(node->data);
free(node);
stack->stack_size -= 1;
return SUCCESS;
}
enum status peek(stack_struct *stack, void *data)
{
if (stack->top == NULL) {
return FAILURE;
}
memcpy(data, stack->top->data, stack->elem_size);
return SUCCESS;
}
void stack_delete(stack_struct *stack)
{
while (stack->top != NULL)
{
stack_node *node = stack->top;
stack->top = stack->top->lower;
free(node->data);
free(node);
}
}
int main(void)
{
enum action choice;
stack_struct *stack = malloc(sizeof(stack_struct));
if (stack == NULL)
{
printf("Not enough memory\n");
return 1;
}
stack_create(&stack, sizeof(int));
while ((choice = get_user_action()) != QUIT) {
clear_screen();
int data;
switch (choice) {
case PUSH:
printf("Enter data to be pushed -> ");
scanf("%d", &data);
if (push(&stack, &data) == SUCCESS){
printf("%d pushed onto the stack", (int)stack->top->data);
} else {
printf("Not enough memory\n");
}
break;
case POP:
if (pop(stack, &data) == SUCCESS){
printf("The data is %d\n", data);
} else {
printf("Stack underflow\n");
}
break;
case TOP:
if (peek(stack, &data) == SUCCESS){
printf("The data at top is %d\n", data);
} else {
printf("Nothing in the stack\n");
}
break;
case LENGTH:
printf("Length is %d\n", stack->stack_size);
break;
default:
assert(!"You should not have reached this.\n");
}
stack_delete(stack);
getchar();
getchar();
}
}
我按234并获得垃圾值。
更新1
我有一个使用指针的堆栈工作副本。它不适用于任意数据类型,仅适用于int
。它can be viewed on codereview我想到了为任意数据制作它。
更新2
在p0w指出printf
中的main
不正确后,我更正了。我还更改了pop
,peek
和stack_delete
函数,以便指向指向struct
的指针。
printf
表示正在传递正确的数据,但pop
和peek
不这么认为。
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum action {START, PUSH, POP, TOP, LENGTH, QUIT, END};
enum status {SUCCESS, FAILURE};
typedef struct node {
void *data;
struct node *lower;
} stack_node;
typedef struct stack {
size_t elem_size;
size_t stack_size;
stack_node *top;
} stack_struct;
void clear_screen(void)
{
system("cls");
}
static enum action get_user_action(void)
{
int choice = START;
do {
clear_screen();
printf("%d Push data\n"
"%d Pop Data\n"
"%d See the top of the stack\n"
"%d See the length of the stack\n"
"%d Exit\n\n"
"Enter your choice -> ", PUSH, POP, TOP, LENGTH, QUIT);
scanf("%d", &choice);
} while (!(START < choice && choice < END));
return (enum action) choice;
}
enum status stack_create(stack_struct **stack, size_t elem_size)
{
(**stack).elem_size = elem_size;
(**stack).stack_size = 0;
(**stack).top = NULL;
return SUCCESS;
}
enum status push(stack_struct **stack, void *data)
{
stack_node *node = malloc(sizeof(node));
if (node == NULL) {
return FAILURE;
}
node->data = malloc(sizeof((**stack).elem_size));
if (node->data == NULL) {
return FAILURE;
}
memcpy(node->data, data, (**stack).elem_size);
if ((**stack).top == NULL) {
node->lower = NULL;
} else {
node->lower = (**stack).top;
}
(**stack).top = node;
(**stack).stack_size += 1;
return SUCCESS;
}
enum status pop(stack_struct **stack, void *data)
{
if ((**stack).top == NULL) {
return FAILURE;
}
stack_node *node = (**stack).top;
memcpy(data, node->data, (**stack).elem_size);
(**stack).top = node->lower;
node->lower = NULL;
free(node->data);
free(node);
(**stack).stack_size -= 1;
return SUCCESS;
}
enum status peek(stack_struct **stack, void *data)
{
if ((**stack).top == NULL) {
return FAILURE;
}
memcpy(data, (**stack).top->data, (**stack).elem_size);
return SUCCESS;
}
void stack_delete(stack_struct **stack)
{
while ((**stack).top != NULL)
{
stack_node *node = (**stack).top;
(**stack).top = (**stack).top->lower;
free(node->data);
free(node);
}
}
int main(void)
{
enum action choice;
stack_struct *stack = malloc(sizeof(stack_struct));
if (stack == NULL)
{
printf("Not enough memory\n");
return 1;
}
stack_create(&stack, sizeof(int));
while ((choice = get_user_action()) != QUIT) {
clear_screen();
int data;
switch (choice) {
case PUSH:
printf("Enter data to be pushed -> ");
scanf("%d", &data);
if (push(&stack, &data) == SUCCESS){
printf("%d pushed onto the stack\n", *(int *)stack->top->data);
printf("%u is top of stack", stack->top);
} else {
printf("Not enough memory\n");
}
break;
case POP:
if (pop(&stack, &data) == SUCCESS){
printf("The data is %d\n", data);
} else {
printf("Stack underflow\n");
}
break;
case TOP:
if (peek(&stack, &data) == SUCCESS){
printf("The data at top is %d\n", data);
} else {
printf("Nothing in the stack\n");
}
break;
case LENGTH:
printf("Length is %d\n", stack->stack_size);
break;
default:
assert(!"You should not have reached this.\n");
}
stack_delete(&stack);
getchar();
getchar();
}
}
答案 0 :(得分:3)
您的结构data
为void *
,因此请修复printf
printf("%d pushed onto the stack", *(int *)stack->top->data);
但是,其他堆栈操作似乎也存在其他问题。
另外,如果您计划将其作为通用堆栈,为什么%d
中有printf
?
您可能需要重新访问。
答案 1 :(得分:1)
除了P0W和我提到的要点之外,您的代码中存在错误,导致VS2010
发生崩溃,但导致GCC
发生崩溃。
在push
函数中动态创建stack_node对象时,你传递的sizeof(node)
node
指向stack_node
,而你应该通过sizeof(stack_node)
}}
两种情况下分配的内存量malloc
都不同。
在第一个中,你得到4 bytes
(由于指针的大小)而在第二个得到8 bytes
(因为stack_node的大小)。
在这种情况下,您无法访问stack_node
struct node *lower
对象的第二个成员。此外,当您访问未分配的内存时,这可能需要未定义的行为。
最后在声明free(node)
它崩溃了。
我不知道为什么会发生这种情况的确切原因,而且我也不知道free
在幕后是如何运作的。
我想知道这种情况的原因。