1

String 是我自己的字符串类,Stack 是我自己的堆栈类。我正在尝试使用由空格分隔的值将中缀更改为后缀。

下面的函数几乎可以工作,但也会返回“分段错误(核心转储)”。

String postfix(String infix){
    std::vector<String> vec;
    vec = infix.split(' ');
    Stack<String> tmp;
    String right, left, op;

    int i = 0;
    while (vec[i] != ';'){
        if (vec[i] == ')'){
            right = tmp.pop();
            op = tmp.pop();
            left = tmp.pop();
            tmp.push(left + ' ' + right + ' ' + op);
        }else{
            if (vec[i] != '(' && vec[i] != ' ')
            tmp.push(vec[i]);
        }
        ++i;
    }

    String postfix = tmp.pop();
    return postfix;
}

我不明白为什么会这样。任何帮助,将不胜感激。

#ifndef STACK_HPP
#define STACK_HPP

template <typename T>
class Node{
public:
  T data;
  Node<T>* next;
  Node() {  data().next(0); } ;
  Node (const T& x) : data (x), next(0) {};
};


template <typename T>
class Stack{

public:
  Stack() : tos(0){};
  ~Stack();
  Stack(const Stack<T>&);
  void swap(Stack<T>& rhs);
  Stack<T>& operator= (Stack<T> rhs) { swap(rhs); return *this; };
  bool isEmpty() const { return tos == 0; };
  T pop();
  void push(const T&);

private:
  Node<T> *tos;
};

///////////////////////////////////////////////////////////////

template <typename T>
Stack<T>::~Stack(){
  while(tos != 0){
    Node<T> *tmp = tos;
    tos = tos -> next;
    delete tmp;
  }
}

template <typename T>
void Stack<T>::swap(Stack<T>& rhs){
  Node<T> *tmp = tos;
  tos = rhs.tos;
  rhs.tos = tmp;
}

template <typename T>
Stack<T>::Stack(const Stack<T>& actual){
  Node<T> *tmp = actual.tos, *bottom = 0;
  tos = 0;
  while (tmp != 0){
    if(tos == 0){
      tos = new Node<T>(tmp -> data);
      bottom = tos;
    }else{
      bottom -> next = new Node<T>(tmp -> data);
      bottom = bottom -> next;
    }
    tmp = tmp -> next;
  }
}

template<typename T>
T Stack<T>::pop(){
  T result = tos -> data;
  Node<T> *tmp = tos;
  tos = tos -> next;
  delete tmp;
  return result;
}

template <typename T>
void Stack<T>::push(const T& x){
  Node<T> *tmp = new Node<T> (x);
  tmp -> next = tos;
  tos = tmp;
}

#endif


//bruce pucci
//string
//cs23001
#include <iostream>
#include <cassert>
#include <vector>
#include <fstream>
#include "string.hpp"

///////////////////////////////string class friend functions////////////////////////
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////I/O/////////////////////////////////////////////
std::ostream& operator<<(std::ostream& out, const String& print){//std::cout operator
  int i = 0;
  while (print.arr[i] > 0){
    out << print.arr[i];
    ++i;
  }
  return out;
}
std::ifstream& operator>>(std::ifstream& in, String& rhs){//ifstream operator.
  char tmp[stringSize];//grabs word by word (chars serperated by whitespace).
  in >> tmp;
  rhs = String(tmp);
  return in;
}
////////////////////////////////string class public functions///////////////////////
////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////constructors///////////////////////////////////////
String::String(){//default constructor. default size
  arr = new char[stringSize];
  cap = stringSize;
  arr[0] = 0;
}
String::String(const char a){//char constructor. default size
  arr = new char[stringSize];
  cap = stringSize;
  arr[0] = a;
  arr[1] = 0;
}
String::String(const char a[]){//char array constructor. default size
  arr = new char[stringSize];
  cap = stringSize;
  int i = 0;
  while (a[i] > 0){
    arr[i] = a[i];
    ++i;
  }
  arr[i] = 0;
}
String::String(const int initSize, const char a[]){//char array constructor. size passed as a parameter
  arr = new char[initSize];
  cap = initSize;
  int i = 0;
  while (a[i] > 0){
    arr[i] = a[i];
    ++i;
  }
  arr[i] = 0;
}
String::String(int initSize){//like default constructor. size passed as parameter
  arr = new char[initSize];
  cap = initSize;
}
//////////////////////////////////dynamic stuff/////////////////////////////////////////////////
String::String(const String& rhs){//big three. copy constructor
  arr = new char[rhs.cap];
  cap = rhs.cap;
  for (int i = 0; i < cap; ++i)
    arr[i] = rhs.arr[i];
}
String::~String(){//big three. destuctor.
  delete [] arr;
}
String& String::operator=(String rhs){//big three. assignment operator.
  swap(rhs);
  return *this;
}
String String::swap(String& rhs){//swap the pointers on 2 char arrays.
  int tmpCap = rhs.cap;
  rhs.cap = cap;
  cap = tmpCap;
  char* tmp = rhs.arr;
  rhs.arr = arr;
  arr = tmp;
  return *this;
}

///////////////////////////////////functions////////////////////////////////////////////////////////////////
void String::reallocate(int a){//changes the size of a dynamic String. size passed as parameter.
  String tmp;
  tmp.cap = a;
  tmp.arr = new char[a];//allocate space of size passed.
  int i = 0;
  while (arr[i] != 0){//copy elements to newly allocated tmp array
    tmp.arr[i] = arr[i];
    ++i;
  }
  tmp.arr[i] = 0;
  swap(tmp);//swap pointers of tmp and passed array
}
std::vector<String> String::split(char splitter) const{//splits a String into a vecotr of
  std::vector<String> vecOfStrings;//Strings besed on the delimited passed
  int start = 0, end = 0;//returns that vector
  bool doIt = false;
  for (int i = 0; i < cap; ++i){//look if the delimiter exists
    if (arr[i] == ' '){
      doIt = true;
      break;
    }
  }
  if (doIt){//if the delimiter exists in the string start looping
    for (int i = 0; i < cap; ++i){
      if (arr[i] == splitter){//when each occurance of the delimiter is found create a
    end = i;//node of String in the vector with the chars since the previous node
    vecOfStrings.push_back(substr(start, end - 1));
    start = (end + 1);
      }
      if (i == (cap - 1)){//do this until the no more delimiters are found
    end = i;
    vecOfStrings.push_back(substr(start, end));
      }
    }
  }
  return vecOfStrings;
}
int String::length() const{//returns the length of the String before the terminating char.
  int counter = 0;
  while (arr[counter] != 0)
    ++counter;
  return counter;
}
int String::capacity() const{//accessor to capacity.
  return cap;
}
String String::substr(int start, int end) const{//returns a subset string of string passed.
  if ((start < 0) || (end < 0))//parameters are starting and ending points of the substring
    return String();
  String result;
  int returnIndex = start;
  for (int i = start; i <= end; ++i)
    result[i - start] = arr[returnIndex++];
  result[end - start + 1] = 0;
  return result;
}
int String::findChar(const char target) const{//returns the position of the first occurance of the char
  for (int i = 0; i < length(); ++i)//being searched for. returns -1 if the char is not found.
    if (arr[i] == target)
      return i;
  std::cout << "The char was not found." << std::endl;
  return -1;
}
int String::findStr(const char target[]) const{//searches for a substring in the string. returns the
  String targetString(target);//position of the first char in the substring
  return findStr(targetString);//uses the String version of findStr. look there for more info.
}
int String::findStr(const String& target) const{//searches for a substring in the string. returns the
  int targetLength = target.length();//position of the first char in the substring
  String candidate;//candidate is the string that
  int candStart = 0, candEnd = candStart + (targetLength - 1), i = 0;//will be compared to other strings
  //of the same length
  while (i < (stringSize - targetLength)){//go through char by char and compare candidate to
    candidate = substr(candStart++, candEnd++);//strings of the same length within the full string.
    if (candidate == target)//ex String = "Hello World." looking for "llo"
      return i;//"Hel" == "llo" no "Hel" == "ell" no "llo == "llo" yes.
    i++;//return 2.
  }
  std::cout << "The string was not found." << std::endl;
  return -1;//if not found at all return -1
}
int String::stringToInt(){
  int result = 0, intTmp;
  char charTmp;
  for (int i = 0; i < length(); ++i){
    charTmp = arr[i];
    switch (charTmp){
    case '0' : intTmp = 0; break;
    case '1' : intTmp = 1; break;
    case '2' : intTmp = 2; break;
    case '3' : intTmp = 3; break;
    case '4' : intTmp = 4; break;
    case '5' : intTmp = 5; break;
    case '6' : intTmp = 6; break;
    case '7' : intTmp = 7; break;
    case '8' : intTmp = 8; break;
    case '9' : intTmp = 9; break;
    case '-' : intTmp = 0; break;
    }
    if (result > 0)
      result = result * 10;
    result = result + intTmp;
  }
  return result;
}

/////////////////////////////////////////////operators////////////////////////////////////////////////////////////////////
char String::operator[](int i) const{//subscript operator. returns char whated in char array. const version.
  return arr[i];//acts as an accessor to chars
}
char& String::operator[](int i){//subscript operator. returns char whated in char array. non const version.
  return arr[i];//acts as an accessor to chars
}
String String::operator+(const String& rhs) const{//concatenate
  String result(arr);
  int start = length(), rhsIndex = 0;
  while (rhs.arr[rhsIndex] != 0){
    result.arr[start] = rhs.arr[rhsIndex];
    start++;
    rhsIndex++;
  }
  result.arr[start] = 0;
  return result;
}
bool String::operator==(const String& rhs) const{
  if (length() != rhs.length())
    return false;
  for (int i = 0; i < length(); ++i)
    if (arr[i] != rhs.arr[i])
      return false;
  return true;
}
bool String::operator!=(const String& rhs) const{
  if (*this == rhs)
    return false;
  return true;
}

bool String::operator<(const String& rhs) const{
  int i = 0;
  while (arr[i] != 0 && rhs.arr[i] != 0){
    if ((arr[i] - rhs.arr[i]) < 0)
      return true;
    else if ((arr[i] - rhs.arr[i]) > 0)
      return false;
    i++;
  }
  if (length() < rhs.length())
    return true;
  return false;
}
bool String::operator>(const String& rhs) const{
  if (*this == rhs)
    return false;
  if (*this < rhs)
    return false;
  return true;
}
bool String::operator<=(const String& rhs) const{
  if (*this == rhs)
    return true;
  if (*this < rhs)
    return true;
  return false;
}
bool String::operator>=(const String& rhs) const{
  if (*this == rhs)
    return true;
  if (*this < rhs)
    return false;
  return true;
}

//////////////////////////////free functions////////////////////////////////
////////////////////////////////////////////////////////////////////////////
///////////////they use the public functions of the String class////////////
String operator+(const char lhs[], const String& rhs){
  String lhsString(lhs);
  String result = lhsString + rhs;
  return result;
}
String operator+(const char lhs, const String& rhs){
  String lhsString(lhs);
  String result = lhsString + rhs;
  return result;
}
bool operator==(const char lhs[], const String& rhs){
  String lhsString(lhs);
  return lhsString == rhs;
}
bool operator==(const char lhs, const String& rhs){
  String lhsString(lhs);
  return lhsString == rhs;
}
bool operator!=(const char lhs[], const String& rhs){
  String lhsString(lhs);
  return lhsString != rhs;
}
bool operator!=(const char lhs, const String& rhs){
  String lhsString(lhs);
  return lhsString != rhs;
}
bool operator<(const char lhs[], const String& rhs){
  String lhsString(lhs);
  return lhsString < rhs;
}
bool operator<(const char lhs, const String& rhs){
  String lhsString(lhs);
  return lhsString < rhs;
}
bool operator>(const char lhs[], const String& rhs){
  String lhsString(lhs);
  return lhsString > rhs;
}
bool operator>(const char lhs, const String& rhs){
  String lhsString(lhs);
  return lhsString > rhs;
}
bool operator<=(const char lhs[], const String& rhs){
  String lhsString(lhs);
  return lhsString <= rhs;
}
bool operator<=(const char lhs, const String& rhs){
  String lhsString(lhs);
  return lhsString <= rhs;
}
bool operator>=(const char lhs[], const String& rhs){
  String lhsString(lhs);
  return lhsString >= rhs;
}
bool operator>=(const char lhs, const String& rhs){
  String lhsString(lhs);
  return lhsString >= rhs;
}

我在代码中添加了一些用于调试目的。6永远不会出现。

String postfix(String infix){
  std::vector<String> vec;
  vec = infix.split(' ');
  Stack<String> tmp;
  String right, left, op;

  int i = 0;
  while (vec[i] != ';'){
    std::cout << 1 << std::endl;
    if (vec[i] == ')'){
      right = tmp.pop();
      op = tmp.pop();
      left = tmp.pop();
      std::cout << 2 << std::endl;
      tmp.push(left + ' ' + right + ' ' + op);
      std::cout << 3 << std::endl;
    }else{
      if (vec[i] != '(' && vec[i] != ' ')
        std::cout << 4 << std::endl;
        tmp.push(vec[i]);
        std::cout << 5 << std::endl;
    }
    ++i;
  }

  std::cout << 6 << std::endl;
  String postfix = tmp.pop();
  return postfix;
}

输出是

-bash-4.1$ 进行测试 g++ -g -Wall -W -Wunused -Wuninitialized -Wshadow -iquote 。-iquote ../string -c test_data3.cpp g++ -g -Wall -W -Wunused -Wuninitialized -Wshadow string.o test_data3.o -o test_data3 ./test_intStack 一切看起来都不错。完成了一个 int Stack 的测试。./test_stringStack 一切看起来都不错。完成测试字符串堆栈。./test_data3 ( AX + ( B * C ) ) ; 1 5 1 4 5 1 4 5 1 5 1 4 5 1 4 5 1 4 5 1 2 3 1 2 3 1 4 5 制作:* [测试] 分段错误(核心转储)rm test_data3.o

4

1 回答 1

1

你几乎肯定想从隔离问题开始。

为此,我将首先进行一些重写,以使用您自己的代码进行后缀转换本身,但分别对字符串和堆栈类型使用std::stringand std::stack

如果这使问题消失,请切换一个(但不是两个)返回以使用您的课程。如果它仍然有效,请切换另一个以使用您的课程。

这很有可能会很快告诉您问题出在您的后缀转换、堆栈还是字符串中。一旦你弄清楚了这一点,我可能会为相关组件编写一些体面的单元测试。

可以改为在上下文中调试它,但是很有可能(至少根据我的经验)这样做通常会留下许多类似的问题,所以下次尝试使用它时,您会遇到类似的问题在略有不同的情况下。通过更系统地处理它,您可以消除整个类别的错误,而不是一次删除它们。

于 2013-11-11T05:24:01.623 回答