精華區beta CompBook 關於我們 聯絡資訊
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