我在函数operator ==上得到了SIGSEGV信号,但是我不知道为什么会这样。调试器显示其中一个参数没有其成员的值,但是有一个默认的构造函数结构。
我收到的信号是 bool operator ==(const Pos&p,const Pos&d)
这是完整的文件。
#include <iostream>
#include <vector>
#include <map>
using namespace std;
int sgn(int x)
{
return (x>0) - (x<0);
}
struct Pos
{
int xpos;
int ypos;
Pos()
:xpos{ 0 }, ypos{ 0 }
{}
Pos(int xp, int yp)
:xpos(xp), ypos(yp)
{}
Pos(const Pos& p)
:xpos(p.xpos), ypos(p.ypos)
{}
Pos& operator=(const Pos&);
bool operator<(const Pos&) const;
};
---->bool operator==(const Pos& p, const Pos& d)<----
{
return p.ypos == d.ypos && p.xpos == d.xpos;
}
bool Pos::operator<(const Pos& p)const
{
return xpos < p.xpos && ypos < p.ypos;
}
Pos& Pos::operator=(const Pos& P)
{
xpos = P.xpos;
ypos = P.ypos;
return *this;
}
class Figure
{
public:
Figure()
:pos(0, 0), is_protected(false), color(' ')
{}
Figure(const Pos&, char);
virtual void fix_move_zone();
bool is_protected;
char color;
Pos pos;
vector<Pos> move_zone;
};
Figure::Figure(const Pos& A, char C)
:pos(A), color(C), is_protected(false)
{}
void Figure::fix_move_zone()
{
return;
}
////////////////////// Global Variables ///////////////////////////
map<Pos, Figure> G_Field; //
bool G_black_king_UA = false; // flag to know if black king is under attack
///////////////////////////////////////////////////////////////////
bool is_valid_move(Pos v)
{
return (v.xpos)>0 && (v.ypos)>0;
}
istream& operator>>(istream& is, Pos p)
{
char c;
is >> c >> p.ypos;
p.xpos = c - 'A' + 1;
if (!is_valid_move(p) || G_Field.find(p) != G_Field.end()) cerr << "ERROR: Either there is no such position or it is taken";
return is;
}
class King : public Figure
{
public:
void fix_move_zone();
King(Pos, char);
};
King::King(Pos p, char c) : Figure(p, c)
{
G_Field[pos] = Figure(pos, color);
for (int i = -1; i<2; i++)
{
for (int j = -1; j<2; j++)
{
if (is_valid_move(Pos(pos.xpos + i, pos.ypos + j))) move_zone.push_back(Pos(pos.xpos + i, pos.ypos + j));
}
}
}
void King::fix_move_zone()
{
for (int i = 0; i<move_zone.size(); i++)
{
if (G_Field[move_zone[i]].color)
{
if (G_Field[move_zone[i]].is_protected)move_zone.erase(move_zone.begin() + i);
}
}
}
class Knight : public Figure
{
public:
void fix_move_zone();
Knight(Pos, char);
};
Knight::Knight(Pos p, char c)
: Figure(p, c)
{
G_Field[pos] = Figure(pos, color);
for (int i = -2; i<3; i++)
{
for (int j = -2; j<3; j++)
{
if (abs(i) + abs(j) == 3 && is_valid_move(Pos(pos.xpos + i, pos.ypos + j))) move_zone.push_back(Pos(pos.xpos + i, pos.ypos + j));
}
}
}
void Knight::fix_move_zone()
{
for (int i = 0; i<move_zone.size(); i++)
{
if (G_Field[move_zone[i]].color)
{
if (G_Field[move_zone[i]].color == color)G_Field[move_zone[i]].is_protected = true;
else G_black_king_UA = true;
}
}
}
class Bishop : public Figure
{
public:
void fix_move_zone();
Bishop(Pos, char);
};
Bishop::Bishop(Pos p, char c)
: Figure(p, c)
{
G_Field[pos] = Figure(pos, color);
for (int i = -7; i<8; i++)
{
for (int j = -7; j<8; j++)
{
if (abs(i) == abs(j) && is_valid_move(Pos(pos.xpos + i, pos.ypos + j))) move_zone.push_back(Pos(pos.xpos + i, pos.ypos + j));
}
}
}
void Bishop::fix_move_zone()
{
for (int i = 0; i<move_zone.size(); i++)
{
if (G_Field[move_zone[i]].color)
{
for (int j = 0; j<move_zone.size(); j++)
{
if (i == j)continue;
if (sgn((pos.xpos - move_zone[i].xpos)) == sgn((pos.xpos - move_zone[j].xpos)) && sgn(pos.ypos - move_zone[i].ypos) == sgn(pos.ypos - move_zone[j].ypos))
{
if (abs(pos.xpos - move_zone[j].xpos)>abs(pos.xpos - move_zone[i].xpos) || abs(pos.ypos - move_zone[j].ypos)>abs(pos.ypos - move_zone[i].ypos))
{
if (G_Field[move_zone[i]].color == color)G_Field[move_zone[i]].is_protected = true;
else G_black_king_UA = true;
move_zone.erase(move_zone.begin() + j);
}
}
}
}
}
}
class Queen : public Figure
{
public:
void fix_move_zone();
Queen(Pos, char);
};
Queen::Queen(Pos p, char c)
:Figure(p, c)
{
G_Field[pos] = Figure(pos, color);
for (int i = -7; i<8; i++)
{
if (is_valid_move(Pos(pos.xpos + i, pos.ypos)))
{
move_zone.push_back(Pos(pos.xpos + i, pos.ypos));
}
for (int j = -7; j<8; j++)
{
if (abs(i) == abs(j) && is_valid_move(Pos(pos.xpos + i, pos.ypos + j))) move_zone.push_back(Pos(pos.xpos + i, pos.ypos + j));
if (is_valid_move(Pos(pos.xpos, pos.ypos + j))) move_zone.push_back(Pos(pos.xpos, pos.ypos + j));
}
}
}
void Queen::fix_move_zone()
{
for (int i = 0; i<move_zone.size(); i++)
{
if (G_Field[move_zone[i]].color)
{
for (int j = 0; j<move_zone.size(); j++)
{
if (i == j)continue;
if (sgn((pos.xpos - move_zone[i].xpos)) == sgn((pos.xpos - move_zone[j].xpos)) && sgn(pos.ypos - move_zone[i].ypos) == sgn(pos.ypos - move_zone[j].ypos))
{
if (abs(pos.xpos - move_zone[j].xpos)>abs(pos.xpos - move_zone[i].xpos) || abs(pos.ypos - move_zone[j].ypos)>abs(pos.ypos - move_zone[i].ypos))
{
if (G_Field[move_zone[i]].color == color)G_Field[move_zone[i]].is_protected = true;
else G_black_king_UA = true;
move_zone.erase(move_zone.begin() + j);
}
}
}
}
}
}
int main()
{
Pos Wking;
Pos Wknight;
Pos WBishop;
Pos WQueen;
Pos BKing;
cout << "Please enter position of the figure in this format:ex. A 7 " << endl;
cout << "Black King: ";
cin >> BKing;
King BKI(BKing, 'b');
cout << "White King: ";
cin >> Wking;
King WKI(Wking, 'w');
cout << "White Knight: ";
cin >> Wknight;
Knight WKN(Wknight, 'w');
cout << "White Bishop: ";
cin >> WBishop;
Bishop WBI(WBishop, 'w');
cout << "White Queen: ";
cin >> WQueen;
Queen WQU(WQueen, 'w');
for (int i = 0; i<BKI.move_zone.size(); i++)
{
for (int j = 0; j<WQU.move_zone.size(); j++)
{
if (BKI.move_zone[i] == WQU.move_zone[j])
{
BKI.move_zone.erase(BKI.move_zone.begin() + i);
break;
}
}
for (int j = 0; j<WKN.move_zone.size(); j++)
{
if (BKI.move_zone[i] == WKN.move_zone[j])
{
BKI.move_zone.erase(BKI.move_zone.begin() + i);
break;
}
}
for (int j = 0; j<WBI.move_zone.size(); j++)
{
if (BKI.move_zone[i] == WBI.move_zone[j])
{
BKI.move_zone.erase(BKI.move_zone.begin() + i);
break;
}
}
for (int j = 0; j<WKI.move_zone.size(); j++)
{
if (BKI.move_zone[i] == WKI.move_zone[j])
{
BKI.move_zone.erase(BKI.move_zone.begin() + i);
break;
}
}
}
if (!BKI.move_zone.size() && G_black_king_UA) cout << "Checkmate!" << '\n';
else cout << "It is not a Checkmate!" << '\n';
return 0;
}
任何帮助将不胜感激。
答案 0 :(得分:0)
BKI.move_zone
为空,因为在循环中删除了BKI.move_zone
的元素。
检查下面。
for (int i = 0; i<BKI.move_zone.size(); i++)
{
for (int j = 0; j<WQU.move_zone.size(); j++)
{
if (BKI.move_zone[i] == WQU.move_zone[j])
{
BKI.move_zone.erase(BKI.move_zone.begin() + i); // BKI.move_zone is empty
break;
}
}
for (int j = 0; j<WKN.move_zone.size(); j++)
{
if (BKI.move_zone[i] == WKN.move_zone[j]) // BKI.move_zone[0] is not exist
{
BKI.move_zone.erase(BKI.move_zone.begin() + i);
break;
}
}
//...
}
BKI.move_zone[i] == WKN.move_zone[j]
与以下相同。
BKI.move_zone[i].operator==(WKN.move_zone[j])
因此,operator==()
的{{1}}无效。
在循环中擦除元素非常危险,因为这可能会影响“过去”数据。这将是不确定的行为。
感谢阅读。
答案 1 :(得分:0)
从BKI.move_zone
删除元素后,不能保证BKI.move_zone[i]
仍然有效。
我使用GDB(调试器)运行了您的代码,并为所有5个查询回答了A 7
。
在这种情况下。 BKI.move_zone.size()
最初是1。然后,在WQU
循环中删除了一个元素。结果,现在BKI.move_zone
有0个元素,在以后的循环中访问BKI.move_zone[i]
变得很危险。
即使BKI.move_zone[i]
在删除后仍然有效,您的代码也可能无法处理已删除元素之后的元素。
要解决此问题,您应该像这样更改循环
for (int j = 0; j<WQU.move_zone.size(); j++)
{
if (BKI.move_zone[i] == WQU.move_zone[j])
{
BKI.move_zone.erase(BKI.move_zone.begin() + i);
break;
}
}
喜欢这样
bool erased = false; // add declaretion at the beginning of BKI loop
for (int j = 0; j<WQU.move_zone.size(); j++)
{
if (BKI.move_zone[i] == WQU.move_zone[j])
{
BKI.move_zone.erase(BKI.move_zone.begin() + i);
erased = true; // flag that erasure happened
break;
}
}
if (erased) { // if erasure happened, rerun the loop
i--; // to cancel i++; in the BKI loop
continue; // rerun the loop
}
请注意,由于在删除操作发生时循环将重新运行,因此您无需在每个循环的开始时初始化erased
。