find
そしてsubstr
、特に構文チェックを緩める必要がある場合に、多くの単純な構文解析の問題に非常に適した2つの非常に優れた関数オーバーロードのファミリーです。
バージョンベクトルから複数のスカラーを抽出するには、見つかったインデックスを次の場所に保存します。
const auto a = verstr.find('.');
const std::string major = verstr.substr(0, a);
次に、のオーバーロードの1つで再利用し、次のいずれstring::find
かで検索を開始しa
ます。
const auto b = verstr.find ('.', a+1);
const std::string minor = verstr.substr(a+1, b);
などなど。
構文チェックが必要な場合は、返されたインデックスを以下と比較してくださいstring::npos
。
const auto a = verstr.find('.');
if (std::string::npos == a)
.... bad syntax ....
この答えのペーストビンスタイルバージョン:
#include <string>
#include <stdexcept>
#include <iostream>
struct Version
{
std::string Major, Minor, Patch;
Version(std::string const &Major)
: Major(Major), Minor("0"), Patch("0")
{}
Version(std::string const &Major, std::string const &Minor)
: Major(Major), Minor(Minor), Patch("0")
{}
Version(std::string const &Major, std::string const &Minor, std::string const &Patch)
: Major(Major), Minor(Minor), Patch(Patch)
{}
};
std::ostream& operator<< (std::ostream &os, Version const &v)
{
return os << v.Major << '.' << v.Minor << '.' << v.Patch;
}
Version parse (std::string const &verstr) {
if (verstr.empty()) throw std::invalid_argument("bad syntax");
const auto first_dot = verstr.find('.');
if (first_dot == std::string::npos)
return Version(verstr);
const auto second_dot = verstr.find('.', first_dot+1);
if (second_dot == std::string::npos)
return Version(verstr.substr(0, first_dot),
verstr.substr(first_dot+1, second_dot));
return Version(verstr.substr(0, first_dot),
verstr.substr(first_dot+1, second_dot),
verstr.substr(second_dot+1));
}
その後
int main () {
std::cout << parse("1.0") << '\n'
<< parse("1.0.4+Patches(55,322)") << '\n'
<< parse("1") << '\n';
parse(""); // expected to throw
}