15.9 一个更合理的距离矩阵
最后更新于:2022-04-01 06:25:14
虽然这段代码可以工作,但它本可以组织的更好。既然我们已经写了一个原型,那么我们就处于评价其设计并改进之的有利位置了。
那现在的代码有些什么问题呢?
1. 我们提前不知道要创建多大的距离矩阵,所以我们选择了一个任意大的数字(50),然后创建了一个固定大小的矩阵。更好的方式是允许距离矩阵以类似Set的方式扩充,而apmatrix类的resize函数使之成为可能。
2. 矩阵中的数据没有很好的封装。我们不得不以城市名的集合与矩阵本身作为参数传给processLine,这样很不合适。再就是,因为我们没提供执行错误检查的访问函数,所以使用距离矩阵容易出错。有个好的想法是,将表示城市名的Set对象和表示距离的apmatrix对象组合到DistMatrix类中。
下面是DistMatrix类头文件大概形式的一个草稿:
~~~
class DistMatrix {
private:
Set cities;
apmatrix<int> distances;
public:
DistMatrix (int rows);
void add (const apstring& city1, const apstring& city2, int dist);
int distance (int i, int j) const;
int distance (const apstring& city1, const apstring& city2) const;
apstring cityName (int i) const;
int numCities () const;
void print ();
};
~~~
我们可以使用这个接口来简化main函数:
~~~
void main ()
{
apstring line;
ifstream infile ("distances");
DistMatrix distances (2);
while (true) {
getline (infile, line);
if (infile.eof()) break;
processLine (line, distances);
}
distances.print ();
}
~~~
也可以简化 processLine函数:
~~~
void processLine (const apstring& line, DistMatrix& distances)
{
char quote = ’\"’;
apvector<int> quoteIndex (4);
quoteIndex[0] = line.find (quote);
for (int i=1; i<4; i++) {
quoteIndex[i] = find (line, quote, quoteIndex[i-1]+1);
}
// 将行分割为子串
int len1 = quoteIndex[1] - quoteIndex[0] - 1;
apstring city1 = line.substr (quoteIndex[0]+1, len1);
int len2 = quoteIndex[3] - quoteIndex[2] - 1;
apstring city2 = line.substr (quoteIndex[2]+1, len2);
int len3 = line.length() - quoteIndex[2] - 1;
apstring distString = line.substr (quoteIndex[3]+1, len3);
int distance = convertToInt (distString);
// 将新数据添加到距离矩阵中
distances.add (city1, city2, distance);
}
~~~
我把实现DistMatrix类的成员函数留作练习请读者完成。