Lab 2-2: Sample program using vector, string,
sort,and find

實習目標 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;
        return 0;
    }
步驟二 請先修改上面這個課本中的範例程式來處理我們先前的 raw1.dat, 保留 vector 的使用, 但是請先宣告一個結構型態
    struct DataRecord
    {
        int ordinalNumber;
        int value;
    };
參考上一個步驟裡的範例, 設定 vector 的每一元素為 DataRecord, 例如:
    vector<struct DataRecord> recordArray; 或是
    vector<DataRecord> recordArray;
然後運用 iostream 的功能將 raw1.dat 檔案內的資料讀取到 recordArray 陣列中, 將每一筆資料在該檔案內的列號記錄在 ordinalNumber 那個欄位中, 將每一筆資料的內容記錄在 value 那個欄位中。
步驟三 請運用 sort() 函式將你在上一步驟讀到的 vector 物件進行排序
  • 要使用 sort() 函式的話, 你需要 #include <algorithm>
  • 然後請注意看 MSDN Library 中的 alg_sort.cpp 範例, 節錄如下:
        #include <algorithm>
        ...
        bool UDgreater(int elem1, int elem2) {
           return elem1 > elem2;
        }
        ...
        vector<int> v1;
        ...
        sort(v1.begin(), v1.end());
        ...
        sort(v1.begin(), v1.end(), UDgreater);
        ...
        
    由於這個範例程式中 vector 的基本元素是 int, 所以才可以用 sort(v1.begin(), v1.end()) 來排序, 我們現在的應用程式中 vector 的基本元素是 DataRecord, 所以必需用第二種排序的方法,也就是 sort(v1.begin(), v1.end(), UDgreater) 來排序, 其中第三個參數是一個所謂 Binary Predicate 的函式之指標, 這個函式需要接受兩個參數並且進行比較大小的動作, 它的 prototype 可以如下述:
        bool greater(DataRecord elem1, DataRecord elem2);
        或是
        bool greater(DataRecord &elem1, DataRecord &elem2);
        或是
        bool greater(const DataRecord elem1, const DataRecord elem2);
        或是
        bool greater(const DataRecord &elem1, const DataRecord &elem2);
        或是
        int greater(const DataRecord &elem1, const DataRecord &elem2);
        
    請完成這個 greater 的函式, 完成排序的程式, 並且將結果加上列號與原始的列號一起印出來
範例執行程式: SortVectorDataRecord.exe (請下載後在命令視窗內執行)
步驟四 請在上一步驟所作出來的程式中運用 find() 函式在排序過的 vector 資料裡尋找資料 {17, 8} 和 {60, 5} 兩筆資料, 並且列印結果出來

範例執行程式: SortVectorDataRecord01.exe (請下載後在命令視窗內執行)

請注意, 在使用 find() 函式時, 必須替 DataRecord 定義如何比較兩個資料結構是相等的, 這一部份你還沒有學到, 請按照下面的說明修改

    struct DataRecord
    {
        ....
        bool operator==(const DataRecord& y);
    };
    
    bool DataRecord::operator==(const DataRecord& y)
    {
        請比較欄位 value 和 y.value 是相等的,
        同時 ordinalNumber 和 y.ordinalNumber 是相等的
    }
    
find() 函式會傳回一個 vector::iterator 型態的資料, 如果這個資料等於 v.end() 就表示沒有找到, 如果找到的話, 你可以運用它傳回的 iterator 來列印結果, iterator 相當於指向那個找到的結構變數的指標, 所以你可以用 iterator->ordinalNumber 和 iterator->value 來存取那個找到的結構裡的兩個欄位。
步驟五 請將所完成的 project (去掉 debug/ 資料匣下的所有內容) 壓縮起來儲存在 cyber 上你的帳號內, 後面的實習課程可能需要使用這裡所完成的程式

C++ 物件導向程式設計課程 首頁

製作日期: 02/16/2004 by 丁培毅 (Pei-yih Ting)
E-mail: pyting@cs.ntou.edu.tw TEL: 02 24622192x6615
海洋大學 電機資訊學院 資訊工程系 Lagoon