#include "assign3.h"
#include <iostream>
using namespace std;

Calculator::Calculator(int size) {
	if (size > 0) {
		mSize = size;
		mPstack = mPtop;
		if ((*mPstack).im && (*mPstack).re) {
			mSize = size;
			mPstack = mPtop;
		} else {
			mSize = 0;
			(*mPstack).re = 0;
			(*mPstack).im = 0;
		}
	} else {
		mSize = 0;
		(*mPstack).re = 0;
		(*mPstack).im = 0;
	}
int Calculator::size() {
	return mSize;
}

Calculator::~Calculator() {
	delete mPstack;
}

bool Calculator::push(myComplex x) {
	if (mPtop) {
		mPtop = &x;
		mPtop++;
		return true;
	} else
		return false;

bool Calculator::pop(myComplex& x) {
	if (mPtop > mPstack) {
		mPtop--;
		x.re = (*mPtop).re;
		x.im = (*mPtop).im;
		return true;
	} else{
		return false;
	}

bool Calculator::oper(char op) {
	myComplex sum;
	if (mPtop < mPstack + 2)
		return false;
	int tempRE = (*mPtop--).re;
	int tempIM = (*mPtop--).im;
	if (op == '/' && tempRE == 0 && tempIM == 0)
		return false;
    int leftRE = (*mPtop--).re;
    int leftIM = (*mPtop--).im;
	if (op == '+') {
        sum.re = tempRE + leftRE;
        sum.im = tempIM + leftIM;
		push(sum);
		return true;
	}
    if(op=='/'){

    	sum.re = leftRE / tempRE;
    	sum.im = leftIM / tempIM;
    	push(sum);
    	return true;
    }
    return false;
}

This is my code. I run for many times . it cannot calculate right answer.

thanks

Edited 5 Years Ago by AlvinLiu: n/a

Can you post all the code? You just posted up the Calculator source file and are missing the myComplex class all together and the main function.

/* This is a class for a four-function myComplex number-
calculator which uses Reverse Polish Notation 
([url]http://en.wikipedia.org/wiki/Reverse_Polish_notation[/url]). The
calculator keeps an internal stack of myComplex numbers. The
user may push numbers on the stack and pop them off again. A
calculation utilizes the top (most recently pushed) numbers
and replaces them with the result. No action is taken if the
operation is illegal (e.g., not enough numbers on the stack or divide
by zero). Mixed-mode calculations are supported only
indirectly (i.e., all numbers must be myComplex but there's nothing
to say their real or imaginary parts can't be zero).

A stack is just like a queue EXCEPT that the first item
pushed onto the stack is the last item that can be popped
off. It's known as a First In Last Out (FILO) structure as
opposed to the First In First Out (FIFO) behavior that
characterizes a queue.

It gets its name from one of those old spring-loaded plate
dispensers that cafeterias used to have - the first plate put in
by the staff goes on the bottom, then the next one, etc. 
Thus, the first one put in is actually the last one removed
by the patrons. Unlike the last week's assignment, this stack
is NOT circular (we say its linear).
*/


// Needed types
struct myComplex {
    double re, im;
};


class Calculator{
public:
    Calculator(int size);
    /* Precondition: "size" is non-negative.
       Specification: if "size" is positive, a calculator, whose stack size is "size",
          is constructed if there is enough space allocated on the heap. Otherwise
          (i.e., if "size" is 0 or no enough space was allocated on the heap), "mSize"
          and "mPstack" will be assigned to 0.
    */

    ~Calculator();    /* delete the heap memory referred to by "mPstack". */

    int size();  /* return the size of the stack. */

    bool push(myComplex x);
    /* push one complex-number "x" on the top of the stack (referred to by
    "mPtop") and get "mPtop" incremented by 1 (i.e., move the top of the
    stack to the next available address). Return true if
    operation successful, false if the stack was full (in which
    case "x" is NOT put on the stack - nothing is done with it at all).
    */

    bool pop(myComplex& x);
    /* decrement "mPtop" by 1 (i.e., move back the top of the stack 
    to the previous available address), pop the complex-number from 
    the location referred to by "mPtop" on the stack and pass it back to the
    referenced variable "x". Return true if successful, false if the
    stack is empty (in which case nothing is done at all). */

    bool oper(char op);
    /* Carries out requested operation: '*' for multiply, '/'
    for divide, '+' for add, and '-' for subtract. A successful
    operation returns a Boolean true. Any other characters will
    result in no action and a Boolean return of false. The value,
    located at the address of "mPtop" minus 1, is the right-hand
    operand, whereas the one next to the right-hand operand (i.e.,
    whose address is "mPtop" minus 2) is the left-hand operand.
    After operation, the left-hand operand on the stack is replaced
    with the computed result, and the "mPtop" should point to
    where the right-hand operand was originally located.
    For example, the calling sequence
        push(x);
        push(y);
        oper('-');
    leaves "x-y" on the stack in place of "x", whereas finally the   
    "mPtop" points to the location where "y" was original stored.
    If "x" and "y" were the only things pushed on the stack, it
    will have only one item on the stack after the subtraction,
    that is, the result of "x-y".

    true is returned if the operation was carried out successfully,
    false otherwise (e.g, insufficient numbers on the stack, 
    divide by zero, etc.)
  */

private:
    myComplex* mPstack;     // Pointer to the start of stack in the heap
    myComplex* mPtop;       // Pointer to the top of the stack
    int mSize;          // stack size
};

This is the header file

Edited 3 Years Ago by Dani: Formatting fixed

#include <iostream>
#include <string>
#include "assign3.h"
#include <math.h>
using namespace std;

bool checkEqual(myComplex a1, myComplex a2);

/** main ********************************************************************
* @params: none
* @return: int
* @descript: Test the stack-based Calculator class
*********************************************************************************/
int main() {
	Calculator calc(5);
	bool bPassed;
	int iInput = 1;
	myComplex num1, num2, res, exp;	// "res" for calculated result, "exp" for expected result.
	num1.re = 3.;
	num1.im = -3.;
	num2.re = 1.;
	num2.im = -2.;

	myComplex c0, c1, c2, c3, c4, c5, c6, c7;
	c1.re = 1; c1.im = 1;
	c3.re = 3; c3.im = 3;
	c5.re = 5; c5.im = 5;
	c7.re = 7; c7.im = 7;
	c2.re = 2; c2.im = 2;
	c4.re = 4; c4.im = 4;
	c6.re = 6; c6.im = 6;
	c0.re = 0; c0.im = 0;
	calc.push(c4);
	calc.push(c2);
	calc.oper('/');
	calc.pop(res);
	cout << "A simple test of (4j4/2j2), the result should be 2j0, whereas your result is " << res.re << "j" << res.im << endl;
	cout << "Below, more tests are coming..." << endl << endl;

	cout << "\nPlease type in a number for different test cases..." << endl;
	cout << "(Menu: 1 for initialization, 2 for push/pop, 3 for addition, 4 for subtraction, 5 for multiplication, and 6 for divide)" << endl;
	cin >> iInput;
	cout << "Typed selection is " << iInput << endl;
	if (iInput <= 6 && iInput > 0 ) {
		switch (iInput) {
			case 1:	{	// 1 for initialization
				bPassed = !calc.pop(res);
				if (bPassed)
					cout << "Stack initialization (1) is correct." << endl;
				else
					cout << "Stack initialization (1) is incorrect." << endl;
				break;
			}
			case 2: {	// 2 for push/pop
				bPassed = true;
				int i;
				for (i=0; i<calc.size(); i++)
					if (!calc.push(num1))
						bPassed = false;
				if (calc.push(num1))
					bPassed = false;
				if (bPassed)
					for(i=0; i<calc.size(); i++)
						if(! (calc.pop(res) && (res.re==num1.re) && (res.im==num1.im)) )
							bPassed = false;
				if (bPassed)
					cout << "Stack push/pop (2) is correct." << endl;
				else
					cout << "Stack push/pop (2) is incorrect." << endl;
				break;
			}
			case 3:	{	// 3 for addition
				while (calc.pop(res)) ;	// empty the stack
				bPassed = (calc.push(num1) && calc.push(num2) && calc.oper('+') && calc.pop(res));
				exp.re = 4.;
				exp.im = -5.;
				if (bPassed) {
					bPassed = checkEqual(exp, res);
				}
				if (bPassed)
					cout << "Addition operation (3) is correct." << endl;
				else
					cout << "Addition operation (3) is incorrect." << endl;
				break;
			}
			case 4: {	// 4 for subtraction
				while (calc.pop(res)) ;	// empty the stack
				bPassed = (calc.push(num1) && calc.push(num2) && calc.oper('-') && calc.pop(res));
				exp.re = 2.;
				exp.im = -1.;
				if (bPassed) {
					bPassed = checkEqual(exp, res);
				}
				if (bPassed)
					cout << "Subtraction operation (4) is correct." << endl;
				else
					cout << "Subtraction operation (4) is incorrect." << endl;
				break;
			}
			case 5: {	// 5 for multiplication
				while (calc.pop(res)) ;	// empty the stack
				bPassed = (calc.push(num1) && calc.push(num2) && calc.oper('*') && calc.pop(res));
				exp.re = -3.;
				exp.im = -9.;
				if (bPassed) {
					bPassed = checkEqual(exp, res);
				}
				if (bPassed)
					cout << "Multiplication operation (5) is correct." << endl;
				else
					cout << "Multiplication operation (5) is incorrect." << endl;
				break;
			}
			case 6: {	// 6 for divide
				while (calc.pop(res)) ;	// empty the stack
				bPassed = (calc.push(num1) && calc.push(num2) && calc.oper('/') && calc.pop(res));
				exp.re = 1.8;
				exp.im = 0.6;
				if (bPassed) {
					bPassed = checkEqual(exp, res);
				}
				if (bPassed)
					cout << "Division operation (6) is correct." << endl;
				else
					cout << "Division operation (6) is incorrect." << endl;
				break;
			}
			default:
				break;
		}
	}
	else
		cout << "Typed selection is illegal!" << endl;
	cout << "Test is complete." << endl;

	return 0;
}

/** checkEqual ********************************************************************
* @params: a1 - the first myComplex object. a2 - the second myComplex object.
* @return: bool, true for equal and false for inequality
* @descript: check whether the two myComplex objects are equal (with a tolerance of 0.001).
*********************************************************************************/
bool checkEqual(myComplex a1, myComplex a2) {
	return ( (fabs(a1.re - a2.re) < 0.001) &&
			 (fabs(a1.im - a2.im) < 0.001) );
}

This is the test file.

One huge problem that you had was that you were not allocating memory for your stack. The reason why you did not get run-time errors for this is because you were never actually using your stack, which is why (along with a few other things) you were getting garbage values for the initial test.

Within the oper() function you have a check that attempts to see if there are at least two numbers in the stack and in your case that is never true so it just returns. I would suggest you remove that all together and take advantage of the fact that your pop() functions return a bool.

Out of all the functions you have the only one that is correct is the pop() function. Your push() function is changing the memory address of mPtop when what you really want is to change the value at mPtop's memory address, and you need a range restriction on that function so you are not pushing too many values onto a stack of a limited size (otherwise you go out of bounds of the memory allocated and this results in a run-time error).

For the oper() function your division function is wrong and you need to look up how to divide complex numbers (I just typed in dividing complex numbers into google) and attempt to come up with the same result that I put below (I did it all with variables on pen and paper and then transferred it into code directly).

#include "assign3.h"
#include <cstdlib>

Calculator::Calculator(int size)
{
	if( size > 0 )
	{
		mSize = size;
		mPstack = (myComplex*)malloc(mSize*sizeof(myComplex)); //try to allocate memory for the stack
		mPtop = mPstack; //set the top of the stack to the start of the stack

		if( !mPstack ) //if the stack could not be allocated
			mSize = 0;
	}
	else
	{
		mSize = 0;
		mPtop = mPstack = 0; //if the size of the stack is 0 then set the pointers to 0 ( aka NULL)
	}
}
int Calculator::size()
{
	return mSize;
}

Calculator::~Calculator()
{
	delete mPstack;
}

bool Calculator::push(myComplex x)
{
	if( mPtop >= mPstack && mPtop < mPstack + mSize ) //if mPtop is within range of the stack size
	{
		*mPtop = x; //set the point in memory where mPtop is pointing to the value of x
		mPtop++;
		return true;
	}
	return false;
}

bool Calculator::pop(myComplex &x)
{
	if( mPtop > mPstack ) //if mPtop is not equal to or less than (so we do not try to get values below the stack aka garbage values)
	{
		mPtop--;
		x = *mPtop;
		return true;
	}
	return false;
}

bool Calculator::oper(char op)
{
	myComplex res, left, right;

	if( !pop(right) ) //if cannot grab something out of the stack
		return false;

	if (op == '/' && right.re == 0 && right.im == 0) //catching divide by 0
		return false;

	if( !pop(left) ) //if cannot grab another out of the stack
		return false;

	//up to this point the only way it should fail is if a bad operator was passed, so always return true unless default case
	switch(op)
	{
		case '+':
			res.re = left.re + right.re;
			res.im = left.im + right.im;
			break;
		case '-':
			res.re = left.re - right.re;
			res.im = left.im - right.im;
			break;
		case '*': //calculated on pen and paper with variables
			res.re = left.re*right.re + -left.im*right.im;
			res.im = left.re*right.im + left.im*right.re;
			break;
		case '/': //calculated on pen and paper with variables
			res.re = (left.re*right.re + left.im*right.im)/(right.re*right.re + right.im*right.im);
			res.im = (-left.re*right.im + left.im*right.re)/(right.re*right.re + right.im*right.im);
			break;
		default:
			return false;
	}

	push(res); //push the result on to the stack
    return true;
}
This article has been dead for over six months. Start a new discussion instead.