Hey everyone,

I'm trying to make it so that my ^ operator is right justified within this binary expression tree.

For example, 2^3^4 should be evaluated as 2^(3^4). So I should get 2^81, instead of the usual 2^12.

Here is the code I have so far. Everything works, except the ^ is still left associative. I know this is a hard one, so if you don't have time to help me out it's no problem.

Thanks!

// btreeEx.h

// queue.h
// linked list implementation of Queue ADT
#include <cstddef>		 	// for NULL
#include <new>				// for bad_alloc exception
#include <iostream>
using namespace std;

template <class T>
struct Node;					// forward reference, Node defined below

template<class T>
class Queue
{
  private:
	Node<T> * front;			// pointer to front of Queue
	Node<T> * rear;			// pointer to rear of Queue
	int length;				// logical length of Queue
  public:
  	Queue();			// default c-tor
	~Queue();			// d-tor

	void makeMT();		// make Queue logically empty
	// Post: front and rear have been reset to the empty state
	bool isMT() const;		// test for Queue being empty
					// returns true if the queue is empty; false otherwise
	bool isFull() const;	// test for Queue being full
					// Returns true if the queue is full; false otherwise
	void enqueue(T item);		// enqueue an item
	// Post: parameter item is at the rear of the queue
	void dequeue(T & item);	// dequeue an item
	// Post: front of queue has been removed and a copy returned in item
	int getLength() const;		// returns length queue  
	// Post: Queue is unchanged
	void replaceItem(T old, T nu);  // replaces all occurrences of old with nu
	// Pre:  queue has been initialized
	// Post:  each occurrence of old in queue has been changed to nu
	void prntQueue() const;	// displays contents of queue
	// Pre:  queue has been initialized
	// Post: contents of queue have been printed

}; // end Queue

	// implementations
/*template <class T>
struct Node 
{
    T info;
    Node<T> * next;
}; */

template<class T>			// default class c-tor
Queue<T>::Queue() : front(NULL), rear(NULL), length(0)			
{ }

template<class T>			// d-tor
Queue<T>::~Queue() 			
{
  makeMT();
}

template<class T>
void Queue<T>::makeMT()
{
	Node <T> * temp;

    while ( front != NULL ) {
        temp = front;
        front = front->next;
        delete temp;
    } // endwhile
    rear = NULL;
	length = 0;
	return;
} // end makeMT()

template<class T>
bool Queue<T>::isMT() const
{
  return ( length == 0 );	// alternative is to return ( front == NULL );
} // end isMT()

template<class T>
bool Queue<T>::isFull() const
{
	Node<T> * location;
	try	{
		location = new Node<T>;
		delete location;
		return false;
	} // endtry
	catch(bad_alloc exception)
	{
		return true;
	} // endcatch
} // end isFull()

template<class T>
void Queue<T>::enqueue(T item)
{
	Node<T> * newNode;

    newNode = new Node<T>;
    newNode->info = item;
    newNode->next = NULL;
    if ( rear == NULL )
        front = newNode;
    else
        rear->next = newNode;
    rear = newNode;
	length++;
} // end enqueue()

template<class T>
void Queue<T>::dequeue(T & item)
{ 
	Node<T> * temp;

    temp = front;
    item = front->info;
    front = front->next;
    if ( front == NULL )
        rear = NULL;
    delete temp;
	length--;
	return;
} // end dequeue()

template<class T>
int Queue<T>::getLength() const 
{
	return length;
} // end getLength()

template<class T>
void Queue<T>::replaceItem(T old, T nu) 
{
  Node<T> * location = front;
  
  while ( location != NULL ) {
    if ( location->info == old )
        location->info = nu;
    location = location->next;
  } // endwhile
} // end replaceItem()

template<class T>
void Queue<T>::prntQueue() const
{
	Node<T> * location = front;
  
	cout << "\n Printing contents of queue:\n";
	while ( location != NULL ) {
		cout << "\t" << location->info;
		location = location->next;
	} // endwhile
	cout << endl;
	return;
} // end prntQueue()
// end Queue implementations


// stkxcptn.h - header file for PopOnMTStack and PushOnFullStack exception class

//#include <iostream>
//using namespace std;

class PopOnMTStack
{
  private :
	string msg;

  public :
	PopOnMTStack()  		// default c-tor
	{
		msg = string("\n Stack underflow - operation aborted");
	}
	const string message() const
	{
		return msg;
	}
}; // end PopOnMTStack

class PushOnFullStack
{
  private :
	string msg;

  public :
	PushOnFullStack()  		// default c-tor
	{
		msg = string("\n Stack overflow - operation aborted");
	}
	const string message() const
	{
		return msg;
	}
}; // end PopOnMTStack

// stack.h
// header file for Stack ADT using a templated linked list
//#pragma once

//#include "stkxcptn.h"
template <class T>
struct Node;	// forward reference - struct Node is defined below

template<class T>
class Stack
{
  private:
    Node<T> * top;

  public:
	Stack();
	~Stack();

    void makeMT();
    // Function:  sets stack to an empty state
    // Post: Stack is empty

    bool isFull() const;
    // Function:  determines whether the stack is full
    // Pre:  Stack has been initialized
    // Post: Function value = false (assuming new succeeds)
 
    bool isMT() const;
    // Function:  determines whether the stack is empty
    // Pre:  Stack has been initialized
    // Post: Function value = (stack is empty)
  
    void push(T item);
    // Function:  adds item to the top of the stack
    // Pre:  Stack has been initialized
    // Post: If (stack is full), PushOnFullStack exception is thrown;
    //       otherwise, item is at the top of the stack
    
    void pop(T & item);
    // Function: removes top item from the stack and returns it in item
    // Pre:  Stack has been initialized 
    // Post: If (stack is MT), PopOnMTStack exception is thrown;
    //       otherwise, top element has been removed from stack

	void prntStack() const;
    // Function: displays contents of the stack  
    // Pre:  Stack has been initialized 
    // Post: Stack is walked and members printed
}; // end Stack

// Stack ADT - implementation using a templated linked list  

//#include <cstddef>
//#include <new>
template <class T>
struct Node
{
   T info;                                //  Node data of type T
   Node * next;               		//  link to next Node

   Node<T>() : info(0), next(NULL)		// default c-tor for Node
   { }
		
   Node<T>( const T & e, Node * nx = NULL )  // parameterized c-tor for Node
		: info(e), next(nx) 
   { }
};  // end Node

template<class T>
Stack<T>::Stack() : top(NULL)
{ }

template <class T>
Stack<T>::~Stack()
{
  Node<T> * temp;
  
  while ( top != NULL ) {
    temp = top;
    top = top->next;
    delete temp;
  } // endwhile
} // end ~Stack()

template<class T>
void Stack<T>::pop(T & item)
{
  if ( isMT() )
    throw PopOnMTStack();
  else {  
    Node<T> * temp;
    temp = top;
    item = top->info;
    top = top->next;
    delete temp;
  } // endif
} // end pop()

template<class T>
bool Stack<T>::isFull() const
{
  Node<T> * location;
  try {
    location = new Node<T>;
    delete location;
    return false;
  } // endtry
  catch(bad_alloc exception)
  {
    return true;
  } // endcatch
} // end isFull()

template <class T>
void Stack<T>::push(T item)
{
  if ( isFull() )
    throw PushOnFullStack();
  else {  
    Node<T> * ptr;
    ptr = new Node<T>(item);
    ptr->next = top;
    top = ptr;
  } // endif 
} // end push()

template <class T>
void Stack<T>::makeMT() 
{
  Node<T> * temp;
  
  while ( top != NULL ) {
    temp = top;
    top = top->next;
    delete temp;
  } // endwhile
} // end makeMT()

template <class T>
bool Stack<T>::isMT() const
{
  return ( top == NULL );
} // end isMT()

template <class T>
void Stack<T>::prntStack() const
{
	Node<T> * ptr = top;
	cout << "\n Walking the stack:  "
	while ( ptr != NULL ) {
		cout << "\t" << ptr->info;
		ptr = ptr->next;
	} // endwhile
  return;
} // end prntStack()


// file tree.h contains the definition of class Tree
// class is templated

#include <fstream>
#include <cmath>				// for pow()
#include <string>				// Assign #19
const char LAST_SYMBOL = '='; 
enum OpType { OPERATOR, OPERAND };
struct InfoNode
{
  OpType whichType; 	// type field
  union 			// anonymous union
  {
    char operation;
    double operand;	// Assign #19 - change type from int to double
  };
};
typedef InfoNode T;
template <class T>
struct TreeNode;
// Assumption: T is a type for which the operators "<"
// and "==" are defined - either an appropriate built-in type or
// a class that overloads these operators

enum OrderType { PRE_ORDER, IN_ORDER, POST_ORDER };

template <class T>
class Tree
{
  private:
    TreeNode<T> * root;
    // The following queues are used for traversals
    Queue<T> preQue;
    Queue<T> inQue;
    Queue<T> postQue;
  public:
    Tree();			// constructor
    ~Tree();			// destructor
    Tree(const Tree<T> & oTree);
    // copy constructor
    void operator=(const Tree<T> & oTree);
    // Overloads the assignment operator
    void makeMT();
    // Function: Initializes tree to the empty state
    // Post: Tree is empty
    bool isMT() const;
    // Function: Determines whether the tree is empty
    // Post: Function value = (tree is empty)
    bool isFull() const;
    // Function: Determines whether the tree is full
    // Post: Function value = (tree is full)
    int numberOfNodes() const;
    // Function: Determines the number of elements in the tree
    // Post: Function value = number of elements in the tree
    void retrieveItem(T & item, bool & found);
    // Function: Retrieves item whose key matches item's key (if present)
    // Pre:  Key of item has been initialized
    // Post: If there is an item someItem whose key matches item's
    //       key, then found is true and item is a copy of someItem;
    //       otherwise found is false and item is unchanged
    //       The tree is unchanged
    void insertItem(T item);
    // Function: Adds item to the tree
    // Pre:  Tree is not full; item is not in the tree
    // Post: item is in the tree
    //       Binary search property is maintained
    void removeItem(T item);
    // Function: Deletes the item whose key matches item's key
    // Pre:  Key of item has been initialized
    //       One and only one item in the tree has a key matching
    //       item's key
    // Post: No element in tree has key matching item's key
    void resetTree(OrderType order);
    // Function: Initializes current position for an iteration
    //           through the tree in order specified
    // Post: Current position is prior to root of the tree
    void getNextItem (T & item, OrderType order, bool & fini);
    // Function: Gets the next element in the tree in the order specified 
    //	in order
    // Pre:  Current position is defined
    //       Item at current position is not last in the tree
    // Post: Current position is one position beyond current position at 
    //	entry to getNextItem()
    //       fini = (current position is last in tree)
    //       item is a copy of element at current position
    void printTree(std::ofstream & outFile) const;
    // Function: Prints the values in the tree in ascending key
    //           order on outFile
    // Pre:  outFile has been opened for writing
    // Post: Values in the three have been printed in ascending key order
    //       outFile is still open
	template <class T>
	friend void buildExprTree(Tree<T> & expr);
	template <class T>
	friend double eval(Tree<T> & expr);
}; // end Tree

//#include "Tree.cpp"

// Implementation file for Binary Search Tree; 
// recursive insertion and deletion functions

template <class T>
struct TreeNode
{
  T info;
  TreeNode * left;
  TreeNode * right;
  TreeNode() 			// default c-tor for TreeNode
  { }
};

template <class T>
int countNodes(Tree<T> * tree)
{       // Post: returns the number of nodes in the tree
  if (tree == NULL)
    return 0;
  else
    return countNodes(tree->left) + countNodes(tree->right) + 1;
}

template <class T>
int Tree<T>::numberOfNodes() const
{     // calls recursive function CountNodes to count nodes in the tree
  return countNodes(root);
}

// Recursively searches tree for item
// Post: If there is an element someItem whose key matches item's, found
//       is true and item is set to a copy of someItem; otherwise found
//       is false and item is unchanged
template <class T>
void retrieve(TreeNode<T> * tree, T & item, bool & found)
{
  if (tree == NULL)
    found = false;                          // item is not found
  else if ( item < tree->info )                 // Search left subtree
    retrieve(tree->left, item, found);      // Search right subtree
  else if ( item > tree->info )
    retrieve(tree->right, item, found);
  else {
    item = tree->info;                      // item is found
    found = true;
  } // endif
}

template <class T>
void Tree<T>::retrieveItem(T& item, bool& found)
{     // calls recursive function Retrieve to search the tree for item
  retrieve(root, item, found);
}

template <class T>
void insert(TreeNode<T> * & tree, T item)    // inserts item into tree
{      // Post:  item is in tree; search property is maintained
  if ( tree == NULL ) {	     // insertion place found
      tree = new TreeNode<T>;
      tree->right = NULL;
      tree->left = NULL;
      tree->info = item;
  }
  else if ( item < tree->info )
    insert(tree->left, item);      // insert in left subtree
  else
    insert(tree->right, item);     // nsert in right subtree
}

template <class T>
void Tree<T>::insertItem(T item)
{      // calls recursive function Insert to insert item into tree
  insert(root, item);
}

template <class T>
// Deletes the node pointed to by tree
// Post: User's data in the node pointed to by tree is no longer in the tree.  
//       If tree is a leaf node or has only non-NULL child pointer the node
//       pointed to by tree is deleted; otherwise, the user's data is replaced
//       by its logical predecessor and the predecessor's node is deleted
void removeNode(TreeNode<T> * & tree)
{
  T data;
  TreeNode<T>* tempPtr;
  
  tempPtr = tree;
  if ( tree->left == NULL ) {
    tree = tree->right;
    delete tempPtr;
  }  
  else if ( tree->right == NULL ) {
    tree = tree->left;
    delete tempPtr;
  }  
  else {
    getPredecessor(tree->left, data);
    tree->info = data;
    remove(tree->left, data);       // Delete predecessor node
  }
}

template <class T>
void remove(TreeNode<T>*& tree, T item)
{     // deletes item from tree - Post:  item is not in tree
  if (item < tree->info )
    remove(tree->left, item);         // Look in left subtree
  else if ( item > tree->info )
    remove(tree->right, item);        // Look in right subtree
  else
    removeNode(tree);                 // Node found; call removeNode
} 

template <class T>
void Tree<T>::removeItem(T item)
{      // calls recursive function remove() to delete item from tree
  remove(root, item);
}

template<class T>
void getPredecessor(TreeNode<T> * tree, T & data)
{     // sets data to the info member of the right-most node in tree
  while ( tree->right != NULL )
    tree = tree->right;
  data = tree->info;
}

template <class T>
void Tree<T>::printTree(std::ofstream & outFile) const
{     // calls recursive function print() to print items in the tree
  print(root, outFile);
}

template<class T>
void print(TreeNode<T> * tree, std::ofstream & outFile)
{      // prints info member of items in tree in sorted order on outFile
  if ( tree != NULL ) {
    print(tree->left, outFile);             // Print left subtree
    outFile << tree->info;
    print(tree->right, outFile);            // Print right subtree
  } // endif
}

template <class T>
Tree<T>::Tree()
{
  root = NULL;
}

template<class T>
void destroy(TreeNode<T> * & tree)
{     // Post: tree is empty; nodes have been deallocated
  if ( tree != NULL ) {
    destroy(tree->left);
    destroy(tree->right);
    delete tree;
  } // endif
}

template <class T>
Tree<T>::~Tree()
{        // calls recursive function destroy() to destroy the tree
  destroy(root);
}

template <class T>
void copyTree(TreeNode<T> * & copy, TreeNode<T> * origTree )
{     // Post: copy is root of a tree that is a dup of tree pointed to by origTree
  if ( origTree == NULL )
    copy = NULL;
  else {
    copy = new TreeNode<T>;
    copy->info = origTree->info;
    copyTree(copy->left, origTree->left);
    copyTree(copy->right, origTree->right);
  } // endif
}

template <class T>
Tree<T>::Tree(const Tree<T> & origTree)
{     // calls recursive function copyTree() to copy origTree into root
  copyTree(root, origTree.root);
}

template <class T>
void Tree<T>::operator=(const Tree<T> & origTree)
{     // calls recursive function CopyTree to copy origTree into root
  if ( &origTree == this )
    return;                       // Ignore assigning self to self
  destroy(root);                  // Deallocate existing tree nodes
  copyTree(root, origTree.root);
}

  // function prototypes for auxiliary functions
template <class T>
void buildExprTree(Tree<T> & expr);  // builds preorder binary expression tree

template <class T>
void preorder(TreeNode<T> *, Queue<T> &);  // enqueues tree items in preorder

template <class T>
void inorder(TreeNode<T> *, Queue<T> &);  // enqueues tree items in inorder

template <class T>
void postorder(TreeNode<T> *, Queue<T> &);  // enqueues tree items in postorder

template <class T>
void Tree<T>::resetTree(OrderType order)
{     // calls function to create a queue of the tree elements in specified order
  switch ( order ) {
    case PRE_ORDER :  preorder(root, preQue);
		     		break;
    case IN_ORDER  :  inorder(root, inQue);
		     		break;
    case POST_ORDER:  postorder(root, postQue);
		     		break;
  } // endswitch
}

template <class T>
void preorder(TreeNode<T> * tree, Queue<T> & preQue)
{      // Post: preQue contains the tree items in preorder
  if ( tree != NULL ) {
    preQue.enqueue(tree->info);
    preorder(tree->left, preQue);
    preorder(tree->right, preQue);
  } // endif
}

template <class T>
void inorder(TreeNode<T>* tree, Queue<T>& inQue)
{     // Post: inQue contains the tree items in inorder
  if ( tree != NULL ) {
    inorder(tree->left, inQue);
    inQue.enqueue(tree->info);
    inorder(tree->right, inQue);
  } // endif
}

template <class T>
void postorder(TreeNode<T> * tree, Queue<T> & postQue)
{     // Post: postQue contains the tree items in postorder
  if ( tree != NULL ) {
    postorder(tree->left, postQue);
    postorder(tree->right, postQue);
    postQue.enqueue(tree->info);
  } // endif
}

// Returns the next item in the desired order
// Post: For the desired order, item is the next item in the queue
//       If item is the last one in the queue, fini is true; otherwise
//       fini is false
template <class T>
void Tree<T>::getNextItem(T & item, OrderType order, bool & fini)
{
  fini = false;
  switch ( order ) {
    case PRE_ORDER : preQue.dequeue(item);
					 if ( preQue.isMT() )
						fini = true;
					 break;
    case IN_ORDER  : inQue.dequeue(item);
					 if ( inQue.isMT() )
						fini = true;
					 break;
    case POST_ORDER: postQue.dequeue(item);
					 if ( postQue.isMT() )
						fini = true;
					 break;
  } // endswitch
}

void parseStr(string s, char & sym, double & d);  // Assign #19 - prototype

template <class T>
void buildExprTree(Tree<T> & expr) 
{
	buildTree(expr.root);
} 

// buildTree.cpp
// buildTree() builds a binary expression tree
// Note:  operands are NOT restricted to single digits 	 
void buildTree(TreeNode<T> * & tree)
{
  string inStr;			// Assign #19
  double opnd;			// Assign #19

  enum MoveType { RIGHT, LEFT };
  MoveType nextMove = LEFT;

  TreeNode<T> * nptr = new TreeNode<T>;
  TreeNode<T> * last;
  char symbol;

  Stack <TreeNode<T> *> stack;
  cin >> symbol;
  cout << " operator: " << symbol << endl;  // first symbol is operator
  nptr->info.whichType = OPERATOR;
  nptr->info.operation = symbol;
  tree = nptr;
    // instead of 
    // cin >> symbol; // this version uses single-digit operands – we have
  cin >> inStr;				// Assign #19 - uses type double operands
  parseStr(inStr, symbol, opnd);	// Assign #19

  while ( symbol != LAST_SYMBOL ) {
    last = nptr;
    nptr = new TreeNode<T>;

    if ( ispunct(symbol) ) {
      cout << " operator: " << symbol << endl;
      nptr->info.whichType = OPERATOR;
      nptr->info.operation = symbol;
    }
    else {
		//cout << "  operand: " << symbol << endl;
	  cout << "  operand: " << opnd << endl;	// Assign #19
	  nptr->info.whichType = OPERAND;
		//nptr->info.operand = int(symbol - '0');
	  nptr->info.operand = opnd;			// Assign #19
	  nptr->right = NULL;
	  nptr->left = NULL;
    } // endif
    
    switch ( nextMove ) {
      case LEFT  :	last->left = nptr;
          			stack.push(last);
 				break;
      case RIGHT :	stack.pop(last);
         			last->right = nptr;
				break;
    } // endswitch
    
    if ( nptr->info.whichType == OPERATOR )
       nextMove = LEFT;
    else 
	 nextMove = RIGHT;
						  // instead of cin >> symbol;
	 cin >> inStr;			  // Assign #19 - uses type double operands
	 parseStr(inStr, symbol, opnd);	// Assign #19
  } // endwhile
  return;
} // end buildTree()

void parseStr(string s, char & sym, double & d)	 	// Assign #19 
{
	const char * p = s.c_str();	// convert to C-style string
	if ( p[0] == '+' || p[0] == '^' || p[0] == '/' || p[0] == '*' || 
		p[0] == '-' || p[0] == LAST_SYMBOL )  {	 // symbol is an operator
		sym = p[0];
		d = 0.0;
	} // endif-thenpart
	else {				// input is type double operand
		d = atof(p);	// convert input to type double operand
		sym = '1';		// can make symbol any non-operator
	} // endif-elsepart
} // end parseStr()

template <class T>			//int eval(Tree<T> & expr) 
double eval(Tree<T> & expr)		// Assign #19
{
	return eval(expr.root);
} 

// Pre:   ptr is a pointer to a binary expression tree
// Post:  Function value = the value of the expression
//		  represented by the binary tree pointed to by ptr
						//int eval(TreeNode<T> * ptr)
double eval(TreeNode<T> * ptr)	// Assign #19
{     // function to evaluate a binary expression tree
   switch ( ptr->info.whichType ) {        				
	 case OPERAND :  return  ptr->info.operand;
	 case OPERATOR :
	 switch ( ptr->info.operation ) {
	
	 case '+' : return ( eval(ptr->left) + eval(ptr->right) ); 

		case '-' : return ( eval(ptr->left) - eval(ptr->right) );

		case '*' : return ( eval(ptr->left) * eval(ptr->right) ); 
					
		case '/' : return ( eval(ptr->left) / eval(ptr->right) );
		
		case '^' : return ( pow(eval(ptr->left), eval(ptr->right)) );
         } // endswitch
	} // endswitch
	return 0.0;
} // end eval()

//tstexpr.cpp
/* ------------------------------------------------------------------------------
 * program to test binary tree expression evaluation
 * 	CS 320 - Data Structures 		   
 */

#include "btreeEx.h"
void main()
 {
	Tree<T> e;  

	cout << "\n Use a Binary Tree for Preorder Expression Evaluation\n";
	cout << "\n Enter expression terminated by an equal sign, e.g.:  - * 6.2 3.1 5.8 =\n";

	buildExprTree(e);
	cout << "\n The value of the expression is " << eval(e);

	cout << "\n -- Done --\n";
	return;
 }

Recommended Answers

All 9 Replies

>For example, 2^3^4 should be evaluated as 2^(3^4).
>So I should get 2^81, instead of the usual 2^12.
Erm, it looks to me like the input is supposed to be prefix rather than infix. If you're getting 2^12 for your result, then I suspect you aren't entering the correct expression. You can test it for yourself:

^ ^ 2 3 4 = 2^12
^ 2 ^ 3 4 = 2^81

You're right about the input. However, the input has to stay as ^ ^ 2 3 4. I need a special case maybe, to take care of the double ^?

>However, the input has to stay as ^ ^ 2 3 4.
That's stupid. You want to input a a prefix expression but evaluate it differently from the prefix notation rules. Would you be kind enough to explain why you need to do this?

That's stupid. You want to input a a prefix expression but evaluate it differently from the prefix notation rules. Would you be kind enough to explain why you need to do this?

hahah, no kidding.

This is, I guess, considered to be a programming challenge from my professor. The only thing I could think of would be to add a exception-handling block for when two ^ are found... but I have no clue if even that will work.

Honestly, I don't think anyone in the class has this figured out. I might turn in my assignment without this part included, hoping he'll mark it off. Quite silly, I agree.

>Honestly, I don't think anyone in the class has this figured out
I'm not surprised. Assuming you've given me the same requirements your teacher gave you, there's really no way you can solve the problem adequately. Since he changed the rules, you need to know the new rules before you can follow them.

You currently have one case:

^ ^ 2 3 4 = 2^81

What about the case you've replaced?

^ 2 ^ 3 4 = ?

What about the infinite recursion you should be able to handle correctly? What are the rules for three operators? Four? Fifty? What if they're not all adjacent? You lack sufficient information.

commented: It doesn't matter what question they ask you: you just know always the right solution :) +3

The whole point of prefix notation is to represent the formula in such a way as to eliminate the complications of precedence and association. To reinstate these complications is sidiotic.

I feel the most likely case here is that you are misunderstanding the assignment. It makes perfect sense to process exponentiation as right-associative; but it does not make sense to reinterpret prefix notation. So perhaps the input is supposed to be infix notation?

I know the problem sounds a little (understatement maybe) odd.
I understand what you're saying nucleon, and that would seem a lot more logical. However, I'm sure I haven't misunderstood the project. :)

>Narue
This is probably going to make you flip out. But in the case of input such as: 2 ^ 3 ^ 4, the left associativity should be used. In any case with subsequent ^, right associativity should be used (e.g., ^ ^ 2 3 4).

heheh, ^.^;

>But in the case of input such as: 2 ^ 3 ^ 4, the left associativity should be used
>used. In any case with subsequent ^, right associativity should be (e.g., ^ ^ 2 3 4).
Then I'd guess your teacher wants you to use prefix evaluation for the former and postfix evaluation for the latter. When you see adjacent operators, move them behind the correct number of operands:

* = Operand or operator not applicable

* ^ ^ 2 3 4 *

Find adjacent operators:
* ^ ^ 2 3 4 *

Count the operands that apply:
* ^ ^ 2 3 4 *

Move the operators to postfix position:
* 2 3 4 ^ ^ *

Evaluate:
Push 2
Push 3
Push 4
Found ^: Pop 4, 3, Evaluate
Push 81
Found ^, Pop 81, 2, Evaluate
Push 2^81

Ah, nice. I'll give that a try. Thanks!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.