實習目標 |
1. 使用 string 與 vector 類別物件所提供的功能
2. 使用 C++ 標準函式庫中所提供 sort() 及 find() 演算法 3. 使用 C++ 標準函式庫中所提供物件的界面 4. 熟悉透過界面描述物件功能的抽象化描述方法 |
---|---|
步驟一 | 在 C++
的標準函式庫中, string
是一個取代 C 中字串 (字元陣列) 的類別(你可以先想成是一種資料型態), vector
(建構元範例) 則是取代 C 中陣列的類別, 運用這兩個類別來寫程式的話, 可以省掉很多不必要的錯誤。(當然你學會在程式中使用這些東西以後, 並不代表原先你在資料結構裡面學的各種低階架構都沒有用了,
在許多時候你的程式環境並沒有提供給你這些類別或是函式, 或是你需要執行起來非常有效率, 或是使用的記憶體要很小, 你就必須自己架構資料結構了)
string 類別的基本使用範例如下: #include <string> using namespace std; string s1, s2; // empty strings string s3 = "Hello, World."; // initialized string s4("I am"); // initialized char dest[100]; s2 = "today"; // string copy s1 = s3 + " " + s4; // concatenation of strings s1 += " 8 "; // appending to a sting cout << s1 + s2 + "!" << endl; // extended ostream strcpy(dest, s1.c_str()); // convert to char array cin >> s1; cout << s1.length(); // or s1.size(); if (s3 + s4 == "Hello, World.I am") { // do something } vector 類別的使用範例如下面這個課本上運用 string 與 vector 列印資料及列號的程式 // Thinking in C++ page 105 #include <iostream> #include <vector> #include <string> #include <iomanip> using namespace std; int main() { ifstream inf("AddLineNumber.cpp"); string line; vector<string> lines; while (getline(inf, line)) lines.push_back(line); for (int i=0; i<lines.size(); i++) cout << i << ":" << lines[i] << endl; // 下面是一段運用 vector 容器物件的 iterator 來依序列印所有 // 元素的程式碼 vector<string>::iterator iter; for (iter=lines.begin(); iter<lines.end(); iter++) cout << *iter << endl; return 0; }iterator 是每一個 STL 的容器類別裡面都有定義的一個內部類別 (internal class), iterator 型態的變數的概念和使用方法 和 C 裡面的 "指標變數" 幾乎是一樣的, 可以用 *, ->, ++, -- 等運算符號, 不過請特別注意這只是概念上相同, 實際上不見得就是記憶體位址, 你要取得容器物件裡某一個元素的 iterator 時, 不是像 C 裡面直接在變數前面加上 & 來取得, 通常是透過 begin(), end(), find() 等等函式來取得。 |
步驟二 | 請先修改上面這個課本中的範例程式來處理我們先前的 raw1.dat,
請先宣告一個結構型態
struct DataRecord { int lineNumber; int value; };參考上一個步驟裡的範例, 設定 vector 裡存放的每一元素為 DataRecord, 例如: vector<struct DataRecord> recordArray; 或是 vector<DataRecord> recordArray; (C++ 語法中 struct 關鍵字可省略) 然後運用 iostream 的功能將 raw1.dat 檔案內的資料讀取到 recordArray 陣列中, 將每一筆資料在該檔案內的列號記錄在 lineNumber 那個欄位中, 將每一筆資料的內容記錄在 value 那個欄位中。
DataRecord tmp; int lineNumber = 0; ... inf >> tmp.value; tmp.lineNumber = ++lineNumber; recordArray.push_back(tmp); |
步驟三 | 請運用標準 C++ 的 STL 函式庫中的 sort()
函式將你在上一步驟讀到的 vector 物件進行排序
|
步驟四 | 請在上一步驟所作出來的程式中運用 find()
函式在排序過的 vector 資料裡尋找資料 {17, 8} 和 {60, 5} 兩筆資料, 並且列印結果出來
範例執行程式: 請下載 SortVectorDataRecord01.exe 並且下載 raw1.dat 後在命令視窗內執行 請注意, 在使用 find() 函式時, 必須替 DataRecord 定義如何比較兩個資料結構是相等的, 這一部份你還沒有學到, 請按照下面的說明修改 struct DataRecord { .... bool operator==(const DataRecord& y); }; bool DataRecord::operator==(const DataRecord& y) { 請比較欄位 value 和 y.value 是相等的, 同時 lineNumber 和 y.lineNumber 是相等的 } Hint: return ((value == y.value) && ...); find() 函式透過想要搜尋的容器物件 v 來呼叫, 例如: #include <algorithm> using namespace std; ... vector<DataRecord> v; ... DataRecord goal; goal.value = 8; goal.lineNumber = 17; ... find(v.begin(), v.end(), goal);呼叫時需要傳給它三個參數
find() 函式會傳回一個 vector<...>::iterator 型態的資料, 如果這個資料等於 v.end() 就表示沒有找到, 如果找到的話, 你可以運用它傳回的 iterator 來列印結果, iterator 相當於指向那個找到的結構變數的指標, 所以你可以用 iterator->lineNumber 和 iterator->value 來存取那個找到的結構裡的兩個欄位, 你也可以運用 iter - v.begin() 來找到 iter 目前在容器中的位置。 |
步驟五 | 請將所完成的 project (去掉 debug/ 資料匣下的所有內容) 壓縮起來儲存在 cyber 上你的帳號內, 後面的實習課程可能需要使用這裡所完成的程式 |
其他相關事項請參考下列文章 |
回
C++ 物件導向程式設計課程
首頁
製作日期: 02/16/2004
by 丁培毅 (Pei-yih Ting)
E-mail: pyting@cs.ntou.edu.tw
TEL: 02 24622192x6615
海洋大學
工學院
資訊工程系
Lagoon