編集 3
正規表現に行き詰まったので、古き良きカスタム解析アプローチに行きました。ファイルの内容は非常にきれいにトークン化でき、トークンは非常に単純なステート マシンを使用してループで解析できるため、それほど悪い結果にはなりませんでした。確認したい方は、Stackoverflow hereの私の他の質問に、range-for、ifstream イテレーター、およびカスタム ストリーム トークナイザーを使用してこれを行うコードのスニペットがあります。これらの手法により、カスタム パーサーを実行する際の複雑さが大幅に軽減されます。
ファイルの内容を 2 つのキャプチャ グループの最初の部分でトークン化し、次に行ごとにトークン化したいと思います。私は半機能的なソリューションが好きですが、これを改善する方法を学びたいです。つまり、キャプチャ グループに関する知識不足を補うための「余分な処理」は必要ありません。次にいくつかの準備があり、最後により正確な質問があります (行
const std::regex expression("([^:]+?)(^:|$)");
...は、その結果の処理と組み合わせて質問したいものです)。
基本的に次のように定義されているファイル:
definition_literal : value_literal
definition_literal : value_literal
definition_literal : value_literal
definition_literal : value_literal
HOW TO INTERPRET THE FOLLOWING SECTION OF ROWS
[DATA ROW 1]
[DATA ROW 2]
...
[DATA ROW n]
各データ行は、空白で区切られた特定の数の整数または浮動小数点数で構成されます。各行には他の行と同じ数の数値があります (たとえば、各行には 4 つの整数があります)。というわけで、「解釈部」は基本的にこのフォーマットを平文で一行に伝えます。
次のようなファイルを読み取る、ほぼ機能するソリューションがあります。
int main()
{
std::ifstream file("xyz", std::ios_base::in);
if(file.good())
{
std::stringstream file_memory_buffer;
file_memory_buffer << file.rdbuf();
std::string str = file_memory_buffer.str();
file.close();
const std::regex expression("([^:]+?)(^:|$)");
std::smatch result;
const std::sregex_token_iterator end;
for(std::sregex_token_iterator i(str.begin(), str.end(), expression); i != end; ++i)
{
std::cout << (*i) << std::endl;
}
}
return EXIT_SUCCESS;
}
正規表現 definedexpression
を使用する<value>
と、定義ファイルの部分、解釈部分、データ行を 1 つずつ出力します。正規表現を次のように変更すると
"([^:]+?)(:|$)"
...それは、私が望むように、1つのグループでトークン化されたすべての行を出力しますが、最初の部分を2つのグループでトークン化し、残りを行ごとにトークン化する方法は?
ポインタ、コード、説明は大歓迎です。ありがとう。
編集:
すでにTom Kerrに指摘されているように、いくつかの追加点として、これはカスタム パーサーを作成するのではなく、私ができるかどうかを確認するためのリハーサルまたは型のコーディングでもあります。これは正規表現で。ここで正規表現が最も効率的な方法ではないことはわかっていますが、それは問題ではありません。
私が望んでいるのは、ヘッダー情報のタプル (サイズ 2 のタプル) のリスト、次に INTERPRET 行 (サイズ 1 のタプル) のようなもので、データをどう処理するかについて関数を選択するために使用できます。行 (サイズ 1 のタプル)。
はい、「HOW TO INTERPRET」行は明確に定義された一連の文字列に含まれており、INTERPRET 行の 1 つが満たされるまで、途中で文字列を分割しながら、最初から行ごとに読み取ることができます。この正規表現ソリューションは最も効率的な方法ではないことはわかっていますが、カタをコーディングして、顧客のパーサー以外のものを作成するようなものです (前回 C++ で書いたのはかなり長いので、これも別の方法でリハーサル中です)。 )。
編集2
次のように、イテレータの型を変更することで、(この質問のコンテキストで) タプルにアクセスできました。
const std::sregex_iterator end;
for(std::sregex_iterator i(str.begin(), str.end(), expression); i != end; ++i)
{
std::cout << "0: " << (*i)[0] << std::endl;
std::cout << "1: " << (*i)[1] << std::endl;
std::cout << "2: " << (*i)[2] << std::endl;
std::cout << "***" << std::endl;
}
これは私が望んでいるものとはまだかけ離れていますが、使用しようとしている正規表現には何か問題があります。いずれにせよ、この新しい発見、別の種類の反復子も役に立ちます。