Перевод кода Matlab создания вектора в переполнение стека

У меня есть этот код 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Икс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];

Этот вопрос имеет смысл для меня, но до сих пор не понимаю, как я могу переписать эту часть: (1:3:3*A, 2:B+1) в С ++?

Заметки:
-Я ограничен в использовании только стандартных библиотек (без boost, mmap и т. Д.).
-Я проверил документацию Mathwork о толстой кишке (и до сих пор не могу понять, как ее реализовать).

2

Решение

Поскольку результирующий размер векторов фиксирован, я бы лучше использовал 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 байтов. Вы должны знать, что любой из этих операций может произойти сбой, поэтому вы должны проверять состояние потока, либо после каждой отдельной операции, либо, по крайней мере, после нескольких из них в группе (так, по крайней мере, перед изменением размера вашего вектора PV). Примечание: если поток уже находится в состоянии сбоя, каждая последующая операция также будет неудачной, если только вы не clear() состояние ошибки раньше.

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

О, это выглядит странно для меня … Вы начинаете со смещения 180, поэтому я предполагаю, что вы должны вычесть перед делением; я. е .:

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

Без этого исправления следующая строка будет иметь всегда вылилось в следующее исключение, потому что вы прочитали бы за пределами файла (помните, вы начали читать со смещения файла 180!):

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

Предпочитаю приведения в стиле C ++, хотя:

if (!is.read(reinterpret_cast<char*>(PV.data()), size))

Вы быстро обнаружите, что вы необходимость reinterpret_castиногда уместно, но должно по крайней мере звонить в колокола тревоги, если вы планируете использовать его, в большинстве случаев это просто скрывает более глубокую проблему, такую ​​как неопределенное поведение. PV.data() существует с C ++ 11 и читает немного легче, чем &PV[0], но оба эквивалентны.

Однако теперь у нас есть еще одна проблема:

Хотя в стандарте ничего не говорится о точности или даже формате («Представление значений для типов с плавающей запятой определяется реализацией»), наиболее вероятно, что в вашей системе double является 64-битным типом данных IEEE754. Вы действительно уверены, что данные хранятся именно в этом формате? Только тогда этот Можно работать вообще, все же, это очень рискованно, производитель и потребитель файлов могут говорить на разных языках, и есть вероятность, что вы получите неправильный ввод …

Допустим, я совсем не эксперт по Matlab, но следующая ваша строка позволяет мне сильно сомневаться в том, что указанный выше формат ввода применим:

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?)
}

Дойти до конца медленно:

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

Закомментирован; да, они вам не нужны, они уже есть в результирующем векторе / массиве, т.е. е. result[0], result[1] а также result[2]

Измените их размер (или зарезервируйте) по мере необходимости, чтобы поместить данные результатов и продолжить.

Прошу прощения, но теперь я не совсем осведомлен о том, что делают ваши вычисления в Matlab, и я не собираюсь изучать Matlab для этого ответа — тем не менее, с указанными выше советами вы могли бы ладить сами. Еще один совет: вы не можете умножать векторы / массивы как друг на друга, так и непосредственно на скаляр; Вы должны сделать это для каждого элемента отдельно в циклах. Вы могли бы рассмотреть станд :: valarray интересная альтернатива, хотя. Кроме того, вы можете найти некоторые интересные вещи в библиотека алгоритмов, особенно в разделе «числовые операции». Не стесняйтесь задавать еще один вопрос, если вы не ладите с этими …

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]