所以,說我有一個類似格式的這個常規數據的數據文件:如何在C++中創建通用數據標記器?
[42,6,9,56,1337]
[220,9001,15,22,35]
[127,0,0,1,8080]
我作爲一個字符串讀取每個行,我有一個接受輸入字符串,多張分隔符爲另一個字符串一個標記,並提及用於存儲輸出的vector<string>
。
// given a string with delimiters inside, parse it into
// individual tokens stored in a vector<string>
void tokenize(const string& str, vector<string>& tokens,
const string& delimiters = " ") {
auto last_pos = str.find_first_not_of(delimiters, 0); // first token
auto curr_pos = str.find_first_of(delimiters, last_pos); // next delim
while (curr_pos != str_end || last_pos != str_end) {
tokens.emplace_back(str.substr(last_pos, curr_pos - last_pos));
last_pos = str.find_first_not_of(delimiters, curr_pos); // next token
curr_pos = str.find_first_of(delimiters, last_pos); // next delim
}
}
int main() {
ifstream fs{"data"};
string tmp{""};
const string delims{"[,]"};
vector<string> tokens;
//vector<int> tokens;
//vector<double> tokens;
while (getline(fs, tmp)) tokenize(tmp, tokens, delims);
cout << tokens << endl;
}
到目前爲止確定。但後來我想用實際的數據類型來代替字符串,所以我編寫了幾個數字包裝函數,它們將vector<string>
轉換成(比如說)vector<int>
。然後我意識到這些基本上是彼此重複的。
// int wrapper
void tokenize(const string& str, vector<int>& tokens,
const string& delimiters = " ") {
vector<string> str_tokens;
tokenize(str, str_tokens, delims);
for (const auto& e : str_tokens)
tokens.emplace_back(stoi(e)); // ints
}
然後我試圖創建另一個一般的包裝,但還是掛了問題, 一個)我不知道如何標準庫轉換功能之間切換,並且 乙)提花它也會嘗試用T字符串執行,這不是最初的想法。
經過一點點進一步的思考,我意識到我可能只是做錯了,應該以某種方式嘗試只使用一個泛型函數。但我不知道如何去做。
下面是程序清單。數據存儲爲名爲「data」的本地文件。 http://pastebin.com/dRAXRWa3
是否有任何理由編寫自己的tokenizer?爲什麼不使用一個庫,比如boost :: spirit? – Rostislav
您可以嘗試閱讀awk或CSV解析器的源代碼,因爲這些是用C或C++編寫的通用數據標記器的示例。 C與C++不同,但我確信代碼會有幫助。 – djechlin
@Rostislav因爲我想了解創建自己的C++程序的細節。 – alarmed