2016-02-21 3 views
2

У Iv есть программа, в которой уже написано несколько библиотек. Структура stackElementT была двойной, теперь ее нужно преобразовать в тип указателя 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"); 
    } 
} 

всякая помощь приветствуется.

+2

«теперь он должен быть преобразован в тип указателя пустоты». Таким образом, 'typedef void stackElementT;' должен быть 'typedef void * stackElementT;' – kaylum

ответ

0

«но не может понять, что выделить для»

решения довольно просто: внутри вашей структуры вы должны иметь свой пустой указатель, который используется для хранения указателя на область памяти, предназначавшуюся для типа вы хотите (вы можете выбрать тип каждого элемента). Для функции Push вы должны передать в качестве аргумента значение Push, с которым вы хотите работать (например, double). Давайте сделаем вид, что у вас есть

void *item; 

определяется как указатель на пустоту в вашей структуре. Все, что вам нужно сделать, это выделить динамическую память для двойки и сделать копию значения, переданного в качестве аргумента вашей структуре. Как это:

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 *, вы должны указать тип этого указателя.