我有一个程序,它已经为它编写了一些库。结构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");
}
}
感谢任何帮助。
答案 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 *变量指定指针时,必须强制转换该指针的类型。