我自己的堆栈中的 C++ 奇怪行为 class
C++ Strange behavior in my own stack class
这是一个包含我的 Stack class 和一些其他功能的程序。
ReadTheFile()
- 读取存储在 num_file.txt
中的数字,以及 returns 包含这些数字的向量。
IntervalCheck()
- 添加来自输入向量的特定范围的数字和 returns 仅包含这些数字的向量。
VecToMyStack()
- 将向量中的数字添加到堆栈中。
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#define STACK_EMPTY -1
#define OUT_OF_STACK -2
using namespace std;
template <class T>
class Stack {
private:
struct Node{
T element;
Node *prevElement;
};
size_t NumberOfElements;
Node *tempAdr;
Node *topElement;
Node *newElement;
Node *erasedElement;
public:
Stack(){
topElement = new Node;
topElement->prevElement = nullptr;
NumberOfElements = 0;
}
~Stack(){
cout << endl << "I'm a destructor";
while(NumberOfElements !=0 ){
tempAdr = topElement->prevElement;
delete topElement;
topElement = tempAdr;
NumberOfElements--;
}
delete topElement;
}
void push(T input_element){
tempAdr = topElement;
topElement = new Node;
topElement->element = input_element;
topElement->prevElement = tempAdr;
NumberOfElements++;
}
void pop(){
if (NumberOfElements == 0) throw STACK_EMPTY;
else {
tempAdr = topElement->prevElement;
delete topElement;
topElement = tempAdr;
NumberOfElements--;
}
}
T top(){
return NumberOfElements != 0 ? topElement->element : throw STACK_EMPTY;
}
void insert(size_t position, T input_element){
if (position >= NumberOfElements) throw OUT_OF_STACK;
else {
tempAdr = topElement;
for (size_t i = 0; i < position; i++){
tempAdr = tempAdr->prevElement;
}
newElement = new Node;
newElement->element = input_element;
newElement->prevElement = tempAdr->prevElement;
tempAdr->prevElement = newElement;
NumberOfElements++;
}
}
void erase(size_t position){
if (position >= (NumberOfElements-1)) throw OUT_OF_STACK;
else{
tempAdr = topElement;
for (size_t i = 0; i < position; i++){
tempAdr = tempAdr->prevElement;
}
erasedElement = tempAdr->prevElement;
tempAdr->prevElement = tempAdr->prevElement->prevElement;
delete erasedElement;
NumberOfElements--;
}
}
void print(){
if (NumberOfElements != 0){
tempAdr = topElement;
for (size_t i = 0; i < NumberOfElements; i++){
cout << tempAdr->element << " ";
tempAdr = tempAdr->prevElement;
}
}
}
size_t size() { return NumberOfElements; }
};
vector<int> ReadTheFile() {
vector<int> vec_from_file;
int buffer;
ifstream basefile;
basefile.open("num_file.txt", ios::in);
if (basefile.is_open()) {
do {
if (basefile >> buffer)
vec_from_file.push_back(buffer);
else {
basefile.clear();
basefile.ignore(1, ' ');
}
} while (!basefile.eof());
basefile.close();
}
else cout << "Unable to open file" << endl;
return vec_from_file;
}
vector<int> IntervalCheck(vector<int> vec_for_check){
vector<int> out_vec;
if (vec_for_check.empty()) cout << "There is nothing to check";
else {
int begin_int, end_int;
do {
cin.clear();
cin.sync();
cout << "Input the first and the last value of the interval: ";
cin >> begin_int >> end_int;
} while (cin.fail());
for (auto &k : vec_for_check)
if (k > begin_int && k < end_int)
out_vec.push_back(k);
}
return out_vec;
}
Stack<int> VecToMyStack(vector<int> input_vec){
Stack<int> output_st;
if (input_vec.empty()) {
cout << "the end";
}
else {
for (auto &k : input_vec){
output_st.push(k);
}
}
return output_st;
}
int main(){
int choice = 0;
do {
cin.clear();
cin.sync();
VecToMyStack(IntervalCheck(ReadTheFile())).print();
cout << "Would you like to measure another interval? 1-yes 2-no";
cin >> choice;
} while (choice == 1);
system("pause");
return 0;
}
整个程序应将文件中的数字压入堆栈,并使用 class 的 print()
方法打印该堆栈。例如,如果 num_file.txt
和
0 1 2 3 4 5 6 7 8 9 10
在内部,程序应该以这种方式工作:
- 输入区间的第一个和最后一个值:0 10 /* 零和
用户输入十个*/
- 1 2 3 4 5 6 7 8 9
- 你想测量另一个区间吗? 1-是 2-否
但是当 VecToMyStack(IntervalCheck(ReadTheFile())).print();
行被执行时,我得到
Access violation reading location 0xFEEEFEEE.
异常。我的 Stack class 的析构函数似乎在 print()
函数之前是 运行。为什么会这样?有什么特别的东西我应该添加到我的 Stack class 或 VecToMyStack()
函数中吗?
最后,经过几个小时的研究,我得到了代码所缺少的平静:
Stack(const Stack &object){
tempAdr = object.topElement;
T * tempMas=new T[object.NumberOfElements];
for (size_t i = 0; i < object.NumberOfElements; i++){
tempMas[i] = tempAdr->element;
tempAdr = tempAdr->prevElement;
}
topElement = new Node;
topElement->prevElement = nullptr;
NumberOfElements = 0;
for (int i = object.NumberOfElements - 1; i >= 0; i--){
push(tempMas[i]);
}
delete[] tempMas;
}
我知道如果没有重载赋值运算符,我的 Stack class 仍然不完整,但至少我的代码运行良好。
这是一个包含我的 Stack class 和一些其他功能的程序。
ReadTheFile()
- 读取存储在num_file.txt
中的数字,以及 returns 包含这些数字的向量。IntervalCheck()
- 添加来自输入向量的特定范围的数字和 returns 仅包含这些数字的向量。VecToMyStack()
- 将向量中的数字添加到堆栈中。#include <iostream> #include <string> #include <vector> #include <fstream> #define STACK_EMPTY -1 #define OUT_OF_STACK -2 using namespace std; template <class T> class Stack { private: struct Node{ T element; Node *prevElement; }; size_t NumberOfElements; Node *tempAdr; Node *topElement; Node *newElement; Node *erasedElement; public: Stack(){ topElement = new Node; topElement->prevElement = nullptr; NumberOfElements = 0; } ~Stack(){ cout << endl << "I'm a destructor"; while(NumberOfElements !=0 ){ tempAdr = topElement->prevElement; delete topElement; topElement = tempAdr; NumberOfElements--; } delete topElement; } void push(T input_element){ tempAdr = topElement; topElement = new Node; topElement->element = input_element; topElement->prevElement = tempAdr; NumberOfElements++; } void pop(){ if (NumberOfElements == 0) throw STACK_EMPTY; else { tempAdr = topElement->prevElement; delete topElement; topElement = tempAdr; NumberOfElements--; } } T top(){ return NumberOfElements != 0 ? topElement->element : throw STACK_EMPTY; } void insert(size_t position, T input_element){ if (position >= NumberOfElements) throw OUT_OF_STACK; else { tempAdr = topElement; for (size_t i = 0; i < position; i++){ tempAdr = tempAdr->prevElement; } newElement = new Node; newElement->element = input_element; newElement->prevElement = tempAdr->prevElement; tempAdr->prevElement = newElement; NumberOfElements++; } } void erase(size_t position){ if (position >= (NumberOfElements-1)) throw OUT_OF_STACK; else{ tempAdr = topElement; for (size_t i = 0; i < position; i++){ tempAdr = tempAdr->prevElement; } erasedElement = tempAdr->prevElement; tempAdr->prevElement = tempAdr->prevElement->prevElement; delete erasedElement; NumberOfElements--; } } void print(){ if (NumberOfElements != 0){ tempAdr = topElement; for (size_t i = 0; i < NumberOfElements; i++){ cout << tempAdr->element << " "; tempAdr = tempAdr->prevElement; } } } size_t size() { return NumberOfElements; } }; vector<int> ReadTheFile() { vector<int> vec_from_file; int buffer; ifstream basefile; basefile.open("num_file.txt", ios::in); if (basefile.is_open()) { do { if (basefile >> buffer) vec_from_file.push_back(buffer); else { basefile.clear(); basefile.ignore(1, ' '); } } while (!basefile.eof()); basefile.close(); } else cout << "Unable to open file" << endl; return vec_from_file; } vector<int> IntervalCheck(vector<int> vec_for_check){ vector<int> out_vec; if (vec_for_check.empty()) cout << "There is nothing to check"; else { int begin_int, end_int; do { cin.clear(); cin.sync(); cout << "Input the first and the last value of the interval: "; cin >> begin_int >> end_int; } while (cin.fail()); for (auto &k : vec_for_check) if (k > begin_int && k < end_int) out_vec.push_back(k); } return out_vec; } Stack<int> VecToMyStack(vector<int> input_vec){ Stack<int> output_st; if (input_vec.empty()) { cout << "the end"; } else { for (auto &k : input_vec){ output_st.push(k); } } return output_st; } int main(){ int choice = 0; do { cin.clear(); cin.sync(); VecToMyStack(IntervalCheck(ReadTheFile())).print(); cout << "Would you like to measure another interval? 1-yes 2-no"; cin >> choice; } while (choice == 1); system("pause"); return 0; }
整个程序应将文件中的数字压入堆栈,并使用 class 的 print()
方法打印该堆栈。例如,如果 num_file.txt
和
0 1 2 3 4 5 6 7 8 9 10
在内部,程序应该以这种方式工作:
- 输入区间的第一个和最后一个值:0 10 /* 零和 用户输入十个*/
- 1 2 3 4 5 6 7 8 9
- 你想测量另一个区间吗? 1-是 2-否
但是当 VecToMyStack(IntervalCheck(ReadTheFile())).print();
行被执行时,我得到
Access violation reading location 0xFEEEFEEE.
异常。我的 Stack class 的析构函数似乎在 print()
函数之前是 运行。为什么会这样?有什么特别的东西我应该添加到我的 Stack class 或 VecToMyStack()
函数中吗?
最后,经过几个小时的研究,我得到了代码所缺少的平静:
Stack(const Stack &object){
tempAdr = object.topElement;
T * tempMas=new T[object.NumberOfElements];
for (size_t i = 0; i < object.NumberOfElements; i++){
tempMas[i] = tempAdr->element;
tempAdr = tempAdr->prevElement;
}
topElement = new Node;
topElement->prevElement = nullptr;
NumberOfElements = 0;
for (int i = object.NumberOfElements - 1; i >= 0; i--){
push(tempMas[i]);
}
delete[] tempMas;
}
我知道如果没有重载赋值运算符,我的 Stack class 仍然不完整,但至少我的代码运行良好。