找不到任何内容时生成默认值

时间:2013-09-02 19:27:01

标签: c++ boost-spirit boost-spirit-karma

我有一个输入向量,可以在空元素和3个元素之间有任何大小。我希望生成的字符串始终是由空格分隔的3个浮点数,如果向量中没有足够的元素,则使用默认值。到目前为止,我已经设法只输出向量的内容:

#include <iostream>
#include <iterator>
#include <vector>

#include "boost/spirit/include/karma.hpp"

namespace karma = boost::spirit::karma;
namespace phx   = boost::phoenix;
typedef std::back_insert_iterator<std::string> BackInsertIt;

int main( int argc, char* argv[] )
{
    std::vector<float> input;
    input.push_back(1.0f);
    input.push_back(2.0f);

    struct TestGram 
        : karma::grammar<BackInsertIt, std::vector<float>(), karma::space_type>
    {
        TestGram() : TestGram::base_type(output)
        {
            using namespace karma;
            floatRule = double_;

            output = repeat(3)[ floatRule ];
        }

        karma::rule<BackInsertIt, std::vector<float>(), karma::space_type> output;
        karma::rule<BackInsertIt, float(), karma::space_type> floatRule;
    } testGram;


    std::string output;
    BackInsertIt sink(output);
    karma::generate_delimited( sink, testGram, karma::space, input );

    std::cout << "Generated: " << output << std::endl;

    std::cout << "Press enter to exit" << std::endl;
    std::cin.get();
    return 0;
}

我已经尝试将浮动规则修改为这样的内容:floatRule = double_ | lit(0.0f),但这只会给我编译错误。对于我尝试的很多其他类似的东西也一样。

我真的不知道如何让这个工作。一些帮助会很棒:)

编辑:只是为了说清楚。如果我有一个包含2个元素的向量:1.0和2.0,我想生成一个如下所示的字符串:"1.0 2.0 0.0"(最后一个值应该是默认值)。

2 个答案:

答案 0 :(得分:2)

不漂亮,但工作:

#include <iostream>
#include <iterator>
#include <vector>
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include "boost/spirit/include/karma.hpp"
#include <boost/spirit/include/phoenix.hpp>

namespace karma = boost::spirit::karma;
namespace phx = boost::phoenix;
typedef std::back_insert_iterator<std::string> BackInsertIt;

int main(int argc, char* argv[]) {
  std::vector<float> input;
  input.push_back(1.0f);
  input.push_back(2.0f);

  struct TestGram: karma::grammar<BackInsertIt, std::vector<float>(),
      karma::space_type> {
    TestGram()
        : TestGram::base_type(output) {
      using namespace karma;
      floatRule = double_;

      output = repeat(phx::bind(&std::vector<float>::size, (karma::_val)))[floatRule]
            << repeat(3 - phx::bind(&std::vector<float>::size, (karma::_val)))[karma::lit("0.0")];
    }

    karma::rule<BackInsertIt, std::vector<float>(), karma::space_type> output;
    karma::rule<BackInsertIt, float(), karma::space_type> floatRule;
  } testGram;

  std::string output;
  BackInsertIt sink(output);
  karma::generate_delimited(sink, testGram, karma::space, input);

  std::cout << "Generated: " << output << std::endl;

  return 0;
}

答案 1 :(得分:1)

大警告:

显示的代码存在缺陷,可能是由于错误,也可能是由于滥用了业力属性传播(请参阅注释)。

它调用未定义的行为(可能)取消引用输入向量上的end()迭代器。

这应该有效

    floatRule = double_ | "0.0";

    output = -floatRule << -floatRule << -floatRule;

注意,floatRule应该接受optional<float>。见 Live on Coliru

最小例子:

#include "boost/spirit/include/karma.hpp"

namespace karma = boost::spirit::karma;
using It = boost::spirit::ostream_iterator;

int main( int argc, char* argv[] )
{
    const std::vector<float> input { 1.0f, 2.0f };

    using namespace karma;
    rule<It, boost::optional<float>()> floatRule      = double_ | "0.0";
    rule<It, std::vector<float>(), space_type> output = -floatRule << -floatRule << -floatRule;

    std::cout << format_delimited(output, space, input);
}

<击>