C++ Primer 答客問 (8)
侯捷 jjhou@ccca.nctu.edu.tw
1999.10.17 第一次發表於
清大.楓橋驛站(140.114.87.5).電腦書訊版(Computer/CompBook)
本文將於日後整理於 侯捷網站/侯捷譯作/C++ Primer 中文版/答客問
侯捷網站:www.jjhou.com
----------------------------------------------------------------
Jimmy wrote (1999/10/15) :
> 侯先生您好:
>
> 我正在拜讀您的譯作 "c++ primer"。由於我對 STL 極感興趣,
> 所以很快就跳到附錄去看 generic algorithms 的範例。這樣的範例
> 真的很棒,讓我從一堆文字描述中直接跳脫出來,畢竟對 programmer
> 而言有實例說明實在是太好了。
>
> 但是我對於 p1130 的 copy_backward() 的描述有點不解。
> 書中文字所舉的例子 {0,1,2,3,4,5} 經過演算法後的結果,
> 與下一段完整例子(操作對象是個 string 陣列)的結果
> 好像有點矛盾。我不確定是否我認知有問題。可否請您
> 檢驗一下。
>
> p.s. 我很喜歡這本書,讀起來很流暢。謝謝您的用心。
侯捷回覆:
您看書真仔細,一舉便中本書要害。
是的,p.1130 copy_backward() generic algorithm 的文字說明中,
第二段敘述是錯誤的。我在翻譯本書的過程中,沒有能夠挑出原文書
的這個大 bug,是我的失職。
有原文書的朋友也請注意,這個 bug 並沒有出現在原文書 errata 中,
至少我上次(1999/08/10)看的時候沒有。
本書出版後,我對附錄中的所有範例程式做了一次檢閱與測試,
這才測出您所指的這一段錯誤敘述。測試結論以及此段勘誤
已載於侯捷網站 www.jjhou.com 之中。以下我再重複一次,
然後做更多補充。如果您上侯捷網站去看,會更清楚些,
因為我以不同的顏色標示出錯誤的地方和修改的地方。
=====================================================
侯捷網站上的勘誤內容:
■p1130: copy_backward() 下的第二段文字(原書錯誤)
原文:
例如,給予數列 {0,1,2,3,4,5},我們可以複製最後三個元素 (3,4,5) 到
最前三個元素 (0,1,2) 身上,作法是將 first 設定為元素 0 的位址,
last1 設定為元素 3 的位址,last2 設定為元素 5 的下一個位址。
於是元素 5 會被指定到原來的元素 2 身上,元素 4 會被指定到原來的元素 1
身上,
元素 3 會被指定到原來的元素 0 身上。最後的結果是 {3,4,5,3,4,5}。
更正:
例如,給予數列 {0,1,2,3,4,5},我們可以複製最前三個元素 (0,1,2) 到
最後三個元素 (3,4,5) 身上,作法是將 first 設定為元素 0 的位址,
last1 設定為元素 3 的位址,last2 設定為元素 5 的下一個位址。
於是元素 2 會被指定到原來的元素 5 身上,元素 1 會被指定到原來的元素 4
身上,
元素 0 會被指定到原來的元素 3 身上。最後的結果是 {0,1,2,0,1,2}。
======================================================
以下是我的新補充。
(1) 我寫了一個實例如下。
// VC6 : cl -GX 1130.cpp
// BCB4 : bcc32 1130.cpp
#include <algorithm>
#include <vector>
#include <iterator>
#include <iostream>
using namespace std;
/* generates :
original elements sequence:
0 1 2 3 4 5
sequence after copy_backward(begin, end-3, end):
0 1 2 0 1 2
*/
void main()
{
int ia[] = { 0, 1, 2, 3, 4, 5 };
vector<int> vec(ia, ia+6);
ostream_iterator<int> ofile(cout, " ");
cout << "original elements sequence:\n\t";
copy(vec.begin(), vec.end(), ofile);
cout << endl;
copy_backward(vec.begin(), vec.end()-3, vec.end());
cout << "sequence after "
<< "copy_backward(begin, end-3, end):\n\t";
copy(vec.begin(), vec.end(), ofile);
cout << endl;
}
(2) 書中對 copy_backward() 的規格說明如下:
template < class BidirectionalIterator1,
class BidirectionalIterator2 >
BidirectionalIterator2
copy_backward( BidirectionalIterator1 first,
BidirectionalIterator1 last1,
BidirectionalIterator2 last2 );
作者把參數名稱取為 last1 和 last2,不甚好,不能望文解義。
我發現 "Generic Programming and the STL" p.236 對於
此演算法的規格說明得比較好:
template < class BidirectionalIterator1,
class BidirectionalIterator2 >
BidirectionalIterator2
copy_backward( BidirectionalIterator1 first,
BidirectionalIterator1 last,
BidirectionalIterator2 result );
"Generic Programming and the STL" p.236 並說,這個演算法
會執行以下 assignment 動作 :
*(result-1) = *(last-1),
*(result-2) = *(last-2),
etc.
這段解釋對我們瞭解 copy_backward() 的行為頗有幫助。
--- the end
--
※ Origin: 楓橋驛站<bbs.cs.nthu.edu.tw> ◆ Mail: jjhou@ccca.nctu.edu.tw