I'm working on a program involving the use of templates to evaluate postfix expressions. I'm not allowed to modify the code in any way; only fill in the blanks, so to speak (most of which have been filled, but errors are turning up). This being said:
1) The template header, template specialization, and main program files are all separate. How do I implement the template in the main program? I'm already using #include at the end of the header file as the specialization substitute.
2) FIXED
3) In the specialization file, do I need to use #include "templateheader.h" above using namespace std, or do I just put template above every function? I'll post an example as I have it now below.
Two asterisks mark the lines where we have to fill in the blanks. If it's only part of a line, it's one star on each side.
stackType.h
#pragma once**
// Catherine Stringfellow and Trey Brumley
// A Stack is a ???**
// Class specification for Stack ADT in file StackType.h
using namespace std;
static const int MAXITEMS = 50;
template <class stack>**
class StackType
{
public:
// Class constructors
StackType();
StackType (const StackType & other);
void makeEmpty();
// 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 = (stack is full)
bool isEmpty() const;
// Function: Determines whether the stack is empty.
// Pre: Stack has been initialized.
// Post: Function value = (stack is empty)
void push(*stack* item);
// Function: Adds newItem to the top of the stack.
// Pre: Stack has been initialized.
// Post: If (stack is full), PushOnFullStack exception is thrown;
// otherwise, newItem is at the top of the stack.
void pop(*stack* & item);
// Function: Removes top item from the stack and returns it in item.
// Pre: Stack has been initialized.
// Post: If (stack is empty), PopOnEmptyStack exception is thrown;
// otherwise, top element has been removed from stack.
// item is a cop of the removed item.
int getStackNum ();
//Function: returns the number of items in the stack
//Pre: Stack has been initialized
//Post: Returns the number of items in the stack
private:
int top;
stack items[MAXITEMS]; //statically allocated array
};
#include "stackType.cpp";**
stackType.cpp
// Catherine Stringfellow and Trey Brumley
// File: StackType.cpp
// Templated member function implementations for class StackType.
// This is the statically allocated array-based stack.
#include "stack"**
using namespace std;
template <class stack>**
StackType *StackType<stack>*::StackType()
{
top = -1;
}
template <class stack>**
StackType *StackType<stack>*::StackType (const StackType & other)
{
top = other.top;
for (int i=0; i < top; i++)
items[i] = other.items[i];
}
template <class stack>**
StackType*<stack>*::makeEmpty()
{
top = -1;
}
template <class stack>**
*bool StackType<stack>*::isEmpty() const
{
return (top == -1);
}
template <class stack>**
bool StackType*<stack>*::isFull() const
{
return (top == MAXITEMS-1);
}
template <class stack>**
StackType*<stack>*::push(StackType newItem)
{
if( !isFull() )
{
top++;
items[top] = newItem;
}
}
template <class stack>**
StackType*<stack>*::pop( & item)
{
if( !isEmpty() )
{
item = items[top];
top--;
}
}
template <class stack>**
int StackType*<stack>*::getStackNum ()
{
return top+1;
}
main
/* Erik Malone and Catherine Stringfellow and Trey Brumley Date: December-5-2013
File: prog5.cpp
Program Specifications
Narrative: Program that evaluates and converts postfix expressions.
Interface:
Introductory Screen:
"Postfix Calculator and Converter"
Exit Screen:
"Goodbye..."
Input:
numbers in expressions should be separated by a space.
(from keyboard, see attached)
Output:
(all to screen, see attached)
Constants:
STACK_MAX
*/
#include "stack"**
#include <string>
#include <iostream>
#include <cmath>
#include <iomanip>
#include <cstdlib>
#include <cctype>
int getValidChoice ();
/* purpose: get valid option choice from menu
prereq: NONE
postcond: int (for a valid choice returned)
*/
void readString(string& s);
/* purpose: Reads a line into a string
recieves: string <s>
returns: NONE
*/
void printString(const string& s);
/* purpose: Prints a string
recieves: const string <s>
returns: NONE
*/
void convertPostfix(string& post, string& result);
/* purpose: converts a prefix expression to infix
recieves: string <post>, string <result>
returns: NONE
*/
void convert(StackType & s, char ch);
/* purpose: pops two operands off a string stack and pushes the result
recieves: string <post>, char <ch>
returns: NONE
*/
void evalPostfix(string& post, double& answer);
/* purpose: calculates the value of the prefix expression
recieves: string <post>, double <answer>
returns: NONE
*/
void evaluate(StackType & s, char ch);
/* purpose: pops two operands off a double stack and pushes the result
recieves: Stack <s>, char <ch>
returns: NONE
*/
void error(int m);
//prints an error message, based on int parametet
//print the introduction and exit screens
void intro();
void outro();
void main()
{
string post;
double answer;
int choice;
//intro screen
intro();
//while user wants to continue
choice = getValidChoice();
while (choice != 3) {
//switch menu options
switch (choice)
{
case 1:
cout<<"Please enter a postfix expression: ";
readString(post);
if (post == "") //error if string empty
error(1);
else
{
evalPostfix(post, answer);
printString(post);
cout<<" = "<<answer<< endl << endl;
}
break;
case 2:
cout<<"Please enter a postfix expression: ";
readString(post);
if (post == "")
error(1);
else
{ string tempString = "";
convertPostfix(post, tempString);
cout<<"Postfix expression: ";
printString(post);
cout<<"\nEpression converted to infix: "<<tempString << endl<<endl;
}
break;
default: //if choice is not recognized print error
error(3);
} //end switch
choice = getValidChoice();
} //end while
outro();
//exit screen on return
system("pause");
}
int getValidChoice ()
{
int choice;
//display menu options
cout<<" Options \n";
cout<< " (1) Evaluate postfix expression " << endl;
cout<< " (2) Convert postfix to infix " << endl;
cout<< " (3) Quit " << endl;
//get menu option
cout<<"Enter option: ";
cin>>choice;
cout <<endl;
//validate menu option
while ((choice < 1) || (choice > 3)) {
cout << "Enter a value between 1 and 3: ";
cin >> choice;
}
return choice;
}
void printString(const string& s)
{
if (s.empty())
cout<<"Empty"; //if string is empty print "empty"
else
cout<<s;
}
void readString(string& s)
{
char temp[40];
cin.ignore(80,'\n'); //clear buffer
cin.getline(temp, 40); //copy line to string
s = temp;
}
void evalPostfix(string& post, double& answer)
{
int index = 0, total = 0;
double tempDbl;
bool negative = false; //to detect negative signs
StackType s; //declare a stack of doubles
//loop index until end of string
while (index < (int) post.length())
{
//pass over spaces in string
while (isspace(post[index]))
index++ ;
//if operator evaluate incrementing index
if (!isdigit(post[index]) &&
!((index+1 < (int) post.length()) &&
(post[index] == '-' && isdigit(post[index+1]))))
//if (!isdigit(post[index]))
evaluate(s, post[index++]);
else
{ //if number, checks for negative sign
if (post[index] == '-')
{
index++;
negative = true;
}
//add up the digits from string
while ((post[index] >= '0') && (post[index] <= '9'))
total = (total * 10) + (post[index++] - '0');
//if there was a negative sign, negate total
if (negative)
{
total = total * -1;
negative = false;
}
//push number onto stack
s.push(total);
total = 0;
}
index++;
}
//pop answer from stack
s.pop(tempDbl);
answer = tempDbl;
}
void evaluate(StackType & s, char ch)
{
double op1, op2;
//check if empty before popping operands
if (!s.isEmpty())
{
s.pop(op2);
if (!s.isEmpty())
{
s.pop(op1);
//push result
switch(ch)
{
case '+':
s.push(op1 + op2);
break;
case '-':
s.push(op1 - op2);
break;
case '*':
s.push(op1 * op2);
break;
case '/':
s.push(op1 / op2);
break;
default:
return;
}
}
}
}
void convertPostfix(string& post, string& result)
{
int index = 0;
string tempString;
StackType s; //declare a stack of strings
//loop index until end of string
while (index < (int) post.length())
{
//pass over spaces in string
if (isspace(post[index]))
index++ ;
//if operator convert incrementing index
if (!isdigit(post[index]) &&
!((index+1 < (int) post.length()) &&
(post[index] == '-' && isdigit(post[index+1]))))
//if (!isdigit(post[index]))
convert(s, post[index++]);
else
{
//clear string
tempString.erase();
//concatenate numbers to string
while (!isspace(post[index]))
tempString = tempString + post[index++];
//push string onto stack
s.push(tempString);
}
index++;
}
//pop resulting string from stack
s.pop(result);
}
void convert(StackType & s, char ch)
{
string op1, op2, tempString;
//check if empty before popping
if (!s.isEmpty())
{
s.pop(op2);
if (!s.isEmpty())
{
s.pop(op1);
//constructing string for result
tempString = tempString + "( ";
tempString = tempString + op1;
//concatenate sign to string
switch(ch)
{
case '+':
tempString = tempString + " + ";
break;
case '-':
tempString = tempString + " - ";
break;
case '*':
tempString = tempString + " * ";
break;
case '/':
tempString = tempString + " / ";
break;
default:
return;
}
//adding rest of the string
tempString = tempString + op2;
tempString = tempString + " )";
//push resulting string onto stack
s.push(tempString);
}
}
}
void error(int m)
{
system("cls"); //clear screen
cout<<"\a"; //system beep
//displays error message according to parameter passed
switch (m)
{
case -1:
cout<<"INTERNAL ERROR";
break;
case 1:
cout<<"ERROR - Postfix expression empty.";
break;
case 3:
cout<<"ERROR - invalid entry.";
break;
default:
cout <<"UNKNOWN ERROR.";
}
cout << endl << endl;
}
void intro()
{
system("cls"); //clear screen
//displays welcome message
cout<<"Postfix Calculator and Converter\n\n";
}
void outro()
{
cout<<"Goodbye...\n\n"; //display exit message
}
As for 2) it has to be std::string, or you could say
using std::string;
or
using namespace std;
and then you should be able to say just string. I would recommend the former, unless you are pulling in a lot of stuff from std::
Other bits of trivia:
name your header file “stack.h”
you do not need a stack.cpp, just implement the functions in stack.h, e.g.
template
class Stack {
….
void doSomething(ElementType& object) {…}
….
};
This tends to be cleaner. You could also do it out of line but it still needs to be in the same file, and if you do it out-of-line, you need to prefix every function with the template keyword
you might want to pick a better more descriptive name than “stack” for the template argument.
You should switch the name of your class with the name of the template argument, that would make more sense. This would become
template <typename StackType>
class Stack
{
...
};
For example
void push(stack item);
Would be
void push(StackType item);
1) You can put the declaration and the definition of the methods into separate files but you need to include them at the end like you did but I suggest your rename you stack.cpp to stack.inl (.inl for inline) or something else.
3) If you use 2 files like above there's no need to include stack.h inside stack.cpp/inl. Think of this like it's the same file. And be careful with that using namespace std since everyone that include your stack.h will be "using namespace std" and that might cause issues...
Finally, there's no template specialization in your source code and there's is no such thing as specialization file. However, template specialization do exist and it's probably not what you expect. More info here
Related
This code is supposed to convert a given postfix expression to a prefix expression,i was experimenting with the string object in c++ but I don't have enough experience to figure out the problem
I think there's an issue in the push() function
Note:I haven't used the stack header file and implemented the stack using array
here's the code
#include <bits/stdc++.h>
#include <iostream>
#define MAX 5
using namespace std;
class stack1
{
private:
int stackTop,expTop;
string stack[MAX],expression;
public:
stack1()
{
stackTop = -1;
for (int i = 0; i < MAX; i++)
{
stack[i] = " ";
}
getexp();
check(expression);
display();
}
string pop();
void push(string expr);
void display();
bool isempty();
bool isfull();
string combo(string optr1,string optr2,string opr);
void getexp();
void check(string expre);
bool isOperator(string ch);
};
//-----------Gets Expression From User------------------------------------------
void stack1::getexp()
{
cout<<"Enter the Postfix Expression"<<endl;
cin>>expression;
expTop=expression.length()-1;
}
void stack1::check(string expre)
{
string ch;
int i=0;
while(expre[i]!=(expre.length()-1))
{
ch=expre[i];
if(isOperator(ch))
{
push(combo(pop(),ch,pop()));
}
else
{
push(ch);
}
}
}
/*
-------------------------------------------------------------------
Inputs:
takes 2 values from the stack which will be operands
either as single characters or whole strings,these
values will be passed as optr1 and opttr2,it will
also take operators such as +,-,* etc.. as char.
these will be passed in place of opr.
working:
combines all the passed values into a single string
into the following format
( optr1 opr optr2 )
and finaly returns this string
----------------------------------------------------------------------
*/
string stack1::combo(string optr1, string optr2, string opr)
{
string expr;
expr="("+optr1+opr+optr2+")";
return expr;
}
/*
------------------------------------------------------------------------
Working:
pops the top value from the stack
and returns it.
decrements the top pointer
and initializes the poped element to " "
-------------------------------------------------------------------------
*/
string stack1 ::pop()
{
string x;
if (isempty())
{
cout << endl
<< "The stack1 is empty" << endl;
}
x=stack [stackTop];
stack [stackTop] = " ";
stackTop--;
return x;
}
void stack1 ::push(string expr)
{
stackTop++;
stack [stackTop] = expr;
}
bool stack1 ::isempty()
{
if (stackTop == -1)
return true;
else
return false;
}
bool stack1 ::isfull()
{
if (stackTop == MAX - 1)
return true;
else
return false;
}
bool stack1::isOperator(string ch)
{
if (ch[0] == '*' || ch[0] == '/' || ch[0] == '+' || ch[0] == '-' || ch[0] == '^')
return true;
else return false;
}
void stack1::display()
{
cout<<"Infix:\t"<<stack[0]<<endl;
}
int main()
{
stack1 obj;
return 0;
}
Besided the obvious hard bug with #include <bits/stdc++.h> which is not part of C++ (and does not even compile on my machine), you have 2 semantic bugs in your code, which lead to a problem.
Additionally you have a design problem leading to an only partially solution.
And, maybe a misunderstanding of the terms and meaning of "string" and "character"
Example: The string "hello" consists of 5 characters: 'h', 'e', 'l', 'l', 'o'
If you use a std::string and initialize it with "hello" (which is of type const char[6]), the the constructor of the std::string will convert your character array to a std::string, containing the following characters at indices:
index character
0 'h'
1 'e'
2 'l'
3 'l'
4 'o'
5 '\0'
In your "check" function in line while(expre[i]!=(expre.length()-1)) you access expre[i] which is a character (for example an 'a') and compare it to the length of the std::string "expre". This can of course not work.
The while loop will never terminate. "i" is always the same and you will push always the first character of the input string onto the stack, unti it is full and you get an exception. You should add an overflow-check in your push function.
Additionally, you use a wrong parameter sequence in/with your "combo" function.
If you modify the while loop like the below, then at least this part will work.
string ch;
int i = 0;
//while (expre[i] != (expre.length() - 1))
while (i != (expre.length()))
{
ch = expre[i];
if (isOperator(ch))
{
push(combo(pop(), pop(),ch));
}
else
{
push(ch);
}
++i;
}
Now you can successfully convert "abcd+^" to "(a^(b(c+d)))".
But still, it will not work fully.
Additionally:
You should use your constructor only to initialize your class.
Please use characters where appropriate and not full std::strings
The whole design needs to be reworked.
Because: basically you are creating an infix and not a prefix expression.
Hence, for learning purposes look at here
I want to give the expression in the form of parenthesis through CIN, like: ()). then, through push & pop operation of the stack, I want the program to print me weather the given expression is BALANCED or NOT. The program works perfectly but only one issue has been found & that is when I enter like ()(, so it tells me that this expression is IMBALANCED which is fine but when I enter like () (, so then it tell me that this expression is BALANCED which is actually not balanced.
#include <iostream>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
using namespace std;
char Stack[10];
int top=-1;
void push(char ch)
{
if(top<10)
{
top++;
Stack[top] = ch;
}
else
cout<<"Stack Overflow";
}
void pop()
{
if(top > -1)
{
top--;
}
else
cout<<"Stack Underflow";
}
int show(){
cout<<"It is imbalanced.";
}
int main(int argc, char** argv)
{
int a=0,b=0;
string exp;
cout << "Write down the parenthesis:" ;
cin >> exp;
bool check = true;
for(int i=0; i<exp.length(); i++)
{
if(exp[i]== '(')
{
push(exp[i]);
}
else if(exp[i]== ')')
{
if(top == -1)
{
check = false;
break;
}
else
{
pop();
}
}
}
for(int i=0; i<exp.length(); i++)
{
if(exp[i]=='('){
++a;
}
else if (exp[i]==')')
{
b++;
}
}
if(a>b){
cout<<"\n\nGiven Combination is IMBALANCED";
return 0;
}
if(check == true)
cout<<"\n\nGiven Combination is BALANCED";
else
cout<<"\n\nGiven Combination is IMBALANCED";
return 0;
}
The main comments boil down to:
Don’t use a stack when no stack is needed.
And if you do use one, don’t limit it to an arbitrary fixed depth.
Handle errors and report malformed expressions.
Make sure you get the right input; std::getline() may be less error-prone than input tokenized using the >> operators. Just skip spaces (or whatever insignificant characters are allowed in the input).
using namespace std; is an antipattern and a bad habit.
The basic idea: Calculate the nesting depth as you iterate over the string. It must be zero, ultimately. It must not drop below zero at any point.
#include <cstdlib>
#include <iostream>
#include <stdexcept>
#include <string>
#include <string_view>
using std::size_t;
bool correctly_parenthesized(std::string_view expression) {
size_t depth{0};
for (const auto character : expression) {
switch (character) {
case '(': ++depth; break;
case ')': if (depth) { --depth; break; } else { return false; }
case ' ': break;
default: throw std::invalid_argument("invalid character");
}
}
return depth == 0;
}
int main() {
std::cout << "Write down the parentheses: ";
std::string exp;
std::getline(std::cin, exp);
try {
std::cout << (correctly_parenthesized(exp) ? "YES" : "NO") << std::endl;
} catch (const std::exception &e) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
}
I'm currently trying to get this postfix expression eval to work but I believe within the int EvaluatePostfix function I'm using stackPtr->peek() incorrectly because whenever I try and get the top value and subtract it by '0' (not shown in code, mb) to convert it to int it says it's a "std::basic_string-char-" so it cant do the subtraction with type char.
postfix.cpp:
#include <iostream>
#include <string>
#include "ArrayStack.h"
bool IsNumericDigit(char C)
{
if(C >= '0' && C <= '9') return true;
return false;
}
// Function to verify whether a character is operator symbol or not.
bool IsOperator(char C)
{
if(C == '+' || C == '-' || C == '*' || C == '/')
return true;
return false;
}
// Function to perform an operation and return output.
int PerformOperation(char operation, int operand1, int operand2)
{
if(operation == '+') return operand1 +operand2;
else if(operation == '-') return operand1 - operand2;
else if(operation == '*') return operand1 * operand2;
else if(operation == '/') return operand1 / operand2;
else std::cout<<"Unexpected Error \n";
return -1;
}
int EvaluatePostfix(std::string expression, StackInterface<std::string>* stackPtr)
{
for(int i = 0;i< expression.length();i++)
{
// Scanning each character from left.
// If character is a delimiter, move on.
if(expression[i] == ' ' || expression[i] == ',') continue;
// If character is operator, pop two elements from stack, perform operation and push the result back.
else if(IsOperator(expression[i]))
{
// Pop two operands.
int operand2 = stackPtr->peek();
stackPtr->pop();
int operand1 = stackPtr->peek();
stackPtr->pop();
//operand1 and operand2 are reversed in case of Prefix Expression
// Perform operation
int result = PerformOperation(expression[i], operand1, operand2);
//Push back result of operation on stack.
stackPtr->push(result);
}
else if(IsNumericDigit(expression[i]))
{
// Extract the numeric operand from the string
// Keep incrementing i as long as you are getting a numeric digit.
int operand = 0;
while(i<expression.length() && IsNumericDigit(expression[i]))
{
// For a number with more than one digits, as we are scanning from left to right.
// Everytime , we get a digit towards right, we can multiply current total in operand by 10
// and add the new digit.
operand = (operand*10) + (expression[i] - '0');
std::cout << operand << std::endl;
i++;
}
// Finally, you will come out of while loop with i set to a non-numeric character or end of string
// decrement i because it will be incremented in increment section of loop once again.
// We do not want to skip the non-numeric character by incrementing i twice.
i--;
// Push operand on stack.
stackPtr->push(operand);
}
}
// If expression is in correct format, Stack will finally have one element. This will be the output.
return stackPtr->top();
}
int main(){
StackInterface<std::string>* stackPtr = new ArrayStack<std::string>();
std::string expression;
std::cout<<"Enter Postfix Expression \n";
std::getline(std::cin,expression);
EvaluatePostfix(expression, stackPtr)
std::cout << stackPtr->push(expression);
}
ArrayStack.h:
#ifndef ARRAY_STACK_EXCEPTIONS
#define ARRAY_STACK_EXCEPTIONS
#include "StackInterface.h"
#include "PrecondViolatedExcep.h"
const int MAX_STACK = 1000;
template<class ItemType>
class ArrayStack : public StackInterface<ItemType>
{
private:
ItemType items[MAX_STACK]; // Array of stack items
int top; // Index to top of stack
public:
ArrayStack();
bool isEmpty() const;
bool push(const ItemType& newEntry);
bool pop();
ItemType peek() const;
}; // end ArrayStack
template<class ItemType>
ArrayStack<ItemType>::ArrayStack() : top(-1)
{
} // end default constructor
// Copy constructor and destructor are supplied by the compiler
template<class ItemType>
bool ArrayStack<ItemType>::isEmpty() const
{
return top < 0;
} // end isEmpty
template<class ItemType>
bool ArrayStack<ItemType>::push(const ItemType& newEntry)
{
bool result = false;
if (top < MAX_STACK - 1)
{
// Stack has room for another item
top++;
items[top] = newEntry;
result = true;
} // end if
return result;
} // end push
template<class ItemType>
bool ArrayStack<ItemType>::pop()
{
bool result = false;
if (!isEmpty())
{
result = true;
top--;
} // end if
return result;
} // end pop
template<class ItemType>
ItemType ArrayStack<ItemType>::peek() const
{
// Enforce precondition
if (isEmpty())
throw PrecondViolatedExcep("peek() called with empty stack");
// Stack is not empty; return top
return items[top];
} // end peek
Edit: The error I get when subtracting stackPtr->peek() by '0' is "no match for 'operator-' (operand types are 'std::basic_stringchar' and
char'"
Thanks!
The problem here is that you are using std::string, char, and int interchangeably, while they are not.
Notice that your data type for you stack is string, and there isn't default way to change from string to int or string to char.
Based on your descriptions, you were trying to get the first char out of the string, which you would probably call either:
c = stackPtr->peek()[0];
or
c = stackPtr->peek().front();
string to int would call std::stoi(stackPtr->peek()), but not sure if you want it as you are implementing it yourself.
So you probably want to extract this part as a separate function:
while(i<expression.length() && IsNumericDigit(expression[i]))
{
operand = (operand*10) + (expression[i] - '0');
std::cout << operand << std::endl;
i++;
}
so you can easily reuse it when you get a string from your stack.
#include<iostream>
#include<stdio.h>
#define MAX 20
using namespace std;
char stk[MAX];
int top=-1;
void push(char c)
{
if(top==MAX-1)
cout<<"Overflow";
else
{
stk[++top]=c;
}
}
char pop()
{
if(top==-1)
{
return '\0';
}
else
return stk[top--];
}
int priority(char ch)
{
if(ch=='(')
return 1;
if(ch=='+'||ch=='-')
return 2;
if(ch=='*'||ch=='/')
return 3;
if(ch=='^')
return 4;
}
int main()
{
char exp[35],*t,x;
cout<<"Enter expression: ";
fgets(exp,35,stdin);
t=exp;
while(*t)
{
if(isalnum(*t))
cout<<*t;
else if(*t=='(')
push(*t);
else if(*t==')')
{
while((x=pop())!='(')
cout<<x;
}
else
{
if(priority(stk[top])>=priority(*t))
cout<<pop();
push(*t);
}
t++;
}
while(top!=-1)
cout<<pop();
return 0;
}
The output for input:
a+b-(c+d/e)
is
ab+cde/+
-
I don't understand why - is on a newline.
I have just started learning c++ and I am trying to implement some programs I did in c using c++. The same code in c works fine. I think there are some holes in my basic c++ knowledge and I would like to fill them up.
std::fgets does not discard the newline in the input stream like getline would. That means exp contains "a+b-(c+d/e)\n" and not "a+b-(c+d/e)". You either need to remove the newline from exp, switch to cin.getline(), or stop your processing loop when it hits the newline.
Try to change fgets to std::cin. And use std::string instead of char*:
#include <iostream>
#include <string>
int main()
{
string exp;
cout << "Enter expression: ";
std::cin >> exp;
auto t = exp.data();
char x;
for(auto &ch: exp)
{
if(isalnum(ch))
cout << ch;
else if(ch == '(')
push(ch);
else if(ch == ')')
{
while((x = pop()) != '(')
cout << x;
}
else
{
if(priority(stk[top]) >= priority(ch))
cout << pop();
push(ch);
}
}
while(top != -1)
cout << pop();
return 0;
}
In addition to the processing of '\n' as mentioned by NathanOliver, your function priority() doesn't return a value when the user entered any other character not checked in the if statements, so the behavior might be undefined.
I am having some trouble with a program that is supposed to take a command line expression and interpret it as a normal mathematical expression.This is what I am getting as an error:
driver.cpp: In function ‘int main(int, char**)’:
driver.cpp:17:57: error: no matching function for call to‘PrefixCalculator::eval(std::istringstream)’
driver.cpp:17:57: note: candidate is:
PrefixCalculator.h:33:3: note: T PrefixCalculator::eval(std::istringstream&) [with T = int, std::istringstream = std::basic_istringstream]
PrefixCalculator.h:33:3: note: no known conversion for argument 1 from ‘std::istringstream {aka std::basic_istringstream}’ to ‘std::istringstream& {aka std::basic_istringstream&}’
I can't understand what the error is trying to suggest to me.
Any suggestions for fixing that? I'm going to add exceptions later, so they are commented out for now.
This is the code:
PrefixCalculator.cpp
#pragma once
#include <sstream>
using namespace std;
template<class T>
class PrefixCalculator {
public:
PrefixCalculator(void){
numOperator = 0;
numOperand = 0;
};
~PrefixCalculator(void){};
T eval(istringstream&);
int getNumOperator() {
return numOperator;
};
int getNumOperand() {
return numOperand;
};
private:
//if you feel you need private helper functions and/or helper data
int numOperator;
int numOperand;
};
template<class T>
T PrefixCalculator<T>::eval(istringstream& input) {
//this function needs to throw an exception if there's a problem with the expression or operators
char nextChar = input.peek();
//this while loop skips over the spaces in the expression, if there are any
while(nextChar == ' ') {
input.get(); //move past this space
nextChar = input.peek(); //check the next character
}
if(nextChar == '+') {
input.get(); //moves past the +
numOperator++;
return eval(input) + eval(input); //recursively calculates the first expression, and adds it to the second expression, returning the result
}
/***** more operators here ******/
if(nextChar == '-') {
input.get();
numOperator++;
return eval(input) - eval(input);
}
if(nextChar == '*') {
input.get();
numOperator++;
return eval(input) * eval(input);
}
if(nextChar == '/') {
input.get();
numOperator++;
return eval(input) / eval(input);
}
/****** BASE CASE HERE *******/
//it's not an operator, and it's not a space, so you must be reading an actual value (like '3' in "+ 3 6". Use the >> operator of istringstream to pull in a T value!
input>>nextChar;
T digit = nextChar - '0';
numOperand++;
return digit;
//OR...there's bad input, in which case the reading would fail and you should throw an exception
}
driver.cpp
#include <sstream>
#include <string>
#include <iostream>
#include "PrefixCalculator.h"
using namespace std;
int main(int argc, char** argv) {
PrefixCalculator<int> calc;
string expression;
cout << "Give a prefix expression to evaluate, or q to quit." << endl;
getline(cin,expression);
while(expression[0] != 'q') {
//try {
int result = calc.eval(istringstream(expression));
cout << result << endl;
//}
//catch { //will not compile, you have to finish this!
//
//}
cout << "Give a prefix expression to evaluate or q to quit." << endl;
getline(cin,expression);
}
return 0;
}
calc.eval(istringstream(expression)); passes a temporary instance to eval(), you'll need an lvalue.
Provide an extra variable for the stream
istringstream iss(expression);
and pass that one
int result = calc.eval(iss);