将double的堆栈结构转换为void *

时间:2016-02-21 04:31:14

标签: c stack push pop

我有一个程序,它已经为它编写了一些库。结构stackElementT是一个double,现在它需要转换为一种void指针。我知道每次将数字推入堆栈时我都需要分配内存,但无法确定要分配的内容。如果我只将结构转换为void *的类型,那么我会得到以下错误:

gcc -I../booklib  -c rpncalc.c
In file included from rpncalc.c:14:0:
stack.h:65:41: warning: parameter 2 (‘element’) has void type [enabled by default]
void Push(stackADT stack, stackElementT element);
                                     ^
rpncalc.c: In function ‘main’:
rpncalc.c:44:17: error: type of formal parameter 2 is incomplete
             Push(operandStack, StringToReal(line));
             ^
rpncalc.c: In function ‘ApplyOperator’:
rpncalc.c:69:9: error: void value not ignored as it ought to be
 rhs = Pop(operandStack);
     ^
rpncalc.c:70:9: error: void value not ignored as it ought to be
 lhs = Pop(operandStack);
     ^
rpncalc.c:79:12: error: incompatible types when assigning to type ‘double’ from type ‘void *’
 result = malloc(result * sizeof(double *));
        ^
rpncalc.c:80:5: error: type of formal parameter 2 is incomplete
 Push(operandStack, result);
 ^
rpncalc.c: In function ‘DisplayStack’:
rpncalc.c:135:13: error: invalid use of void expression
         printf("%g", GetStackElement(stack, i));
         ^
make: *** [rpncalc.o] Error 1

这是stack.h代码:

/*
 * File: stack.h
 * -------------
 * This interface defines an abstraction for stacks.  In any
 * single application that uses this interface, the values in
 * the stack are constrained to a single type, although it
 * is easy to change that type by changing the definition of
 * stackElementT in this interface.
 */

#ifndef _stack_h
#define _stack_h

#include "genlib.h"

/*
 * Type: stackElementT
 * -------------------
 * The type stackElementT is used in this interface to indicate
 * the type of values that can be stored in the stack.  Here the
 * stack is used to store values of type double, but that can
 * be changed by editing this definition line.
 */

typedef void stackElementT;

/*
 * Type: stackADT
 * --------------
 * The type stackADT represents the abstract type used to store
 * the elements that have been pushed.  Because stackADT is
 * defined only as a pointer to a concrete structure that is not
 * itself defined in the interface, clients have no access to
 * the underlying fields.
 */

typedef struct stackCDT *stackADT;

/*
 * Function: NewStack
 * Usage: stack = NewStack();
 * --------------------------
 * This function allocates and returns a new stack, which is
 * initially empty.
 */

stackADT NewStack(void);

/*
 * Function: FreeStack
 * Usage: FreeStack(stack);
 * ------------------------
 * This function frees the storage associated with the stack.
 */

void FreeStack(stackADT stack);

/*
 * Function: Push
 * Usage: Push(stack, element);
 * ----------------------------
 * This function pushes the specified element onto the stack.
 */

void Push(stackADT stack, stackElementT element);

/*
 * Function: Pop
 * Usage: element = Pop(stack);
 * ----------------------------
 * This function pops the top element from the stack and returns
 * that value.  The first value popped is always the last one
 * that was pushed.  If the stack is empty when Pop is called,
 * the function calls Error with an appropriate message.
 */

stackElementT Pop(stackADT stack);

/*
 * Functions: StackIsEmpty, StackIsFull
 * Usage: if (StackIsEmpty(stack)) . . .
 *        if (StackIsFull(stack)) . . .
 * -------------------------------------
 * This functions test whether the stack is empty or full.
 */

bool StackIsEmpty(stackADT stack);
bool StackIsFull(stackADT stack);

/*
 * Function: StackDepth
 * Usage: depth = StackDepth(stack);
 * ---------------------------------
 * This function returns the number of elements currently pushed
 * on the stack.
 */

int StackDepth(stackADT stack);

/*
 * Function: GetStackElement
 * Usage: element = GetStackElement(stack, index);
 * -----------------------------------------------
 * This function returns the element at the specified index in
 * the stack, where the top of the stack is defined as index 0.
 * For example, calling GetStackElement(stack, 0) returns the top
 * element on the stack without removing it.  If the caller tries
 * to select an out-of-range element, GetStackElement calls Error.
 * Note: This function is not a fundamental stack operation and
 * is instead provided principally to facilitate debugging.
 */

stackElementT GetStackElement(stackADT stack, int index);

#endif

这里是推送和弹出的rpncalc.c:

/*
 * File: rpncalc.c
 * ---------------
 * This program simulates an electronic calculator that uses
 * reverse Polish notation, in which the operators come after
 * the operands to which they apply.
 */

#include <stdio.h>
#include <ctype.h>
#include "genlib.h"
#include "simpio.h"
#include "strlib.h"
#include "stack.h"

/* Private function prototypes */

static void ApplyOperator(char op, stackADT operandStack);
static void HelpCommand(void);
static void ClearStack(stackADT operandStack);
static void DisplayStack(stackADT operandStack);

/* Main program */

main()
{
    stackADT operandStack;
    string line;
    char ch;

    printf("RPN Calculator Simulation (type H for help)\n");
    operandStack = NewStack();
    while (TRUE) {
        line = malloc(line * sizeof(double *));
        printf("> ");
        line = GetLine();
        ch = toupper(line[0]);
        switch (ch) {
          case 'Q': exit(0);
          case 'H': HelpCommand(); break;
          case 'C': ClearStack(operandStack); break;
          case 'S': DisplayStack(operandStack); break;
          default:
            if (isdigit(ch)) {
                Push(operandStack, StringToReal(line));
            } else {
                ApplyOperator(ch, operandStack);
            }
            break;
        }
    }
}

/* Private functions */

/*
 * Function: ApplyOperator
 * Usage: ApplyOperator(op, operandStack);
 * ---------------------------------------
 * This function applies the operator to the top two elements on
 * the operand stack.  Because the elements on the stack are
 * popped in reverse order, the right operand is popped before
 * the left operand.
 */

static void ApplyOperator(char op, stackADT operandStack)
{
    double lhs, rhs, result;

    rhs = Pop(operandStack);
    lhs = Pop(operandStack);
    switch (op) {
      case '+': result = lhs + rhs; break;
      case '-': result = lhs - rhs; break;
      case '*': result = lhs * rhs; break;
      case '/': result = lhs / rhs; break;
      default:  Error("Illegal operator %c", op);
    }
    printf("%g\n", result);
    result = malloc(result * sizeof(double *));
    Push(operandStack, result);
}

/*
 * Function: HelpCommand
 * Usage: HelpCommand();
 * ---------------------
 * This function generates a help message for the user.
 */

static void HelpCommand(void)
{
    printf("Enter expressions in Reverse Polish Notation,\n");
    printf("in which operators follow the operands to which\n");
    printf("they apply.  Each line consists of a number, an\n");
    printf("operator, or one of the following commands:\n");
    printf("  Q -- Quit the program\n");
    printf("  H -- Display this help message\n");
    printf("  C -- Clear the calculator stack\n");
    printf("  S -- Display all values in the stack\n");
}

/*
 * Function: ClearStack
 * Usage: ClearStack(stack);
 * -------------------------
 * This function clears the stack by popping elements until it is
 * empty.
 */

static void ClearStack(stackADT stack)
{
    while (!StackIsEmpty(stack)) {
        (void) Pop(stack);
    }
}

/*
 * Function: DisplayStack
 * Usage: DisplayStack(stack);
 * ---------------------------
 * This function displays the contents of a stack.
 */

static void DisplayStack(stackADT stack)
{
    int i, depth;

    printf("Stack: ");
    depth = StackDepth(stack);
    if (depth == 0) {
        printf("empty\n");
    } else {
        for (i = depth - 1; i >= 0; i--) {
            if (i < depth - 1) printf(", ");
            printf("%g", GetStackElement(stack, i));
        }
        printf("\n");
    }
}

感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

“但无法弄清楚要为”

分配什么

解决方案非常简单:在你的结构中你必须有你的void指针,用于存储指向你想要的类型的内存空间的指针(你可以选择每个项目的类型)。对于函数Push,您必须传递参数以推送您想要使用的值(例如,double)。让我们假装你有

void *item;

定义为结构中void的指针。您所要做的就是为double分配动态内存,并将作为参数传递的值的副本复制到您的结构中。像这样:

stack->item = (double*) malloc(sizeof(double)); //the void pointer variable now stores the address to a memory location for double variable
*(stack->item) = value;

分配就是这么简单:库的用户不需要知道如何实现泛型堆栈。

如果你想存储一个指针,你可以做同样的事情,但不需要复制。您希望在堆栈中指向此结构的指针可以直接分配给项目:

stack->item = argument; //argument is a pointer to a structure (e.g. FILE).

此外,在你的释放堆栈功能中,你必须记住释放指向你存储的值的指针。这一切都是这样的,并且记得像我一样在malloc中进行类型转换。为void *变量指定指针时,必须强制转换该指针的类型。