Zapis tablicy dynamicznej 2D do pamięci i odczyt jej z pamięci

0

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ć?

0

W liście przechowuj wskaźniki do tych twoich macierzy. Jak zaimplementować macierz to chyba wiesz?

0

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".

0

Kurcze, tylko trudno coś mi sobie wyobrazić kształt tej struktury przechowującej macierze i do tego jak się odwoływać do poszczegolnej macierzy

0

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.

0

to w takim razie struktura T bedzie zdefiniowana jako {T *next i co jeszcze w srodku} ?

0

piszę w c++

0

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/

0

Tylko że nie mogę korzystać z wektorów. Taki odgórny zakaz

0

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;
};
0

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

0

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;
}

0

sry, gwiazdki zostaly, nic nie pogrubily i bardzo nieladnie to wyglada, na pastebin wkleilem

http://pastebin.com/SQ3SMSdM

0

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;
  }
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

1 użytkowników online, w tym zalogowanych: 0, gości: 1