Problem taki mnie dopadł, że potrzebuję funkcji, która macierz wyrzuconą na konsolę (czytaną z pliku lub wpisaną) będzie można zapisać do pamięci a potem ją odtworzyć kiedy będzie potrzebna i na niej działać. Potrzebuję więc funkcji zapisu jej i odczytu. Żeby można było zapisać np. 5 różnych macierzy pod różnymi nazwami albo numerkami a potem wybierając dowolny numerek ją odczytać. Słyszałem takie podpowiedzi, że na listach to można zrobić ale jakoś trudno mi wyobrazić w jaki sposób to stworzyć. Jest w stanie ktoś mi coś pomóc, podpowiedzieć?
W liście przechowuj wskaźniki do tych twoich macierzy. Jak zaimplementować macierz to chyba wiesz?
Potrzebujesz jakiejś struktury, która przechowa te Twoje macierze. Jeżeli chcesz się odwoływać po numerku to lista, wektor, zwykła tablica, możesz nawet stos jak chcesz (w bibliotece standardowej C++ wszystko to jest gotowe). Jeżeli po nazwie to trzeba wykorzystać jakąś tablicę asocjacyjną (jak poprzednio).
Potem wczytujesz macierz, zapisujesz ją pod odpowiednim numerkiem i gotowe. Możesz całość opakować np. w klasę do przechowywania macierzy. Jeżeli macierze nie będą zmieniać rozmiaru to najprościej używać zwykłych "tablic dwuwymiarowych".
Kurcze, tylko trudno coś mi sobie wyobrazić kształt tej struktury przechowującej macierze i do tego jak się odwoływać do poszczegolnej macierzy
No zasadniczo będzie to "spis" wskaźników. Twoja macierz to T **macierz
i z takich elementów będzie się składać ta struktura.
to w takim razie struktura T bedzie zdefiniowana jako {T *next i co jeszcze w srodku} ?
piszę w c++
To na jaką cholerę pisać Ci jakieś listy. std::list
skoro chcesz listę. Jeżeli nie planujesz usuwać ze środka a tylko dodawać nowe wpisy na koniec std::vector
będzie odpowiedniejszy.
http://www.cplusplus.com/reference/stl/list/
http://www.cplusplus.com/reference/stl/vector/
Tylko że nie mogę korzystać z wektorów. Taki odgórny zakaz
Masz alokację tablicy trójwymiarowej, ty potrzebujesz tylko dwuwymiarowej więc możesz przyciąć najwyższy poziom:
typedef float* array;
typedef array* array2D;
typedef array2D* array3D;
array3D alloc(int x, int y, int z)
{
array3D arr = (array3D)malloc(sizeof(array2D)*z);
for(int i = 0; i < y; i++)
{
array2D sub = (array2D)malloc(sizeof(array)*y);
for(int j = 0; j < x; j++)
{
array row = (array)malloc(sizeof(float)*x);
sub[j] = row;
}
arr[i] = sub;
}
return arr;
}
A lista (powinna być z szablonami...):
struct List
{
List *next;
matrix *data;
};
trzymaj klase do macierzy kwadratowej, wlasciwie dzisiaj mialem przerabiac na klase szablonową, jakby ktoś chciał zajrzeć i zweryfikowac czy jest dobry szablon, to pozniej zuploaduje
typedef struct macierz{
float** Rekord;
int wysokoscMacierzyKwadratowej;
macierz(){
wysokoscMacierzyKwadratowej = 0;
Rekord = NULL;
}
void MacierzNowa(int wysokosc){
MacierzUsun();
wysokoscMacierzyKwadratowej = wysokosc;
Rekord = new float*[wysokoscMacierzyKwadratowej];
for(int i(0); i<wysokoscMacierzyKwadratowej; i++)
Rekord[i] = new float[wysokoscMacierzyKwadratowej];
MacierzResetuj();
}
void MacierzUsun(){
if(Rekord != NULL){
for(int i(0); i< wysokoscMacierzyKwadratowej; i++)
delete Rekord[i];
delete Rekord;
Rekord = NULL;
}}
void MacierzResetuj(){
for(int i(0) ; i < wysokoscMacierzyKwadratowej ; i++ )
for(int j(0) ; j < wysokoscMacierzyKwadratowej ; j++)
Rekord[i][j] = 0;
}
void MacierzWyswietl(int x, int y){
nbox(x,y,sx_okna,sy_okna);
move(y,x);
for(int i(0) ; i <= wysokoscMacierzyKwadratowej ; i++ )
{
for(int j(0) ; j <= wysokoscMacierzyKwadratowej ; j++)
{
if(j == 0){
if(i == 0)
nwrite(" ", colors, 5, getx(), gety());
nwrite(" ", colors, 5, getx(), gety());
ndwrite(j);
}else
if(i == 0){
if(j > 0)
{
nwrite(" ", colors, 5, getx(), gety());
ndwrite(i);
}
}
if(i > 0 && j > 0){
nwrite(" ", colors, 5, getx(), gety());
ndwrite(Rekord[i][j], 1);
}
}
move(gety()+1, x);
}
}
void MacierzZapisz(float wartosc, int wiersz, int kolumna){
Rekord[wiersz][kolumna] = wartosc;
}
float SumaWiersza(int wiersz){
float suma(0);
for(int i(0); i < wysokoscMacierzyKwadratowej; i++)
suma+=Rekord[wiersz][i];
return suma;
}
float SumaMacierzy(){
float suma(0);
for(int i(0), i < wysokoscMacierzyKwadratowej; i++)
suma+=SumaWiersza(i);
return suma;
}
};
a no i to wersja z curses.h , przerob na iostream.h ,rozszerz o obliczanie ofsetu, zapis/odczyt w locie i obuduj w klasie dynamicznie przechowujacej jakies zdublowane wskazniki do macierzy jakbys chcial zwiekszyc w trakcie programu
peace
ChS
Albo zmienilem od razu, pogrubilem zmiany z floatow' na typy T, ktos przeleci z gory do dolu i napisze czy wszystko ok?
ucze sie od wczoraj szablonow , dzieki z gory
ChS
template<class T>
typedef struct macierz{
**T ** Rekord;**
int wysokoscMacierzyKwadratowej;
void MacierzNowa(int wysokosc){
MacierzUsun();
wysokoscMacierzyKwadratowej = wysokosc;
Rekord = **new T ***[wysokoscMacierzyKwadratowej];
for(int i(0); i<wysokoscMacierzyKwadratowej; i++)
Rekord[i] = **new T[wysokoscMacierzyKwadratowej];**
MacierzResetuj();
}
void MacierzUsun(){
if(Rekord != NULL){
for(int i(0); i< wysokoscMacierzyKwadratowej; i++)
delete Rekord[i];
delete Rekord;
Rekord = NULL;
}}
void MacierzResetuj(){
for(int i(0) ; i < wysokoscMacierzyKwadratowej ; i++ )
for(int j(0) ; j < wysokoscMacierzyKwadratowej ; j++)
Rekord[i][j] = 0;
}
void MacierzZapisz(**T wartosc**, int wiersz, int kolumna){
Rekord[wiersz][kolumna] = wartosc;
}
**T** SumaWiersza(int wiersz){
**T** suma(0);
for(int i(0); i < wysokoscMacierzyKwadratowej; i++)
suma+=Rekord[wiersz][i];
return suma;
}
** T** SumaMacierzy(){
**T** suma(0);
for(int i(0), i < wysokoscMacierzyKwadratowej; i++)
suma+=SumaWiersza(i);
return suma;
}
};
template<class T>::macierz(){
wysokoscMacierzyKwadratowej = 0;
Rekord = NULL;
}
sry, gwiazdki zostaly, nic nie pogrubily i bardzo nieladnie to wyglada, na pastebin wkleilem
Klasa obsługująca tablicę dwuwymiarową nie musi mieć dwuwymiarowej wewnętrznej reprezentacji:
#include <iostream>
#include <sstream>
#include <iomanip>
using namespace std;
template<class T> class matrix
{
private:
unsigned size;
T *tb;
public:
matrix(unsigned size=0,const T &V=T()):size(size),tb(size?new T[(size*size)]:0)
{
for(unsigned i=0,m=size*size;i<m;++i) tb[i]=V;
}
~matrix() { if(size) delete[] tb; }
unsigned Size()const { return size; }
operator unsigned()const { return size; }
T &operator()(unsigned y,unsigned x) { return at(y,x); }
const T &operator()(unsigned y,unsigned x)const { return at(y,x); }
T *operator[](unsigned r) { return tb+r*size; }
const T *operator[](unsigned r)const { return tb+r*size; }
void Resize(unsigned newsize,const T &V=T())
{
if(size==newsize) return;
T *newtb=newsize?new T[(newsize*newsize)]:0;
unsigned minsize=size<newsize?size:newsize;
if(size)
{
for(unsigned y=0;y<minsize;++y)
{
for(unsigned x=0;x<minsize;++x)
{
newtb[y*newsize+x]=tb[y*size+x];
}
}
delete[] tb;
}
tb=newtb;
size=newsize;
for(unsigned y=0;y<newsize;++y)
{
for(unsigned x=0;x<newsize;++x)
{
if((x>=minsize)||(y>=minsize)) newtb[y*newsize+x]=V;
}
}
}
class ExceptionOverRange {};
T &at(unsigned y,unsigned x)
{
if((x>=size)||(y>=size)) throw ExceptionOverRange();
return tb[y*size+x];
}
const T &at(unsigned y,unsigned x)const
{
if((x>=size)||(y>=size)) throw ExceptionOverRange();
return tb[y*size+x];
}
T SumRow(unsigned r)
{
T suma=T();
for(unsigned x=r*size,X=x+size;x<X;++x) suma+=tb[x];
return suma;
}
T SumCol(unsigned c)
{
T suma=T();
for(unsigned y=c,Y=y+size*size;y<Y;++y) suma+=tb[y];
return suma;
}
T Sum(unsigned c)
{
T suma=T();
for(unsigned i=0,m=size*size;i<m;++i) suma+=tb[i];
return suma;
}
ostream &prn(ostream &s)const
{
unsigned w=4;
for(unsigned i=0,m=size*size;i<m;++i)
{
ostringstream ss;
ss.copyfmt(s);
ss<<tb[i];
unsigned ww=ss.str().length()+1;
if(w<ww) w=ww;
}
for(unsigned y=0,p=0;y<size;++y,cout<<endl)
{
for(unsigned x=0;x<size;++x,++p)
{
s<<setw(w)<<tb[p];
}
}
return s;
}
};
template<class T> ostream &operator<<(ostream &s,const matrix<T> &m) { return m.prn(s); }
int main()
{
matrix<double> M(2);
cout.setf(ios::fixed);
cout.precision(1);
cout<<"rozmiar "<<(unsigned)M<<'x'<<(unsigned)M<<endl;
cout<<"M:"<<endl<<M<<endl<<endl;
M.Resize(3,3.3);
cout<<"nowy rozmiar "<<(unsigned)M<<'x'<<(unsigned)M<<endl;
cout<<"M:"<<endl<<M<<endl<<endl;
M.Resize(4);
cout<<"nowy rozmiar "<<(unsigned)M<<'x'<<(unsigned)M<<endl;
cout<<"M:"<<endl<<M<<endl<<endl;
M.Resize(5,5.5);
cout<<"nowy rozmiar "<<M.Size()<<'x'<<M.Size()<<endl;
cout<<"M:"<<endl<<M<<endl<<endl;
cout<<"M(1,1)="<<M(1,1)<<endl;
cout<<"M[1][1]="<<M[1][1]<<endl;
cout<<"M(2,2)="<<M(2,2)<<endl;
cout<<"M[2][2]="<<M[2][2]<<endl;
cout<<"M(3,3)="<<M(3,3)<<endl;
cout<<"M[3][3]="<<M[3][3]<<endl;
cout<<"M(4,4)="<<M(4,4)<<endl;
cout<<"M[4][4]="<<M[4][4]<<endl;
if(M)
{
cout<<"Rozmiar nie zerowy, zerujemy"<<endl;
M.Resize(0);
if(!M) cout<<"Rozmiar zerowy"<<endl;
}
cin.sync();
cin.get();
return 0;
}
@_13th_Dragon
rozumiem technicznie ale nie wszystko, nie korzystam jeszcze z wyjątków i nie za bardzo kumam o co chodzi w konstruktorze, dales tam przypisanie w petli do aktualnego adresu(zakladajac s > 0) referencji na konstruktor domyslny, parametru aktualnego.
Taka konstrukcja daje mozliwosc inicjowania pamieci macierzy przez wskaznik domyslnymi wartosciami obiektu, dobrze rozumuje ? A co z typami wbudowanymi? Kompilator wtedy to przepuszcza(olewa) czy instrukcja np. int() ma jakas wartosc?
wlasnie taki skill programowania musze ogarnac.
dzieki za udostepnienie kodu, przyda sie do nauki.
pozdrawiam
ChS