将矢量创建的Matlab代码翻译成C ++

时间:2018-02-22 15:36:05

标签: c++ matlab vector colon

我有这个Matlab代码:

[arr1 arr2 arr3] = fReadFileBin(filename));

功能主体是:

function [Result1 , Result2 , Result3 ] = fReadFileBin(filename)
    fid = fopen(filename, 'r');
    fseek(fid, 180, 0);
    PV = fread(fid, [A*3 B+2], 'float32');
    fclose(fid);

    Result1 = PV(1:3:3*A, 2:B+1);
    Result1 = Result1';
    Result2 = PV(2:3:3*A, 2:B+1);
    Result2 = Result2';
    Result3 = PV(3:3:3*A, 2:B+1);
    Result3 = Result3';

结果我有3个填充的大小为B x A的向量,并输入Double。

当我尝试用C ++重写它时:

   std::vector<std::vector<double>> result;
   result.resize(B, std::vector<double>(A));    

   std::ifstream is(filename, std::ios::binary);

   is.seekg(0, std::ios_base::end);
   std::size_t size = is.tellg();
   is.seekg(0, std::ios_base::beg);

   is.seekg( 180, 0);

   std::vector<double> PV (size / sizeof(double));
   if (!is.read((char*)&PV[0], size))
   {
       throw std::runtime_error("error reading file");
   }
   // Load the data
   is.read((char*)&PV[0], size);
   is.close();

   // std::vector<double> Result1 = 
   // std::vector<double> Result2 = 
   // std::vector<double> Result3 = 

   //R=R'
   //R[j][i] = R[i][j];  

This question对我来说确实有意义,但我还是不知道如何重写这一部分:C ++中的(1:3:3*A, 2:B+1)

注意:
-I&#39; m仅限于使用标准库(无增强,mmap等) - 我检查了关于冒号的Mathwork文档(仍然无法理解如何实现它)。

1 个答案:

答案 0 :(得分:3)

由于结果的大小是固定的,我宁愿使用std :: array:

std::array<std::vector<double>, 3> result;

不再调整大小,无论如何看起来会更简单:

//result.resize(B, std::vector<double>(A));
result.resize(3);

使用这一行,你的外部向量现在恰好包含三个向量 - 每个向量都是空的 - 就像数组方法一样。你最后选择的是,你需要明确地调整内部向量的大小。不过,我们稍后会回过头来看。

is.seekg(0, std::ios_base::end);
std::size_t size = is.tellg();  // OK, you fetched file size

//is.seekg(0, std::ios_base::beg); // using beg, you can give the desired offset directly
//is.seekg( 180, 0);  // but use the seekdir enum! So:
is.seekg(180, std::ios_base::beg);

但是,您应该检查之前至少有180个字节的文件。您应该知道这些操作中的任何可能会失败,因此您应该在每次单个操作之后或至少在组中的多个操作之后检查流的状态(因此至少在调整向量之前{ {1}})。附注:如果流已经处于失败状态,则每个后续操作也将失败,除非您PV之前的错误状态。

clear()
呃,看起来很奇怪......你从抵消180开始,所以我假设你应该在分裂之前减去;一世。 E:

std::vector<double> PV (size / sizeof(double));

如果没有此修复,下一行将始终导致抛出以下异常,因为您将读取超出文件末尾的内容(请记住,您开始从文件偏移180开始读取!):

size_t size = ...;
if(size < 180) // bad file!
{
    // throw or whatever appropriate
}
size -= 180;
// go on...

不过喜欢C ++风格的演员:

if (!is.read((char*)&PV[0], size))

你会很快发现你需要 if (!is.read(reinterpret_cast<char*>(PV.data()), size)) ,有时是合适的,但如果你考虑使用它,至少应该敲响警钟,在大多数情况下,它只是隐藏远离一些更深层次的问题,如未定义的行为。自{+ 1}}起,reinterpret_cast存在,并且比PV.data()读取更容易,但两者都是等价的。

但是,我们现在还有一个不同的问题:

虽然标准没有说明有关精度甚至格式的任何信息(“浮点类型的值表示是实现定义的。”),但很可能在您的系统上是双64位IEEE754数据类型。您确定数据是否以这种格式存储?只有这样,这个才能工作,但是,这是非常危险的,文件制作者和消费者可能会说不同的语言,很可能会得到错误的输入......

现在承认,我根本不是matlab专家,你的下列内容让我怀疑上述输入格式是否适用:

&PV[0]

最后,你已经PV = fread(fid, [A*3 B+2], 'float32'); ^^ 子句中读取了你的数据,所以放下第二条读数线,除了产生另一个失败之外什么都没有......

如果现在数据以二进制格式存储,但是人类可读格式,可以读取值,如下所示:

if

慢慢走到尽头:

std::vector<double> pv; // prefer lower camel case variable names
pv.reserve(size/sizeof(double)); // just using as a size hint;
                                 // we can't deduce number of entries
                                 // from file length exactly any more

double v;
while(is >> v)
{
    pv.push_back(v);
}
if(!v.eof())
{
    // we did not consume the whole file, so we must
    // assume that some input error occurred!
    // -> appropriate error handling (throw?)
}

注释掉;对,你不需要它们,你已经将它们放在结果向量/数组中,i。即// std::vector<double> Result1 = // std::vector<double> Result2 = // std::vector<double> Result3 = result[0]result[1] ...

根据需要调整它们(或保留)以将结果数据放入并继续。

我很抱歉,我现在并不是很清楚你的matlab计算是做什么的,而且我不打算学习matlab这个答案 - 但是,上面的提示你可能会自己相处。再进一步暗示:你不能将vector / arrays整体相互叠加或直接与标量相乘;你必须在循环中分别为每个元素执行此操作。不过,你可能会认为std::valarray是一个有趣的选择。此外,您可能会在algorithm library中找到一些有趣的内容,尤其是“数字操作”部分。如果你不相处这些话,请随意提出另一个问题...