C++ 入門指南 4.01

單元 23 - 認識標準程式庫

-unit23-

標準程式庫 (standard library) 是依據 C++ 標準,隨編譯器 (compiler) 提供的程式庫 (library)

標準程式庫 → 原始程式碼

我們已經用過不少標準程式庫中的例子,例如於命令列印出字串 (string)

cout << endl << m << endl << endl << endl;

完整程式請參考單元 1 - 認識 C++ 語言

或是產生擬隨機整數

int a = rand() % 10;

完整程式請參考單元 16 - 繼續測試

當然還有上一個單元重構版本的 Encrypt 類別 (class) ,其中攪亂密碼表字串順序

// 初始化密碼表字串
code_array = "abcdefghijklmnopqrstuvwxyz";
// 獲取時鐘週期個數
unsigned int seed = system_clock::now().time_since_epoch().count();
// 攪亂字串中的元素順序
shuffle(code_array.begin(), code_array.end(), mt19937(seed));

到編碼與解碼

r += code_array.at(alphabet_array.find(c));

以上都是利用標準程式庫的例子,標準程式庫涵蓋的應用相當廣泛。

標準程式庫隨新標準也不斷推出新的擴充內容,我們從單元 14 單元 24 的練習一路來介紹不少標準程式庫中的功能,如下表

單元類型
14陣列、資料型態
15陣列、型態轉換
16vector 、擬隨機數
17vector 、 shuffle
18map 、時間相關
19map 、格式化輸出
20set 、數學相關
21集合體型態、數學相關
22命令列參數、系統指令
23輸入與檔案處理
24字串相關

以上散落在各單元的練習是以舉例示範為主的小程式 (program) ,實際上開發程式是要按照目標進行開發,標準程式庫的好處是已經有極其大量已經寫好,具有效率並且測試無誤的程式,這些程式都可以直接拿來使用,我們寫程式就不需要什麼都從頭自己開發。

進行軟體開發要避免重新發明輪子,這裡所謂輪子也就是開發好的程式,為什麼要避免重新發明輪子呢?原因很簡單,這樣我們就可以專注開發我們想要的功能,例如要開發圖形介面的應用程式,如果不使用其他第三方程式庫 (third party library) ,全部自己從頭開發的話,等於差不多要自己開發一套作業系統,那工程極其浩大,除了要精熟一門程式語言以外,更要熟悉各種硬體基礎知識。

如果要好好、詳細的介紹標準程式庫,那可能就是一本大部頭的書了說,本書中只挑選些常用功能介紹。

學會程式語言會基本語法後,接下來就是搭配學習程式庫的內容,通常會先以標準程式庫開始,然後繼續延伸就是學習第三方程式庫,第三方程式庫或者可稱為應用程式介面 (application programming interface) 軟體開發套件 (software development kit) 軟體框架 (software framework) 遊戲引擎 (game engine) 等等的名稱,之所以有這些名稱差異,不外是應用領域不同或是程式語言不同。

基本上寫程式常見的是在程式中混用標準程式庫的各種功能,除了我們重構版的 Encrypt 是典型的例子外,以下再看到一個利用標準程式庫的例子

// 引入標準程式庫中時間日期的相關程式
#include <ctime>
// 引入標準程式庫中相關的輸入、輸出程式
#include <iostream>
// 引入標準程式庫中的 array
#include <array>
// 引入標準程式庫中的 vector
#include <vector>

// cout 為 std 中的輸出物件
using std::cout;
// endl 為 std 中的斷行符號
using std::endl;
// array 為 std 中的陣列型態
using std::array;
// vector 為 std 中的集合體型態
using std::vector;

int main() {
    // 計算陣列處理時間
    time_t t1 = time(NULL);
    long i = 0;
    array<long, 1000000> a;
    for (int j: a) {
        j = i++;
        cout << j << ", ";
    }
    cout << endl;

    time_t t2 = time(NULL);

    // 計算 vector 處理時間
    time_t t3 = time(NULL);
    vector<long> v;
    for (int k = 0; k < 1000000; k++) {
        v.insert(v.end(), k);
        cout << v[k] << ", ";
    }
    cout << endl;

    time_t t4 = time(NULL);

    // 顯示處理時間
    cout << endl << endl;
    cout << "array: " << t2 - t1 << endl;
    cout << "vector: " << t4 - t2 << endl;

    return 0;
}

/* 《程式語言教學誌》的範例程式
   http://kaiching.org/
   檔名:time_test.cxx
   功能:示範利用標準程式庫比較 array 與 vector 執行時間
   作者:張凱慶 */

這個程式比較建立 arrayvector1000000 個相同整數元素的處理時間,

// 顯示處理時間
cout << endl << endl;
cout << "array: " << t2 - t1 << endl;
cout << "vector: " << t4 - t2 << endl;

其中時間是利用 time(NULL) 取得現在的系統時間,單位是秒

time_t t1 = time(NULL);

一共分別取得四次時間,分別是 array 處理前的 t1 ,處理後的 t2vector 處理前的 t3 ,處理後的 t4 ,利用 Windows 11 下的 Ubuntu 子系統,編譯執行結果如下

-time_test-

因為利用 Windows PowerShell 編譯 C++11 程式會出現問題,因此改用 Ubuntu 子系統進行編譯。

以上只是粗略地以「秒」為單位計算,可以大概知道 vectorarray 耗時,但相對 vector 的功能也較多。

現在寫程式通常會混用大量程式庫內容,因為很多程式功能都已經開發好,放在程式中,我們就不需要重新開發已經有的程式功能,而能專注開發新的程式功能,依據程式語言標準隨附的是標準程式庫,編譯器也通常都會直接實作標準程式庫的功能。

然而雖然 C++ 的標準程式庫提供非常豐富的資源,可是使用者介面 (user interface) 仍是沿襲 C 語言命令列 (command line) 的風格,因此我們要替 Encrypt 設計一個圖形使用者介面 (graphical user interface, GUI) 就得借助第三方程式庫。所以接下來就讓我們繼續認識一下第三方程式庫 - Qt 吧!

中英文術語對照
應用程式介面application programming interface
類別class
命令列command line
編譯器compiler
遊戲引擎game engine
圖形使用者介面graphical user interface, GUI
程式庫library
程式program
軟體開發套件software development kit
軟體框架software framework
標準程式庫standard library
字串string
第三方程式庫third party library
使用者介面user interface
重點整理
1. 標準程式庫是依 C++ 標準隨編譯器提供的程式庫,第三方程式庫則是其他開發商提供程式庫。
2. 標準程式庫提供眾多的應用,包括容器、工具、地方資訊、字串、串流及輸出入、語言、執行緒、數學等應用。
3. 學習程式設計不應該重新發明輪子,實際寫程式往往會混用程式庫的內容。
問題與討論
1. 為什麼要有標準程式庫?不能程式的所有功能都自己開發嗎?
2. 什麼是命名空間?為什麼要用命名空間?
3. 為什麼要有第三方程式庫?除了 Qt 外還有其他的第三方程式庫嗎?
練習
1. 標準程式庫 iostreamcin 物件用來接收使用者輸入,連帶須使用 >> 運算子,將儲存輸入的變數放在 >> 之後,寫一個程式 exercise2301.cxx ,宣告字元變數 c ,然後用 cin 接收使用者輸入,最後印出字元變數 c參考程式碼
2. 承上題,寫一個程式 exercise2302.cxx ,改成使用 cin 接收使用者輸入兩個整數,然後印出相加值。 參考程式碼
3. 承上題,寫一個程式 exercise2303.cxx ,利用 while (true) 迴圈接收使用者輸入,直到使用者輸入 'q' 之後就結束程式。 參考程式碼
4. 標準程式庫中的 fstream 可以用來進行檔案處理,寫一個程式 exercise2304.cxx ,宣告 fstream 的檔案物件,然後利用 open() 開啟指定的檔案, open() 的第一個參數為檔名字串,第二個參數可以用 std::ios_base::app ,接下來用 is_open() 判斷檔案是否開啟,開啟成功寫入自訂字串,開啟失敗印出失敗訊息。 參考程式碼
5. 承上題,將 open() 的第二個參數改成 std::ios::in 讀取檔案內容,實際讀取要用 read()read() 的第一個參數用字元陣列,第二參數則是字元陣列的長度,寫一個程式 exercise2305.cxx ,讀取並印出上題存檔的文字內容。 參考程式碼
6. 承上題,寫一個程式 exercise2306.cxx ,利用 cingetline() 取得使用者輸入的字元陣列,然後儲存到檔案中,再從檔案讀取印出來。 參考程式碼
7. 標準程式庫 filesystem 中的 exists() 可以判斷檔案是否存在,寫一個程式 exercise2307.cxx ,利用 exists() 判斷指定的檔案例如 demo.cxx 是否存在。 參考程式碼
8. 承上題, file_size() 回傳指定檔案的位元組數,寫一個程式 exercise2308.cxx ,利用 file_size() 印出指定的檔案例如 demo.cxx 的位元組數。 參考程式碼
9. 承上題, is_directory() 可以判斷指定路徑是否為目錄,寫一個程式 exercise2309.cxx ,利用 is_directory() 判斷指定的檔案例如 demo 是否為目錄。 參考程式碼
10. 承上題, is_empty() 可以判斷指定檔案是否沒有內容,寫一個程式 exercise2310.cxx ,利用 is_empty() 判斷指定的檔案例如 demo.cxx 是否沒有內容。 參考程式碼

相關教學影片

上一頁 單元 22 - 重構
回 C++ 入門指南 4.01 目錄
下一頁 單元 24 - 認識第三方程式庫 - Qt
回 C++ 教材
回程式語言教材首頁