【发布时间】:2016-01-10 02:55:57
【问题描述】:
所以,假设我有一个数据文件,其中包含与此类似的常规数据:
[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
}
然后我尝试创建另一个通用包装器,但我对以下问题感到困惑 A) 我不确定如何在标准库转换函数之间进行更改,并且 B) 认为它也会尝试使用字符串 T 来执行,这不是最初的想法。
经过进一步思考,我意识到我可能只是做错了,应该以某种方式尝试只使用一个通用函数。但我不知所措。
这是程序清单。数据存储为一个名为“data”的本地文件。 http://pastebin.com/dRAXRWa3
【问题讨论】:
-
有任何理由编写自己的分词器吗?为什么不直接使用库,比如 boost::spirit?
-
您可以尝试阅读 awk 或 CSV 解析器的源代码,因为这些是用 C 或 C++ 编写的通用数据标记器的示例。 C 与 C++ 不同,但我相信代码会有所帮助。
-
@Rostislav 因为我正在尝试学习创建自己的 C++ 程序的细节。
-
@djechlin 谢谢,感谢您的建议。我会考虑你的建议。
-
有道理。我只是想确定:)