prefix calculator having trouble compilng - c++

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);

Related

I am Not able to find out where this code went wrong

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

Invalid String initialization for c++

I was trying to make a script for a math thing that a saw and I got the following error...
line 23|error: invalid initialization of non-const reference of type 'std::__cxx11::string&' {aka 'std::__cxx11::basic_string&'} from an rvalue of type 'bool'|
I am pretty new to c++ and I tried to search this problem on the internet, but nothing works. Can you please help me?? (code below btw)
#include <string>
#include <math.h>
using namespace std;
bool hasEnding (std::string &fullString, std::string &ending) {
if (fullString.length() >= ending.length()) {
return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending));
} else {
return false;
}
}
int main() {
int current_num;
bool odd;
bool even;
cout << "Type a positive number: "; // Type a number and press enter
cin >> current_num;
while (current_num >= 2) {
std::string s = std::to_string(current_num);
cout << s << endl;
odd = hasEnding (s, "1"||"3"||"5"||"7"||"9");
even = hasEnding (s, "0"||"2"||"4"||"6"||"8");
if (odd == true) {
current_num = current_num*3;
current_num = current_num+1;
}
if (even == true) {
current_num = current_num/2;
}
}
return 0;
}
Thanks to the people in the comments... I fixed it by finding a thing that checks if a number in even or odd instead of making a very inefficient script which checks the last number. The solution for it was n % 2 == 0

C++ Postfix expression evaluation using stacks. I dont think I'm converting the data correctly

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.

I have written this program for infix to postfix conversion

#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.

Extracting int for char array in C++

I am trying to extract single character from char array and converting it in to integer.
I need to extract number from code for example if user enters A23B,I need to extract 23 and store it in a single variable here is my code
#include <iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;
int main()
{
char code[5] ={'\0'};
cout << "Enter Your Four Digit Code\nExample A23B\n";
cin.getline(code,5);
cout << "You typed:\n" << code;
int a = atoi(code[1]);
int b = atoi(code[2]);
cout << endl <<a <<"\t"<<b;
//Other processing related to number a and b goes here
}
but it's not working and produces the following errors
C:\helo\clan\Test\main.cpp||In function 'int main()':|
C:\helo\clan\Test\main.cpp|12|error: invalid conversion from 'char' to 'const char*'|
C:\helo\clan\Test\main.cpp|12|error: initializing argument 1 of 'int atoi(const char*)'|
C:\helo\clan\Test\main.cpp|13|error: invalid conversion from 'char' to 'const char*'|
C:\helo\clan\Test\main.cpp|13|error: initializing argument 1 of 'int atoi(const char*)'|
||=== Build finished: 4 errors, 0 warnings ===|
atoi takes a const char*, not char.
If you need to get '2' and '3' from "A23B":
int b = atoi(code + 2);
code[2] = 0;
int a = atoi(code + 1);
If you need to get '23' from "A23B" then:
int a = atoi(code + 1);
For common situation , why not using std::string and std::stringstream like this:
#include <string>
#include <sstream>
template <class T>
std::string num2string (const T &in)
{
static std::stringstream out;
out.str ("");
out.clear();
out << in;
return out.str();
}
template <class T>
T string2num (const std::string &in)
{
T out;
static std::stringstream tmp;
tmp.str ("");
tmp.clear();
tmp << in;
tmp >> out;
return out;
}
You can use these two functions converting string between nums(int,double...).
Why not
int a = int(code[1]-'0') * 10 + int(code[2] - '0');
i.e. Convert the two ASCII characters to the appropriate integers and then do the maths.
EDIT
You should check to ensure that the string is 4 characters long and characters 2 & are digits.
You pass a char to a function that expects char *, and you can't do that. Why not doing:
int a = code[1] & 0xff;
int b = code[2] & 0xff;
I think you want something like this:
#include <iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;
int main()
{
char code[5] ={'\0'};
cout << "Enter Your Four Digit Code\nExample A23B\n";
cin.getline(code,5);
cout << "You typed:\n" << code;
char aStr[2] = {code[1], 0};
char bStr[2] = {code[2], 0};
int a = atoi(aStr);
int b = atoi(bStr);
cout << endl <<a <<"\t"<<b;
//Other processing related to number a and b goes here
}
And if you want 23 in one variable then maybe this:
char aStr[3] = {code[1], code[2], 0};
int a = atoi(aStr);
Your code is horribly unsafe (what if the user enters more than four digits? What if a line break takes up more than one byte?)
Try something like this:
int a, b;
std::string line;
std::cout << "Enter Your Four Digit Code (Example: A23B): ";
while (std::getline(std::cin, line))
{
if (line.length() != 4 || !isNumber(line[1]) || !isNumber(line[2]))
{
std::cout << "You typed it wrong. Try again: ";
continue;
}
a = line[1] - '0';
b = line[2] - '0';
break;
}
We need the isNumber helper:
inline bool isNumber(char c) { return '0' <= c && c <= '9'; }
If anyone wants to do this code with out including to many library's(Some schools require just basic libraries like mine)
This function is done with cmath and cctype
It will take in a course number like cs163 and turn it into an int of 163
ascii value for 1 = 49 that is why the - 48 is there.
Something like this will do it as well, but with out using a lot of function like string class.
This isn't super optimised I know, but it will work.
int courseIndexFunction(char * name){
int courseIndex = 0;
int courseNameLength = 5;
if (name[2] && name[3] && name[4]){
//This function will take cs163 and turn
//it into int 163
for (int i = 2; i < courseNameLength; ++i){
double x = name[i] - 48;
x = x * pow(10.0 , 4-i);
courseIndex += x;
}
}
return courseIndex;
}