在编程时,一个函数功能单一化不仅仅只是有降低耦合性的好处,在避免一些很深或者很容易忽略的bug也很有帮助。请看下面的问题代码(原题是CCF2014年最优配餐问题,这个算法并不是正确的。算法 正确性并不是本文的重点):
#include <iostream>
#include<queue>
#include<vector>
using namespace std;
queue<pair<int, int> > q;
int n = 1000, m = 0, k = 0, d = 0;
int ans = 0;
struct Direction {
int x;
int y;
}Direction[4] = { (0,1),(0,-1),(1,0),(-1,0) };
bool NotOuside(int x, int y)
{
if (x >= 0 && x <= n - 1)
{
if (y >= 0 && y <= n - 1)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
void bfs()
{
}
int main()
{
cin >> n >> m >> k >> d;
vector<vector<int> >Rectangle(n, vector<int>(n, 0));
vector<vector<int> >Rectangle2(n, vector<int>(n, 0)); //表示每个顾客的订餐数量
vector<vector<bool> >Rectangle3(n, vector<bool>(n, false)); //表示每个点是否已经被访问过
vector<vector<int> >Rectangle4(n, vector<int>(n, 0)); //表示每个顾客的订餐代价
int x = 0, y = 0, c = 0;
while (m--)
{
cin >> x >> y;
Rectangle[x][y] = 1; //v[][] == 1表示该点是分店
}
while (k--)
{
cin >> x >> y >> c;
Rectangle[x][y] = 2; //2表示该点是顾客
q.push(make_pair(x, y)); //将顾客放入队列
Rectangle2[x][y] = c; //记录该点顾客的订单数量
}
while (d--)
{
cin >> x >> y;
Rectangle[x][y] = -1; //-1表示该点不可经过
}
pair<int, int> temp(0, 0);
while (!q.empty())
{
pair<int, int> v = q.front(); q.pop();
Rectangle3[v.first][v.second] = true;
for (int i = 0; i < 4; ++i)
{
temp.first = v.first + Direction[i].x;
temp.second = v.second + Direction[i].y;
++Rectangle4[v.first][v.second];
if (!NotOuside(temp.first, temp.second) || Rectangle3[temp.first][temp.second] ||
Rectangle[temp.first][temp.second] == -1)
{
continue;
}
if (Rectangle[temp.first][temp.second] == 2) // 表示找打了顾客
{
break;//直接就返回
}
Rectangle3[temp.first][temp.second] = true;//标记temp点已经被访问过
q.push(make_pair(temp.first, temp.second));
}
}
int ans = 0;
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n; ++j)
{
if (Rectangle4[i][j] != 0)
{
ans += Rectangle4[i][j] * Rectangle2[i][j];
}
}
}
cout << ans << endl;
system("pause");
return 0;
}
这段代码编译时能通过,运行时绝对会出幺蛾子。起初我用的是DEVC++写的代码,但是该工具无法调试,对于程序运行期间报的错我死活无法定位(可能跟我不太熟悉DEVC++有关)。后来放入到VS中运行,程序在运行时报错,点击忽略就会定位到错误行数(上述代码中的89行)。在这一行中我进行了一个判断,但是调用处判断逻辑有问题,所以导致了 最终代码结果不正确。
从第一个 判断条件失败后,紧接着 进行或操作符后面的判断,大师第一个判断都失败了,就说明已经超出了矩阵的边界了而在第二个判断条件我还在去矩阵外的某个坐标处的值,这就属于非法访问内存,所以程序在运行时就会报错。
因此在写代码时一定要先考虑清楚,尽可能的考虑多的情形条件以及进行多的条件判断。
上述代码在89行之前加上一个判断if(NotOuside(temp.first, temp.second)),程序运行时就不会报错
起初我还以为是vector我没用对,导致的非法访问内存