C 中的config設計

2022-06-17 19:42:08 字數 4320 閱讀 7074

配置檔案讀寫類,它要有以下這些方法:

1. 支援讀入乙個指定配置檔案的能力

2. 支援隨時加入乙個配置項的能力

3. 足夠強大,能夠寫入各種資料結構的配置資訊

c++ 裡,我們要儲存這樣的資料就使用 std::map 即可。

也就是說,我們的 config 類中,需要有乙個最基本最基本的儲存配置檔案鍵值對資訊的 std::map 成員,這個成員用來將配置檔案中的每個 key 值和其對應的 value 值記錄下來。

那麼另外乙個問題也就來了,我們的 std::map 究竟應該是什麼型別的呢?

哈哈,這個問題其實非常簡單,因為我們的鍵值對資訊都是要讀出寫入到檔案的,那麼 std::map 不論是 key 值還是 value 值都將會是字串型別,即 c++ stl 的 std::string (config 類不支援中文編碼)類即可。

那麼有人就會問了,如果 value 值只是乙個簡簡單單的 std::string 類的話,我想要儲存乙個非常複雜的資料結構怎麼辦,比如乙個phonekey 值,對應了乙個**號碼列表呢?

這個問題其實也非常簡單,這裡的 std::map 成員只是 config 類中的最基本最基本儲存到檔案裡的字串鍵值對記錄,而 config 為了支援使用者儲存多種複雜的 value 值,還提供了模板支援。因此,這裡只需要你提供的 value 值的結構可以被轉化為 std::string 型別,就可以使用 config 類來儲存你的資料結構了。

因此,讓我們看看 config 類的**:

std::string m_delimiter;  //!< separator between key and value  

std::string m_comment; //!< separator between value and comments

std::map<:string std::string> m_contents; //!< extracted keys and values

這三個內部的屬性,m_delimiter是我們之前提到的 key 值和 value 值的分隔符=的設定,m_comment是我們之前提到的注釋內容開頭#字元的設定,m_contents就是我們上面討論的 std::map 物件,並且以 key 值和 value 值均為 std::string 型別儲存。

此外,我們在 config 類中看到的那麼多的模板函式,其歸根結底想要實現的,就是支援使用者自定義的 value 資料結構的讀取和寫入:

//!template t read(const std::string& in_key) const;  

// modify keys and values

template void add(const std::string& in_key, const t& in_value);

這裡擷取了兩個重要的函式,乙個用來讀取 key 值對應的 value 值,乙個用來新增乙個鍵值對。可以看到,這裡的 key 值永遠都是乙個 std::string 型別的物件,而相應的 value 值則是模板定義的型別,支援使用者自定義傳入任何的可以轉成 std::string 型別的資料結構。

接下來讓我們想想這樣乙個問題,在我們看到了配置檔案的內容之後,並且將其抽象成了 std::map 的資料結構,之後我們需要做的,就是給類的呼叫者暴露方法的方法即可。

那麼應該有哪些方法呢:

1. 乙個可以跟某個具體的配置檔案繫結起來的建構函式

2. 獲取指定 key 值的 value 值

3. 加入一對鍵值對

4. 修改指定 key 值的 value 值

5. 刪除一對鍵值對

暫時就想到了這些比較重要的,那麼 config 類中提供了這些方法了嗎?

哈哈,提供了,讓我們乙個乙個來看:

1. 乙個可以跟某個具體的配置檔案繫結起來的建構函式

config::config(string filename, string delimiter, string comment)

: m_delimiter(delimiter), m_comment(comment)

作者使用 std::ifstream 開啟了乙個本地檔案,注意,呼叫這個方法之前必須保證該檔案存在。我們要注意到作者呼叫了in >> (*this),呼叫了本類的 operator>> 過載函式,用來讀取檔案內容(此函式過於冗長,可以自行檢視原始碼)並將其儲存到 std::map

//!template t read(const std::string& in_key) const;  

template t read(const std::string& in_key, const t& in_value) const;

template bool readinto(t& out_var, const std::string& in_key) const;

這三個都是模板函式,主要是用來獲取使用者自定義資料結構的 value 值。需要注意的是,這三個函式的用法,第乙個是返回 value 值;第二個是可以將 value 值在引數中返回;第三個直接將 value 值寫入到傳入的 var 物件中。

3. 加入一對鍵值對 

4. 修改指定 key 值的 value 值 

作者直接使用了乙個函式即完成了第 3 點和第 4 點的工作:

template

void config::add(const std::string& in_key, const t& value)

這裡使用了 c++ 的 std::map 的特性,如果 key 值在 std::map 中存在,則更新 value 值,否則就新增一對鍵值對。需要注意的是,這裡呼叫了這行**:

std::string v = t_as_string(value);

其中t_as_string函式將使用者傳入的自定義模板類轉化為 std::string 型別進行儲存,而該方法的實現如下:

/* static */

template

std::string config::t_as_string(const t& t)

這個類直接呼叫了使用者自定義模板類的 operator<< 過載操作符函式,也就是說,只要使用者自定義資料結構自定義過載了 operator<< 操作符函式,就可以用 config 類來進行 value 值的讀寫操作了。

5. 刪除一對鍵值對

void config::remove(const string& key)

幸而有 c++ stl 強大的功能,刪除一對鍵值對就是這麼簡單。

6. 另外的一些方法 

作者為了方便使用者使用,還提供了諸如查詢檔案是否存在、鍵值是否存在、讀入檔案、設定獲取鍵值分隔符、設定獲取注釋識別符號等等方法。都是比較簡單並且易用的,感興趣的同學可以自行檢視原始碼。

這裡,我自行編寫了乙個 demo 來測試 config 類的功能:

#include #include #include #include #include "config.h"

int main()

out.close();

system("pause");

return 0;

}

幸而有強大的 config 類,讓我操作配置檔案變成了一件這麼簡單的事情!

然而這裡需要注意的是,我們在使用 config 類進行了 add() 操作之後,我們僅僅只是在 config 類中操作了 std::map 型別的 m_contens 物件內容而已,我們還需要將其寫入到檔案中去,因此這裡我最後呼叫了寫檔案流進行寫入操作,注意這行**:

// 利用 config 類的 << 過載運算子

out << config;

這裡隱含呼叫了 config 類的 operator<< 過載運算子:

std::ostream& operator<

return os;

}

cpp cmake中的config編寫

關於cpp cmake的config編寫,本文枚列幾個關鍵檔案。方便大家實現,注意到config.h是通過cmake自動生成,但是要注意下configure file時候的路徑。另外就是configure file前要事先定義好巨集變數。cmakelists.txt編輯 cmakelist.txt ...

python flask中config配置管理問題

在專案中我們需要配置各種環境。如果我們的配置項很少的話,可以直接簡單粗暴的來 比如 debug true,secret key x 也可以在引用之後直接傳入物件 import settings 2 使用檔案名字載入。直接傳入名字就行了 別的字尾的也可以,不侷限於.py的 預設當配置檔案不存在的時候丟...

C 讀寫 Config 檔案

在學習 c 的過程中,需要用到讀取配置檔案的功能,所以通過查閱資料,得出下面的 請讀者評閱 邏輯框架1.先例項化乙個 execonfigurationfilemap 並將檔案的物理路徑賦給其 execonfigfilename 屬性2.將要開啟的 config 檔案的 物理路徑 賦值給 execon...