【问题标题】:The pop function in my Stack return strange characters - C++我的堆栈中的 pop 函数返回奇怪的字符 - C++
【发布时间】:2015-10-08 12:22:57
【问题描述】:

我在 C++ 中的 Stack 和 String 函数存在严重问题。 我已经对我的字符串进行了编码并且可以正常工作,但现在我不知道该怎么做。我的 Stack 也是,我已经将 Stack 类与整数一起使用,但是当我尝试与我的 String(ADT) 一起使用时不起作用。

堆栈.hpp:

// Stack.hpp

#ifndef CS2_STACK_CPP
#define CS2_STACK_CPP

#include <iostream>

template<class T>
class node{
public:
    T nodeValue;
    node<T> *next;
    node(): next(NULL){};
    node(const T& item):nodeValue(item){};
};

template<class T>
class Stack{
public:
    node<T> *TOS;
    Stack(): TOS(NULL){};
    Stack(const Stack<T>&);
    ~Stack();
    void push(const T&);
    T pop();
    Stack<T>& operator=(const Stack<T>&);
    void cpList(const Stack<T>& S);
};

template<class T>
Stack<T>::Stack(const Stack<T> &S){
    node<T> *curr = S.TOS, *back;
    if(curr == NULL){
        TOS = NULL;
    }else{
        curr = curr -> next;
        TOS = new node<T>(S.TOS -> nodeValue);
        back = TOS;
        while(curr != NULL){
            back -> next = new node<T>(curr -> nodeValue);
            back = back -> next;
            curr = curr -> next;
        }
    }
}

template<class T>
Stack<T>::~Stack(){
    node<T> *curr, *pnext;
    curr = TOS;
    while(curr != NULL){
        pnext = curr -> next;
        delete curr;
        curr = pnext;
    }
    delete TOS;
}

template<class T>
void Stack<T>::push(const T &item){
    node<T> *p;
    p = new node<T>(item);
    if (TOS != NULL) {
        p -> next = TOS;
        TOS = p;
    } else {
        TOS = p;
    }
}

template<class T>
T Stack<T>::pop(){
    node<T> *p;
    T item;
    if(TOS != NULL){
        item = TOS -> nodeValue;
        p = TOS;
        TOS = TOS -> next;
        return p -> nodeValue;
        delete p;
    } else {
        std::cout << "Empty stack!" << std::endl;
    }
}

template<class T>
Stack<T>& Stack<T>::operator=(const Stack<T>& S){

    if(this == &S){
        return *this;
    }

    node<T> *curr, *pnext, *nNode, *last = NULL;
    curr = TOS;
    while(curr != NULL){
        pnext = curr -> next;
        delete curr;
        curr = pnext;
    }

    cpList(S);
    return *this;
}

template <class T>
void Stack<T>::cpList(const Stack<T>& S){
    node<T> *ptr, *newNode, *last = NULL;

    ptr = S.TOS;

    while(ptr != NULL){
        newNode = new node<T>(ptr->nodeValue);
        if (last == NULL){
            TOS = newNode;
        }else{
            last->next = newNode;
        }
        last = newNode;
        ptr = ptr -> next;
    }

}

#endif

字符串.hpp:

// String.hpp

#ifndef CS2_STRING_H
#define CS2_STRING_H

#include <iostream>

const int SIZE = 256;

class String
{
public:
    // Constructor method without value
    String();

    // Constructor method receiving a char array
    String(const char*);

    // Constructor method receiving a char array
    String(const char);

    // Constructor method receiving a size and a char
    // Precondition: The size need to be equal or greater
    // than the size of the char
    // Postcondition: Create a String with a end character '\0'
    String(int,const char*);

    // Constructor method just receiving a size
    // Precondition: Size need to be equal or greater than 0
    // Postcondition: Generate a String with that capacity and
    // with just a end character '/0' at the position 0
    String(int);

    // Copy constructor
    String(const String&);

    // Destructor method for String class
    ~String();

    void resize(int); 

    // Return the actual capacity of the String
    int getCapacity()const;

    // Precondition: A valid String or char[]
    // Postcondition: Return and integer with the length
    int length()const;

    // Precondition: Insert a positive integer
    // Post condition: Return a char in that position
    char getChar(int)const;

    // Precondition: Insert a positive integer
    // Postcondition: Return a char in that position
    char operator[](int)const;

    // Precondition: 
    // Postcondition: 
    void swap(String&);

    // Precondition: Insert and positive value initial, less than
    // SIZE and a positive value for the end less than SIZE
    // Postcondition: Return a String inside this interval 
    // (initial to end)
    String substring(int,int)const;

    // Precondition: Insert a valid char
    // Postcondition: Return the integer with the position of the
    // char, if don't return 0
    int findchar(char)const;

    // Precondition: Insert a valid String
    // Postcondition: Return and integer with the position that
    // start that String, if don't return 0
    int findstring(String)const;

    String& operator=(const String&);

    // Precondition: 2 valid strings (LHS + RHS)
    // Postcondition: Return a String with that 2 values
    // concatenated
    String operator+(String)const;

    // Precondition: 2 valid strings (LHS and RHS)
    // Postcondition: return a boolean that say if this
    // 2 strings are equal
    bool operator==(String)const;

    // Precondition: 2 valid strings (LHS and RHS)
    // Postcondition: return a negation of the operator==
    bool operator!=(String)const;

    // Precondition: Receive 2 values (LHS and RHS)
    // Postcondition: Return a boolean that say if the
    // LHS is less than RHS using the lexicographical order
    bool operator<(String)const;

    // Precondition: Receive 2 values (LHS and RHS)
    // Postcondition: Return a negation of the operator<
    bool operator>(String)const;

    // Precondition: Receive 2 values (LHS and RHS)
    // Postcondition: Return a boolean that say if the
    // LHS is less or equal to RHS using the lexicographical
    // order
    bool operator<=(String)const;

    // Precondition: Receive 2 values (LHS and RHS)
    // Postcondition: Return a boolean that say if the
    // LHS is greater or equal to RHS using the lexicographical
    // order
    bool operator>=(String)const;

    // Precondition: LHS be a String and LRS be a String too
    // Postcondition: Return inside LHS the concatenation
    // of LHS and RHS
    String& operator+=(const String&);

    // Overload of the C++ output method
    friend std::ostream& operator<<(std::ostream&, const String&);
private:

    char *value;
    int  capacity;

};


#endif // CS2_STRING_H

字符串.cpp:

// String.cpp

#include "String.hpp"
#include <cstring>

//CONSTRUCTORS
String::String(){

    capacity = SIZE;

    value = new char[capacity];
    value[0] = '\0';

}

String::String(const char *ch){

    capacity = SIZE;

    int i =0;
    while(ch[i] != '\0'){
        i++;
    }

    value = new char[capacity];

    i=0;

    while(ch[i] != '\0'){
        value[i] = ch[i];
        i++;
    }

    value[i] = '\0';

}

String::String(const char ch){

    capacity = SIZE;

    value = new char[2];
    value[0] = ch;
    value[1] = '\0';
}

String::String(int tsize, const char *ch){
    int i =0;
    while(ch[i] != '\0'){
        i++;
    }
    if(tsize>=i){
        value = new char[capacity];
        i=0;
        while(ch[i] != '\0'){
            value[i] = ch[i];
            i++;
        }
        value[i] ='\0';
    }else{
        std::cout << "Error in the initialization, please the size need to be bigger." << std::endl;
    }
}

String::String(int tsize){
    if(tsize>=0){
        capacity = tsize;
        value = new char[capacity];
        value[0] = '\0';
    }
}

String::String(const String& rhs){
    int i = 0;
    capacity = rhs.capacity;
    value = new char[capacity];
    while(rhs[i] != '\0'){
        value[i] = rhs[i];
        i++;
    }
    value[i]='\0';
}

String::~String(){
    delete[] value;
}

void String::resize(int tsize){
    char *temp = value;
    capacity = tsize;
    value = new char[capacity];
    int i = 0;
    while(temp[i] != '\0'){
        value[i] = temp[i];
        i++;
    }
    value[i] = '\0';
    delete temp;
}

int String::getCapacity()const{
    return capacity;
}

int String::length()const{
    int i = 0;
    while(value[i]!='\0'){
        i++;
    }
    return i;
}

char String::getChar(int position)const{
    if(position>=0){
        return value[position];
    }
}

char String::operator[](int position)const{
    if(position>=0){
        return value[position];
    }
}

void  String::swap(String& rhs){
    int tempc = capacity;
    capacity = rhs.getCapacity();
    rhs.capacity = tempc;

    char *tempStr = value;
    value = rhs.value;
    rhs.value = tempStr;
}

String String::substring(int initial, int end)const{
    char newChar[256];
    int aux = 0;
    if(( ((initial >= 0) && (initial <= end)) ) && ( ((end > 0) && (end < SIZE)) ) ){
        for(int i = initial;i <= end;i++){
            newChar[aux]=value[i];
            aux++;
        }
    }
    String treturn(newChar);
    return treturn;
}

int String::findchar(char rhs)const{
    int x = 0;
    for(int i = 0;i < SIZE;i++){
        if( value[i] == rhs ){
            x = (i + 1);
            break;
        }
    }
    return x;
}

int String::findstring(String rhs)const{
    int x = 0, aux = 0;
    int lhssize = length();
    int rhssize = rhs.length();
    while(value[x]!='\0'){
        if(value[x]==rhs[aux]){
            aux++;
            if(aux==rhssize){
                return ( (x + 1) - rhssize);
            }
        }else{
            aux = 0;
        }
        x++;
    }
    return 0 ;
}

String& String::operator=(const String& str){
    int i = 0;
    while(str[i]!='\0'){
        value[i] = str[i];
        i++;
    }
    return *this;
}

String String::operator+(String rhs)const{

    char newChar[SIZE];
    int aux = 0;

    int max = this->length() + rhs.length();

    for(int i = 0; i < this->length(); i++){
        newChar[aux] = this -> getChar(i);
        aux++;
    }

    for(int i = 0; i < rhs.length(); i++){
        newChar[aux]=rhs.getChar(i);
        aux++;
    }

    String newString(newChar);

    return newString;

}

// OK
bool String::operator==(String rhs)const{
    int i=0;
    while(value[i] != '\0'){
        if(value[i] != rhs.value[i]){
            return false;
            i++;
        }
    }
    return value[i]==rhs.value[i];
}

bool String::operator!=(String rhs)const{
    String test(value);
    return !(test==rhs);
}

bool String::operator<(String rhs)const{
    int i =0;
    while( (value[i]!='\0') && (value[i] == rhs.value[i]) ){    
        i++;
    }
    return value[i] < rhs.value[i];
}

bool String::operator>(String rhs)const{

    String test(value);

    return !(test<rhs);
}

bool String::operator<=(String rhs)const{

    int i =0;

    while( (value[i] != '\0') && ( value[i] == rhs[i] ) ){
        i++;
    }

    return value[i] <= rhs[i];
}

bool String::operator>=(String rhs)const{

    int i =0;

    while( (value[i] != '\0') && (value[i] == rhs[i]) ){
        i++;
    }

    return value[i] >= rhs[i];

}

String& String::operator+=(const String& rhs){

    int offset = length();
    int i = 0;

    while(rhs[i] != '\0'){
        value[i+offset] = rhs[i];
        i++;
    }
    value[i+offset] = '\0';

    return *this;
}

std::ostream& operator<<(std::ostream& out,const String& rhs){

    int i=0;

    while(rhs[i] != '\0'){
        out << rhs[i];
        i++;
    }

    return out;
}

还有 InfixToPostfix.cpp:

#include "../String.cpp"
#include "../Stack.hpp"

int main(){
    Stack<String> S;
    String result, right, left, oper;
    String elements("((A+B)*C)");
    int i;
    for(i=0;i<elements.length();i++){
        char t = elements[i];
        if(t == ')'){
            right = S.pop();
            oper = S.pop();
            left = S.pop();
            S.push(left + right + oper);
        }else if(t != '('){
            S.push(t);
        }
    }
    return 0;
    result = S.pop();
    std::cout << result << std::endl;
}

// AB+C*

我真的不知道这是否是寻求帮助的好方法,但我不知道该怎么办了。我正在使用带有 UTF-8 的 Sublime Text 进行编码,并使用我大学的 unix 服务器进行编译。谢谢各位。

【问题讨论】:

  • 请发布出现问题的最小可编译代码。
  • 如果与std::string 一起使用,它是否按预期工作?如果是问题出在 String 类上,否则问题出在堆栈或您的代码上。
  • 您通过调用您的链表实现堆栈使我们感到困惑。在 push 函数中,您不会为第一个被推送的元素设置 next 指针。在pop 函数中,return 不能放在delete 之前。我确信编译器必须警告你——听听警告!
  • 寻求帮助的一个好方法是详细描述您所说的“严重问题”是什么意思。第二个建议是:在调试器中运行它,看看它一步一步做了什么。也许,您可以通过这种方式自己查明问题。学习使用调试器是您职业生涯中的一大步,您应该尽快完成。
  • 我正在尝试学习如何调试,在 Windows 环境中调试的最佳 IDE 是什么?这是我第一次接触 C++。我只是在我的 Sublime IDE 中编码并上传到 Linux 机器中的 FTP 服务器,以使用 SSH 编译我的文件。谢谢你的回答。

标签: c++ string stack infix-notation


【解决方案1】:

在代码中查看我的 cmets。这是在您的代码中打印出垃圾的罪魁祸首:

String& String::operator=(const String& str){
  int i = 0;
  while(str[i]!='\0'){
    value[i] = str[i];
    i++;
  }
  value[i] = '\0'; // <- You must still set the string terminator
  // or else garbage characters will be read until a null terminator is reached
  return *this;                                                                                                                                                
}

我必须指出的一件事是,您在销毁对象的方式上存在一些问题。例如;

template<class T>
Stack<T>::~Stack(){
  node<T> *curr, *pnext;
  curr = TOS;
  while(curr != NULL){
    pnext = curr -> next;
    delete curr;
    curr = pnext;
  }
  // delete TOS; // You already deleted the root node! This will result in segfault/double free                                                                                                                                             
}

最后,您必须修复这部分代码:

template<class T>
T Stack<T>::pop(){
  using namespace std;
  node<T> *p;
  T item;
  if(TOS != NULL){
    item = TOS -> nodeValue;
    p = TOS;
    TOS = TOS -> next;
    //    return p -> nodeValue; // How can you delete the node if you are already returning in this line?                                                                                                                              
    delete p;
  } else {
    std::cout << "Empty stack!" << std::endl;
  }

  return item; // Your function needs to return a proper value in both cases above
}

【讨论】:

  • 我实现了您所说的,但一直收到错误消息:分段错误(核心转储)。在了解了有关调试的基本知识(我正在培训和学习,这是我第一次接触 C++ 人员)之后,它说错误出在析构函数中,当我尝试在 pnext 中分配 curr -> next 的值时,因为在最后一种情况,当 curr = 最后一个位置时,我们没有下一个指针。如何处理?谢谢你的评论。最好的问候。
  • 如果curr-&gt;nextnull,那么在while 循环中的迭代之后,curr 本身就是null。因此循环将停止评估。我实际上已经测试了代码,老实说,我认为除非您再次更改其他内容,否则不会再出现段错误。
猜你喜欢
  • 2016-10-24
  • 1970-01-01
  • 2014-08-11
  • 1970-01-01
  • 2010-10-14
  • 2015-03-01
  • 2011-09-08
  • 2021-01-20
  • 2020-02-14
相关资源
最近更新 更多