【问题标题】:C++ better way to parse values into a vectorC++ 将值解析为向量的更好方法
【发布时间】:2012-07-13 19:30:32
【问题描述】:

我正在解析来自“C-only”接口的文本数组,其中每个字符串可能具有任意数量的值,这些值可能单独被“istream::operator >>()”解析。

例如,其中一个解析器用于自定义 IPv4 类:

std::istream &  operator >>( std::istream& stream, IPv4 &var )

实现非常明显。

现在假设输入如下:

const char *string_array[] =
{
    "192.168.0.1, 192.168.0.32,    192.168.0.40",
    "169.254.3.18, 169.254.3.19, 169.254.3.20, 169.254.3.21",
    "10.0.92.100",
    "10.0.0.101,    10.0.0.102,    10.0.0.103   ,  10.0.0.104 , 10.0.0.110  ",
};

我想找到一种优雅的方式将所有解析的值放入一个数组中,以便我可以将其发送到“仅限 C”的函数。

天真的方法是首先用stringstream 包含所有字符串(const char *),然后用我的operator >> 循环这个流。

        std::stringstream   ss;
        IPv4 ip;
        std::vector< IPv4 > ip_vector;

         for ( int c = 0; c < count; ++c )
                        ss << string_array[ c ] << ", ";

         while ( ss.good( ) )
         {
                        ss >> ip;
                    ip_vector.push_back( ip );
         }

对我来说似乎不是那么明智,但我不知道如何让它变得更聪明。

另请注意:Boost 不是此解决方案的选项。

【问题讨论】:

  • 你确定你描述的方法会奏效吗?您正在将所有字符串写入没有分隔符的流中,因此您最终可能会得到如下片段:192.168.0.40169.254.3.18.
  • 是的,你是对的。我会修正我的例子,谢谢。

标签: c++ parsing stl stream


【解决方案1】:

您可以使用内置的 STL 功能来代替编写自己的循环。

copy(string_array, string_array + count,
     ostream_iterator<const char *>(ss, ", "));
copy(istream_iterator<IPv4>(ss), istream_iterator<IPv4>(),
     back_inserter(ip_vector));

【讨论】:

  • std::begin(string_array)std::end(string_array) 也应该用作迭代器限制。
  • @rhalbersma:如果你有 C++11,是的。
【解决方案2】:

std::copy()std::back_inserter 肯定是出路。 我会坚持,虽然for循环遍历字符串而不是连接@ehemient所建议的stringstream中的所有内容:

std::vector< IPv4 > ip_vector;

for ( unsigned c = 0; c < count; ++c )
{
    std::stringstream   ss( string_array[ c ] );

    std::copy( std::istream_iterator< IPv4 >( ss ), std::istream_iterator< IPv4 >( ),
                std::back_inserter( ip_vector ) );
}

这样你就清楚你正在转换所有的字符串。 您还必须构造 3 个 std::stringstream 对象,但不必为连接字符串重新定位内存。

【讨论】:

    【解决方案3】:

    我认为连接它是没用的:只需“加入”循环,就像:

    istream &skipblanks(istream &s) {
      char c;
      while ((c = s.peek()) == ' ' || c == ',')
       s.get();
      return s;
    }
    
    ...
    std::vector< IPv4 > ip_vector;
    for ( int c = 0; c < count; ++c ) {
        istringstream ss(string_array[ c ]);
        while (ss) {
            IPv4 ip;
            if (skipblanks(ss) >> ip)
                ip_vector.push_back( ip );
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2022-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-20
      • 2019-10-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多