2

私はこれを役に立たなくするためにいくつかの試みをしました。プログラムはコンパイルされますが、プログラムに提供するために考えられるすべてのタイムスタンプ形式は無効です。

#include <boost/program_options.hpp>
#include <boost/optional.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
#include <string>
using namespace boost::program_options;
using namespace std;

int main(int argc, const char** argv) {
    boost::posix_time::ptime forceDate;
    boost::optional<boost::posix_time::ptime> forceDateOptional;

    options_description descr("Options");
    descr.add_options()
    ("force-date,a", value(&forceDate)->value_name("<date>"), "...");

    try {
        variables_map args;
        store(command_line_parser(argc, argv).options(descr).run(), args);
        notify(args);
        cout << "Done." << endl;
        return 0;
    } catch (std::exception& e) {
        cerr << e.what() << endl;
        return 1;
    }
}

でコンパイルしg++ -I /usr/local/include -L /usr/local/lib -lboost_program_options -lboost_system x.cppて実行し./a.out --force-date 2012-01-03ます。

スローされた例外からのエラーは次のとおりです。

the argument ('2012-01-03') for option '--force-date' is invalid
4

2 に答える 2

3

最初に、ストリームから削除program_optionsして単純に解析することで、例を単純化してみましょう。posix_time::ptime

boost::posix_time::ptime forceDate;
std::istringstream ss("2012-01-03");
if(ss >> forceDate) {
    std::cout << forceDate << "\n";
}

上記の例では何も出力されないため、明らかに解析に問題があります。ドキュメントを調べるoperator>>と、期待される月の形式が数値ではなく省略名であることが明らかになります。

上記のコードを次のように変更すると

boost::posix_time::ptime forceDate;
std::istringstream ss("2012-Jan-03");
if(ss >> forceDate) {
    std::cout << forceDate << "\n";
}

目的の出力が生成されます。

ドキュメントをさらに掘り下げると、を使用して入力形式を制御する方法が示されますboost::posix_time::time_input_facet。はset_iso_extended_format、使用する数値形式に形式を設定します。

boost::posix_time::ptime forceDate;
std::istringstream ss("2012-01-03");

auto facet = new boost::posix_time::time_input_facet();
facet->set_iso_extended_format();

ss.imbue(std::locale(ss.getloc(), facet));
if(ss >> forceDate) {
    std::cout << forceDate << "\n";
}

ライブデモ


今に戻るprogram_options。ライブラリがロケールを直接サポートしているようには見えないため、上記のソリューションを機能させる唯一の方法は、グローバル ロケールをいじることです。次の行を例に追加すると、希望どおりに動作します。

auto facet = new boost::posix_time::time_input_facet();
facet->set_iso_extended_format();
std::locale::global(std::locale(std::locale(), facet));

ライブデモ

于 2015-10-30T05:13:28.320 に答える
0

あなたのコードを複製し、Ubuntu 14.04 でコンパイルすることができました。あなたと同じ結果が得られました。だから私は日付をaに渡し、std::stringそれからaを構築しようとしましboost::posix_time::ptimeた:

#include <boost/program_options.hpp>
#include <boost/optional.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
#include <string>
using namespace boost::program_options;
using namespace std;

int main (int argc, const char ** argv) {
    auto dateStr = string {};
    auto descr = options_description { "Options" };

    descr.add_options ()
        ("help,h", "produce help message")
        ("date,a", value (&dateStr)->value_name ("<date>"), "...");

    try {
        auto args = variables_map {};
        store (command_line_parser (argc, argv).options (descr).run (), args);
        notify (args);

        auto forceDate = boost::posix_time::ptime { dateStr };

        cout << "Done." << endl;
        return 0;
    } catch (std::exception & e) {
        cout << e.what () << endl;
        return 1;
    }
}

this SO answer you must linkに従っていることがわかる前に、少し掘り下げなければなりませんboost_date_timeでした。次のスクリプトを使用して、コンパイルと再実行を同時に行いました。

rerun.sh

#!/bin/bash
g++ -o main.x64 -std=c++11 -I . -L/usr/lib/x86_64-linux-gnu main.cpp -lboost_program_options -lboost_system -lboost_date_time
./main.x64 --date "2012-01-01"

これは、実行するために使用した最終的なコードです。

main.cpp

#include <boost/program_options.hpp>
#include <boost/optional.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
#include <string>
using namespace boost::program_options;
using namespace boost::posix_time;
using namespace std;

int main (int argc, const char ** argv) {
        auto dateStr = string {};
        auto descr = options_description { "Options" };

        descr.add_options ()
                ("date,a", value (&dateStr)->value_name ("<date>"), "...");

        try {
                auto args = variables_map {};
                store (command_line_parser (argc, argv).options (descr).run (), args);
                notify (args);

                // this is the important part.
                auto d = boost::gregorian::date {
                        boost::gregorian::from_simple_string (dateStr)
                };

                auto forceDate = boost::posix_time::ptime { d };

                cout << "Done." << endl;
                return 0;

        } catch (std::exception & e) {
                cout << e.what () << endl;
                return 1;
        }
}
于 2015-10-30T04:45:01.277 に答える