Skip to content

Instantly share code, notes, and snippets.

@grayed
Last active May 15, 2024 12:06
Show Gist options
  • Save grayed/59063f95ddef3054f622ef424744dff3 to your computer and use it in GitHub Desktop.
Save grayed/59063f95ddef3054f622ef424744dff3 to your computer and use it in GitHub Desktop.
Saving and loading matricies
#include <climits>
#include <iostream>
#include <fstream>
#include <cstring>
#include <new>
using namespace std;
/*
* data access layer - взаимодействует с данными непосредственно во внешних источниках
* business logic layer - основная деятельность
* display layer - взаимодействие с пользователем, организация интерфейса
*
*/
class Matrix {
struct MatrixData {
double *nums;
size_t nrows, ncols;
int nrefs;
MatrixData(size_t nrows, size_t ncols) : nrows(nrows), ncols(ncols), nrefs(1) {
//cerr << "created MatrixData " << nrows << "x" << ncols << ": 0x" << hex << (intptr_t)this << endl;
if (ncols >= SIZE_MAX / sizeof(double))
throw out_of_range("too large columns count");
nums = static_cast<double*>(calloc(nrows, ncols * sizeof(double)));
if (!nums)
throw bad_alloc();
}
MatrixData(const MatrixData &o) : nrows(o.nrows), ncols(o.ncols), nrefs(1) {
nums = static_cast<double*>(calloc(nrows, ncols * sizeof(double)));
if (!nums)
throw bad_alloc();
memcpy(nums, o.nums, nrows * ncols * sizeof(double));
}
void addreference() {
//cerr << "addref for MatrixData: 0x" << hex << (intptr_t)this << endl;
nrefs++;
}
void dereference() {
//cerr << "dereferenced MatrixData: 0x" << hex << (intptr_t)this << endl;
if (!--nrefs) {
free(nums);
delete this;
}
}
MatrixData* detach() {
//cerr << "detached MatrixData: 0x" << hex << (intptr_t)this << endl;
MatrixData *o = new MatrixData(*this);
dereference();
return o;
}
} *d;
public:
/// https://gist.github.com/grayed/ файл matrix-file.cpp
/// 1. Реализовать методы для получения и перезаписи строки и столбца из vector<double>.
/// 2. Реализовать методы получения из Matrix новой Matrix без указанных столбцов/строк.
/// Реализовать глобальную функцию, которая получает Matrix, и записывает её в указанный файл,
/// кроме нулевых строк (содержимое которых состоит из одних нулей).
Matrix(size_t nrows, size_t ncols) : d(new MatrixData(nrows, ncols)) {}
Matrix(const Matrix &m) : d(m.d) { d->addreference(); }
~Matrix() {
//cerr << "!destructor " << (intptr_t)d->nums << "!";
d->dereference();
}
size_t rows() const { return d->nrows; }
size_t cols() const { return d->ncols; }
Matrix& operator=(const Matrix &m) {
d->dereference();
d = m.d;
d->addreference();
return *this;
}
double& operator()(size_t row, size_t col) {
//cerr << '(' << (intptr_t)this << ')';
if (row >= d->nrows)
throw out_of_range("invalid row index");
if (col >= d->ncols)
throw out_of_range("invalid column index");
if (d->nrefs > 1)
d = d->detach();
return d->nums[row * d->ncols + col];
}
double operator()(size_t row, size_t col) const {
//cerr << '[' << (intptr_t)this << ']';
if (row >= d->nrows)
throw out_of_range("invalid row");
if (col >= d->ncols)
throw out_of_range("invalid column index");
return d->nums[row * d->ncols + col];
}
Matrix operator*(double n) const {
Matrix m(d->nrows, d->ncols);
for (size_t row = 0; row < d->nrows; row++)
for (size_t col = 0; col < d->ncols; col++)
m(row, col) = (*this)(row, col) * n;
return m;
}
friend ostream& operator<<(ostream &os, const Matrix &m);
};
// UI + data
ostream& operator<<(ostream &os, const Matrix &m) {
if (dynamic_cast<ofstream*>(&os))
os << m.rows() << ' ' << m.cols() << endl;
for (size_t row = 0; row < m.rows(); row++) {
for (size_t col = 0; col < m.cols(); col++)
os << m(row, col) << ' ';
os << endl;
}
return os;
}
istream& operator>>(istream &is, Matrix &m) {
size_t nrows, ncols;
is >> nrows >> ncols;
m = Matrix(nrows, ncols);
for (size_t row = 0; row < nrows; row++) {
for (size_t col = 0; col < ncols; col++)
is >> m(row, col);
}
return is;
}
int main()
{
Matrix m1(5, 5); m1(0, 0) = 1; m1(0, 1) = 2; m1(1, 0) = 3; m1(1, 1) = -0.5;
cout << "Source matrix: " << m1 << endl;
{
ofstream ofs("foo.txt");
ofs << m1;
}
{
ifstream ifs("foo.txt");
Matrix m2(1, 1);
ifs >> m2;
cout << "Read from file: " << m2;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment