首页 > 解决方案 > 在 C++ 中使用带有 Stack 模板的字符串时遇到问题

问题描述

我有一个任务,我们必须用后缀和中缀操作做一些事情。我的教授向我们提供了所有代码,其中 main 中的一段代码为空,供我们执行某些后缀操作。我正在尝试实现他提供的带有字符串的 Stack 模板,但它不起作用。这是 main 的代码(您可以忽略所有注释掉的部分):

#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++;
    
  }
}

*/

如果我注释掉堆栈声明(“Stack<string> stack;”),则程序编译并在运行时输出“Start”。但是,如果我包含堆栈声明,程序似乎再次成功编译,但是当我运行它时,绝对没有任何反应。这就是我注释掉所有其余代码的原因,所以我可以在较小的范围内对其进行测试,但仍然没有。我什至在教授提供的 Stack cpp 文件的末尾包含了模板字符串声明。

这是我的教授提供的 Stack.hpp:

//#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
};

这是我的教授也提供的 Stack.cpp(我在末尾添加了“模板类 Stack<string>;”):

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

我不明白发生了什么事。我认为在 Stack.cpp 末尾添加声明可以解决我遇到的所有问题(之前,我遇到了一堆“未定义的引用...”错误)但是,现在我也遇到了这个问题。有人可以帮我理解为什么这不起作用吗?任何帮助将不胜感激。顺便说一句,一切都与“Stack<int>”和“Stack<char>”完美配合,它只是“Stack<string>”,我遇到了这个问题。谢谢你。

我已经尝试阅读一堆与此类似的问题的其他答案,但没有一个能回答我的问题。我已经使用了显式实例化我将在 .cpp 文件末尾使用的实现的方法,但我的程序仍然无法正常工作。我不想将所有内容都移到头文件中,因为该文件最初不是我的(我只想进行细微的编辑,并且只有在绝对必要的情况下)。

标签: c++stringtemplatesstack

解决方案


大多数编译器都sizeof(std::string)等于 24 字节(x32 架构)或 32 字节(x64 架构)。通过在, will be或中创建100000字符串数组。Stack<std::string>sizeof(Stack<std::string>)100000 * 24 = 2.28MiB100000 * 32 = 3.05MiB

然后您尝试在自动内存区域(也称为“堆栈内存”,因为它通常是这样实现的)中创建这样的对象。这种记忆是非常有限的。实际限制取决于您的操作系统(也可能会更改),但对于 Unix 系统,默认情况下通常为 8 MiB,对于 Windows,则为 1 MiB(请参阅此问题)。

您可以修改操作系统中的自动存储量,但推荐的方法是降低MAXSIZE或使用动态分配。后者最好用C++std::vector<T>std::unique_ptr<T[]>在 C++ 中完成。


推荐阅读