-1

I have an assignment where we have to do some stuff with postfix and infix operations. My professor provided all of the code to us with a section of the code in main empty for us to perform certain postfix operations. I am trying to implement the Stack template he provided with strings but it is not working. Here is the code for main (you can ignore all the commented out part):

#include "stack.hpp"
using namespace std;

int main()
{
  cout << endl << "Start" << endl;
  Stack<string> stack;
  //string s = "hello world";
  //char s = 'h';
  //stack.push(s);
  //cout << endl << endl << stack.pop() << endl << endl;
  return 0;
}

/*

// Auxiliary method, you probably find it useful
// Operands are all lower case and upper case characters
bool isOperand(char c){
  return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}

// Auxiliary method, you probably find it useful
int precedence(char c)
{
  if(c == '+' || c == '-'){
    return 0;
  }
  if(c == '*' || c == '/'){
    return 1;
  }
  if(c == '^'){
    return 2;
  }
  return -1;
}

int main(){

cout << endl << "start" << endl;
  freopen("input_postfix2infix.txt", "r", stdin);
  string input;
  string solution;
  int line_counter = 0;

  cout << endl << "before loop" << endl;
  while(cin >> solution){
    cin >> input;
    Stack<string> stack;
    string result;

     //The input file is in the format "expected_solution infix_expression", 
     //where expected_solution is the infix_expression in postfix format

    string s = "hello world";
    //char s = 'h';
    stack.push(s);
    cout << endl << endl << stack.pop() << endl << endl;

    //cout << input << endl << endl;
    for(int i=0; i<input.length(); ++i){
        char c = input.at(i);
        if(isalnum(c))
        {
            string s;
            s.push_back(c);
            stack.push(s);
        }
        else
        {
            if(c == '+')
            {
                string a = stack.pop();
                string b = stack.pop();
                string sum = a + '+' + b;
                sum = '(' + sum + ')';
                stack.push(sum);
            }
            else if(c == '-')
            {
                string a = stack.pop();
                string b = stack.pop();
                string diff = b + '-' + a;
                diff = '(' + diff + ')';
                stack.push(diff);
            }
            else if(c == '*')
            {
                string a = stack.pop();
                string b = stack.pop();
                string prod = a + '*' + b;
                prod = '(' + prod + ')';
                stack.push(prod);
            }
            else if(c == '/')
            {
                string a = stack.pop();
                string b = stack.pop();
                string quot = b + '/' + a;
                quot = '(' + quot + ')';
                stack.push(quot);
            }
            else if(c == '^')
            {
                string exp = stack.pop();
                string a = stack.pop();
                string power = a + '^' + exp;
                power = '(' + power + ')';
                stack.push(power);
            }
        }
        // WRITE CODE HERE to store in 'result' the postfix transformation of 'input'

    }
    result = stack.pop();
  
    // You need to do some extra stuff here to store in 'result' the postfix transformation of 'input'
    
    // Checking whether the result you got is correct
    if(solution == result){
      cout << "line " << line_counter << ": OK [" << solution << " " << result << "]" << endl;
    }else{
      cout << "line " << line_counter << ": ERROR [" << solution << " " << result << "]" << endl;
    }
    line_counter++;
    
  }
}

*/

If I comment out the stack declaration ("Stack<string> stack;") then the program compiles and when it runs, "Start" is outputted. However, if I include the stack declaration, the program seems to compile successfully again, but when I run it, absolutely nothing happens. That's why I commented out all the rest of the code, so I can test it out on a smaller scale, and still nothing. I have even included the template string declaration at the end of the Stack cpp file my professor provided.

Here is Stack.hpp provided by my professor:

//#include <bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>

// Ideally this would not be a huge number, you could also use a vector
#define MAXSIZE 100000

using namespace std;
template<class T>
class Stack{
private:
  T arr[MAXSIZE]; // the actual stack
  int topIndex;   // index of the top element
public:
  Stack(){
    topIndex = -1; // constructor
  };
  ~Stack(){};      // destructor
  void push(T c);  // push c to the list
  T pop();         // return and remove the top element in the stack
  T peek();      // return the top element in the stack
  int size();      // returns the size of the stack
  void display();  // display the stack in stdout
};

Here is Stack.cpp also provided by my professor (I added the "template class Stack<string>;" at the end):

#include "stack.hpp"

using namespace std;

template<class T>
void Stack<T>::push(T c){
  if(topIndex > MAXSIZE-1){
    cout<<"Stack overflow"<<endl;
    return;
  }
  arr[topIndex + 1] = c;
  topIndex++;
}

template<class T>
T Stack<T>::pop(){
  if(topIndex < 0){
    cout<<"Cannot delete. Stack empty."<<endl;
  }

  return arr[topIndex--];
}

template<class T>
T Stack<T>::peek(){
  if(topIndex < 0){
    cout<<"Cannot peek. Stack empty."<<endl;
  }
  return arr[topIndex];
}

template<class T>
int Stack<T>::size(){
  return topIndex+1;
}

template<class T>
void Stack<T>::display(){
  for(int i=topIndex; i>=0; --i){
    cout<<arr[i]<<"\t";
  }
  cout<<endl;
}

template class Stack<char>;
template class Stack<int>;
template class Stack<string>;

I don't understand what is going on. I thought adding the declaration at the end of Stack.cpp would fix ALL the issues I was having (before, I was getting a bunch of "undefined reference too..." errors) but, now I have this issue too. Could someone please help me too understand why this isn't working? Any help would be greatly appreciated. By the way, everything works perfectly with "Stack<int>" and "Stack<char>", its just "Stack<string>" where I have this problem. Thank you.

I have tried reading a BUNCH of other answers to questions similar to this one but none of them answers my issue. I have used the approach of explicitly instantiating the implementation I will use at the end of the .cpp file and yet my program is still not working. I do not want to move everything into the header file since the file is not originally mine (I only want to make minor edits and only if I absolutely have to).

  • 1
    `#include ` in stack.cpp? You are including `cstring` which is a different file. – 001 Feb 19 '21 at 21:35
  • 1
    `100000*(sizeof(std::string))` is probably something 1-3 MB, depending on your compiler and architecture. You probably get stack overflow and your program crashes. Use heap memory for such big containers (preferably in form of `std::vector` or `std::unique_ptr`). – Yksisarvinen Feb 19 '21 at 21:38
  • Oh yeah, I didn't realize this. By changing MAXSIZE to 10, the program ran. I might have to go ahead and make a new implementation of the Stack template as I do not want to change too much in his code. – joseph onuorah Feb 19 '21 at 21:46
  • @Yksisarvinen Thank you so much for your solution! – joseph onuorah Feb 19 '21 at 21:47

1 Answers1

2

Most compilers have sizeof(std::string) equal to 24 bytes (x32 architecture) or 32 bytes (x64 architecture). By creating array of 100000 strings in Stack<std::string>, sizeof(Stack<std::string>) will be 100000 * 24 = 2.28MiB or 100000 * 32 = 3.05MiB.

You then try to create such object in automatic memory area (also called "stack memory", because that's how it's usually implemented). This memory is highly limited. The actual limit depends on your OS (and may be changed as well), but for Unix systems it's usually 8 MiB by default, for Windows it would be 1 MiB (see this question).

You can modify the amount of automatic storage in your OS, but the recommended way would be to either lower MAXSIZE or to use dynamic allocation. The latter is preferably done with std::vector<T> or std::unique_ptr<T[]> in C++.

Yksisarvinen
  • 18,008
  • 2
  • 24
  • 52