2

我有一个 Boost ublas 矩阵,我想将它的内容打印到一个文本文件中。我有以下实现,它可以工作。

#include <iostream>
using namespace std;
#include "boost\numeric\ublas\matrix.hpp"
typedef boost::numeric::ublas::matrix<float> matrix;
#include <algorithm>
#include <iterator>
#include <fstream>

int main()
{
    fill(m1.begin2(), m1.begin2() + 400 * 500, 3.3);

    ofstream dat("file.txt");
    for (auto i = 0; i < 400 ; i++) {
        for (auto j = 0; j < 500; j++) {
            dat << m1(i, j) << "\t"; // Must seperate with Tab
        }
        dat << endl; // Must write on New line
    }

我想在不使用嵌套 for 循环的情况下编写此代码。我尝试了 ostreambuf_iterator API,如下所示

copy(m1.begin2(), m1.begin2() + 500 * 400, ostream_iterator<float>(dat, "\n")); // Can only new line everything

然而,正如你所看到的,连续的元素被写在新的一行上,我无法像嵌套 for 循环那样实现排序类型。有没有办法做我在嵌套中使用 STL 算法所做的事情?

4

1 回答 1

4

对于这类小型格式化/生成器任务,我喜欢 Boost Spirit Karma。

直接方法

如果您不介意每行都有尾随制表符,这里是

Live On Coliru

matrix m1(4, 5);
std::fill(m1.data().begin(), m1.data().end(), 1);

using namespace boost::spirit::karma;
std::ofstream("file.txt") << format_delimited(columns(m1.size2()) [auto_], '\t', m1.data()) << "\n";

印刷

1.0 → 1.0 → 1.0 → 1.0 → 1.0 → 
1.0 → 1.0 → 1.0 → 1.0 → 1.0 → 
1.0 → 1.0 → 1.0 → 1.0 → 1.0 → 
1.0 → 1.0 → 1.0 → 1.0 → 1.0 → 

使用multi_array视图

const_multi_array_ref当您将适配器用作原始存储的“视图”时,您将获得更大的灵活性:

Live On Coliru

std::ofstream("file.txt") << format(auto_ % '\t' % eol, 
     boost::const_multi_array_ref<float, 2>(&*m1.data().begin(), boost::extents[4][5]));

这会产生相同的结果,但每行没有尾随制表符:

1.0 → 1.0 → 1.0 → 1.0 → 1.0
1.0 → 1.0 → 1.0 → 1.0 → 1.0
1.0 → 1.0 → 1.0 → 1.0 → 1.0
1.0 → 1.0 → 1.0 → 1.0 → 1.0

更新使用辅助函数使其更具可读性且不易出错:

template <typename T> boost::const_multi_array_ref<T, 2> make_view(boost::numeric::ublas::matrix<T> const& m) {
    return  boost::const_multi_array_ref<T,2> (
            &*m.data().begin(),
            boost::extents[m.size1()][m.size2()]
        );
}

所以它变得只是

Live On Coliru

std::cout << format(auto_ % '\t' % eol, make_view(m1)) << "\n";

在我看来,这非常优雅

注意当然,这些假设是行优先布局。

于 2015-03-27T21:40:45.663 回答