在編程時,一個函數功能單一化不僅僅只是有降低耦合性的好處,在避免一些很深或者很容易忽略的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我沒用對,導致的非法訪問內存