Strona 2 z 3 PierwszyPierwszy 123 OstatniOstatni
Pokaż wyniki 11 do 20 z 28

Temat: Wczytywanie danych z pliku do wektora

  1. #11

    Domyślnie

    To moze inaczej. Podaje kod do oceny, bo czuje ze troche przekobinowalam.

    Kod:
    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <string>
    using namespace std;
    
    void wczytaj(const char *tekst, double **&tab, int &l_wierszy,int &l_kolumn);
    void wypisz(double **&tab, int &l_wier_tab,int &l_kol_tab);
    void zwolnij_pamiec(double **tab,int &l_wier_tab);
    int main()
    { double **tablica;
      int wiersze, kolumny;
    
      wczytaj("dane.txt", tablica, wiersze, kolumny);
      wypisz(tablica, wiersze, kolumny);
      zwolnij_pamiec(tablica, wiersze);
    }
    
    
          void wczytaj(const char *tekst, double **&tab,int &l_wier_tab,int &l_kol_tab)
          {
             int l_wierszy=1;
             int l_kolumn=2;
    
       //Dynamiczna alokacja pamieci wiersza, ktory posiada wymiary macierzy
            int **wymiar = new int *[l_wierszy];
            for (int i=0; i<l_wierszy; i++) wymiar[i] = new int [l_kolumn];
    
    
            ifstream plik(tekst);
            if(!plik)
            {
                    cerr << "Brak pliku.";
            }
    
            for (int i=0; i<l_wierszy; i++)
            for (int j=0; j<l_kolumn; j++)
                                                                   
     }
    
    
            l_wier_tab = wymiar[0][0]+1;        //liczba wierszy tablicy, do ktorej wczytujemy dane DODAJEMY 1, bo wczytujemy od piwerwszego wiersza
            l_kol_tab = wymiar[0][1];         //liczba kolumn tablicy
    
    // Dynamiczna alokacja pamieci!!!
    
              tab = new double *[l_wier_tab];
             for (int i=0; i<l_wier_tab; i++) tab[i] = new double [l_kol_tab];
    
             for(int i = 1; i < l_wier_tab; i++)
             for(int j = 0; j < l_kol_tab; j++)
             {
                plik >> tab[i][j];
             }
    
             plik.close();
    
       }
          
           void wypisz(double **&tab, int &l_wier_tab,int &l_kol_tab)
            {
              for (int i=1; i<l_wier_tab; i++)
              for (int j=0; j<l_kol_tab; j++)
              {
                  cout<<"tab["<<i<<"]["<<j<<"]="<<tab[i][j]<<endl;
              }
            }
    
            void zwolnij_pamiec(double **tab,int &l_wier_tab)
            {
              for(int i=0;i<l_wier_tab;i++) delete [] tab[i];
              delete []tab;
            }
    Bede wdzieczna za wszlkie slowa krytyki.

  2. #12

    Post

    Popracuj nad estetyką kodu

    Funkcja wczytaj jest mocno przekombinowana i trudno stwierdzić czy będzie działała prawidłowo. Dobrze też żeby zwracała czy wczytywanie się powiodło.
    Kod:
    bool wczytaj(const char* nazwa_pliku, double** &dane, int &wiersze, int &kolumny)
    {
    	ifstream plik(nazwa_pliku);
    	if(!plik)
    	{
    		cerr << "Nie udało się otworzyć pliku " << nazwa_pliku << endl;
    		return false; //jeśli nie udało się otworzyć pliku to zwraczasz niepowodzenie
    	}
    
    	plik >> wiersze >> kolumny; //pobranie rozmiarów macierzy
    
    	dane = new double*[wiersze];
    	for(int i = 0; i < wiersze; ++i)
    		dane[i] = new double[kolumny]; //alokacja pamięci
    
    	for(int i = 0; i < wiersze; ++i)
    		for(int j = 0; j < kolumny; ++j)
    			plik >> dane[i][j];      //pobieranie danych
    
    	return true; //operacja zakończona sukcesem
    }
    Poza tym zamiast szatkować pamięć, możesz zapisywać wszystkie wiersze w jednym kawałku pamięci, wtedy nie potrzebujesz dodatkowej funkcji do zwalniania, tylko możesz użyć po prostu delete[]
    Kod:
    bool wczytaj(const char* nazwa_pliku, double* &dane, int &wiersze, int &kolumny)
    {
    	/*...*/
    	dane = new double[wiersze*kolumny]; //alokacja pamięci
    
    	for(int i = 0; i < wiersze; ++i)
    		for(int j = 0; j < kolumny; ++j)
    			plik >> dane[i * kolumny + j]; //pobieranie danych
    
    	return true; //operacja zakończona sukcesem
    }
    Kod pobierający dane można wtedy trochę uprościć
    Kod:
    	for(int i = 0; i < wiersze*kolumny; ++i)
    		plik >> dane[i];
    Zamiast ręcznego zarządzania pamiecią możesz użyć vectora, wtedy nie musisz niczego zwalniać, bo vector zrobi to za ciebie gdy wyjdziesz poza zakres jego istnienia
    Kod:
    bool wczytaj(const char* nazwa_pliku, vector<double> &dane, int &wiersze, int &kolumny)
    {
    	/*...*/
    	dane.resize(wiersze*kolumny); //zmiana rozmiaru wektora
    
    	for(int i = 0; i < wiersze*kolumny; ++i)
    		plik >> dane[i]; //pobieranie danych
    
    	return true; //operacja zakończona sukcesem
    }
    Przydałoby się też oprócz sprawdzania czy udało sie otworzyć plik, także sprawdzać czy udało się odczytać dane z pliku (plik może być uszkodzony albo coś)
    Kod:
    bool wczytaj(const char* nazwa_pliku, vector<double> &dane, int &wiersze, int &kolumny)
    {
    	ifstream plik(nazwa_pliku);
    	if(!plik)
    	{
    		cerr << "Nie udało się otworzyć pliku " << nazwa_pliku << endl;
    		return false;
    	}
    
    	plik >> wiersze >> kolumny;
    	if(!plik)
    	{
    		cerr << "Nie udało się pobrać rozmiarów macierzy" << endl;
    		return false;
    	}
    
    	dane.resize(wiersze*kolumny);
    
    	for(int i = 0; i < wiersze*kolumny; ++i)
    		plik >> dane[i];
    	if(!plik)
    	{
    		cerr << "Nie udało się pobrać wszystkich danych" << endl;
    		dane.clear(); //Przy ręcznym zarządzaniu pamięcią musisz zwolnić zaalokowaną pamięć. W przypadku vectora nie jest to konieczne ale nie zaszkodzi.
    		return false;
    	}
    
    	return true;
    }
    istream (a więc także ifstream, który dziedziczy po istream) staje się fałszywy gdy ostatni odczyt nie powiódł się.
    Cytat Napisał Gosik Zobacz post
    Bede wdzieczna za wszlkie slowa krytyki.
    Mam nadzieję, że nie piszesz słabego kodu tylko po to by Cię krytykowano
    Niniejszy post przedstawia opinie autora w dniu dzisiejszym, na datę jego publikacji. Nie mogą być one wykorzystane przeciwko niemu w dniu jutrzejszym, ani innym następującym po nim dniu. Autor zastrzega sobie prawo do zmiany poglądów bez podawania przyczyn.

  3. #13

    Domyślnie

    Mam nadzieję, że nie piszesz słabego kodu tylko po to by Cię krytykowano
    Nie. Jednakze cenne uwgi fachowcow zawsze mi sie przydaja.

    Troche zmienilam kod i storzylam klase, ktora wczytuje dane z pliku oraz klase, ktora wykonuje dzialania.

    Kod:
    #include<iostream>
    #include<fstream>
    using namespace std;
    
    class Wczytywanie
    {
            private:
                    const char *nazwa_pliku;
                    double *dane;
                    int wiersze;
                    int kolumny;
            public:
                    Wczytywanie(const char *nz){ nazwa_pliku = nz;}
                    bool wczytaj();
                    void wyswietl();
    };
    
    
    bool Wczytywanie::wczytaj()
    {
            ifstream plik(nazwa_pliku);
            if(!plik)
            {
                    cerr << "Nie udało się otworzyć pliku " << nazwa_pliku << endl;
                    return false; //jeśli nie udało się otworzyć pliku to zwraczasz niepowodzenie
            }
    
            plik >> wiersze >> kolumny; //pobranie rozmiarów macierzy
    
            dane = new double[wiersze*kolumny]; //alokacja pamięci
    
            for(int i = 0; i < wiersze; ++i)
                    for(int j = 0; j < kolumny; ++j)
                            plik >> dane[i * kolumny + j]; //pobieranie danych
    
    //      delete[] dane;
    
            return true; //operacja zakończona sukcesem
    }
    
    void Wczytywanie::wyswietl()
    {
             //...
    }
    
    class Dzialania
    {
                    private:
                            Wczytywanie *wek;
    
                    public:
                            void mnozenie();
    };
    
    void Dzialania:: mnozenie(Dzialania *wek);
    { 
    //od tego momentu kod jest 'zczapki'
            nowa_tab = new [wiersze*kolumny];
    
            for (int i = 0; i < wiersze; ++i)
                    for (int j =0; j < kolumny; ++j)
                            {
                                    nowa_tab[i * kolumny +j]+= wek1[i * kolumny +j]*wek2[i * kolumny +j];
                            }
    }
    int main()
    {
      Wczytywanie nr1("wyniki.txt");
      Wczytywanie nr1("wyniki2.txt");
            nr1.wczytaj();
            nr1.wyswietl();
    }
    Jak widac napotkalam problem. Mianowicie chcialabym wykorzystac obiekty z klasy Wczytywanie w klasie Dzialania. Stworzylam wskaznik do adresu obiektow, ale problem jest taki, ze na etapie mnozenia ich nie znam.
    Jak mozna z tego wybrnac?

    Chcialabym rozniez zapytac, w ktorym momencie programu powinno nastepowac zwalnianie pamieci przy uzyciu delete[]?
    Czy powinnam stworzyc osobna funkcje i na samym koncu ja uzyc?
    Ostatnio edytowane przez Gosik : 03-29-2013 - 20:35

  4. #14

    Post

    Cytat Napisał Gosik Zobacz post
    Mianowicie chcialabym wykorzystac obiekty z klasy Wczytywanie w klasie Dzialania.
    A możesz zdradzić co chcesz z nimi zrobić? Bo widzę, że Wczytywanie potrafi tylko wczytywać i wyświetlać. Podobny temat o dwóch klasach: http://hack.pl/forum/c-c/10624-%5Bc-...nej-klasy.html.
    Cytat Napisał Gosik Zobacz post
    Stworzylam wskaznik do adresu obiektow, ale problem jest taki, ze na etapie mnozenia ich nie znam.
    Rozumiem, że chodzi Ci o pole wek klasy Dzialania, będące wskaźnikiem na Wczytywanie? Możesz np. osobno tworzyć obiekt Wczytywanie i przekazywać wskaźnik do niego konstruktorowi Dzialania, który zapisze go do pola wek. Opcjonalnie możesz tworzyć potrzebny obiekt Wczytywanie w konstruktorze Dzialania.
    Cytat Napisał Gosik Zobacz post
    Chcialabym rozniez zapytac, w ktorym momencie programu powinno nastepowac zwalnianie pamieci przy uzyciu delete[]?
    Wtedy gdy ta pamięć nie będzie już potrzebna. Jeśli obiekt zarządza pamiecią to możesz ją zwalniać w jego destruktorze, tylko że wtedy przyda się jeszcze odpowiedni konstruktor kopiujący i operator przypisania, do poczytania [C++] destruktor klasy i core dumped

    Cytat Napisał Gosik Zobacz post
    Kod:
    void Dzialania:: mnozenie(Dzialania *wek);
    Nie masz w klasie Dzialania metody o takiej sygnaturze (oprócz nazwy liczą się też typy przyjmowanych argumentów).
    Ostatnio edytowane przez Rolek : 03-30-2013 - 12:34
    Niniejszy post przedstawia opinie autora w dniu dzisiejszym, na datę jego publikacji. Nie mogą być one wykorzystane przeciwko niemu w dniu jutrzejszym, ani innym następującym po nim dniu. Autor zastrzega sobie prawo do zmiany poglądów bez podawania przyczyn.

  5. #15

    Domyślnie

    Chcialabym stworzyc obiekt macierz1, macierz2 zawierajace dane z roznych plikow oraz klase Dzialania, ktora bedzie wykonywala dzialania.
    Czy jest to bez sensu pomysl?
    W literaturze znajduje tylko przyklady z lapa (masz kalse zarowka i lamapa) albo z danymi osobowymi. Bez wiekszego doswiadczenia z programowaniem obiektowym nie potrafi wymyslec konkretnego przykladu...
    Czy lepiej bedzie te dzialania stworzyc jako metody klasy Macierz? Czy moze jako funkcje zaprzyjaznione (czytalam o tch funkcjach ale nie wiem jakie maja zastosowanie w praktyce)?
    A możesz zdradzić co chcesz z nimi zrobić? Bo widzę, że Wczytywanie potrafi tylko wczytywać i wyświetlać. Podobny temat o dwóch klasach: http://hack.pl/forum/c-c/10624-%5Bc-...nej-klasy.html.
    Szczerze, to zbytnio tego nie rozumiem. Dlaczego mam tu stworzyc konstruktor kopjujacy? Chyba wynika to z faktu, ze ich nie rozumiem. Wiem, ze konstruktor kopjujacy sluzy do skonstruowania obiektu, ktory jest kopia innnego juz istniejacego obiektu klasy. Na tym moja wiedza sie konczy, nie wiem jakie jest w praktyce ich zastosowanie.

    Oto co udalo mi sie wydumac:
    Kod:
    class Macierz
    {
            private:
                    const char *nazwa_pliku;
                    double *dane;
                    int wiersze;
                    int kolumny;
            public:
                    Macierz(const char *nz){ nazwa_pliku = nz;}
                    Macierz(Macierz &wzor); //konstruktor kopijacy
                    ~Macierz(); //destruktor
                    bool wczytaj();
                    void wyswietl();
    
    };
    
    
    bool Macierz::wczytaj()
    {
            ifstream plik(nazwa_pliku);
            if(!plik)
            {
                    cerr << "Nie udało się otworzyć pliku " << nazwa_pliku << endl;
                    return false; //jeśli nie udało się otworzyć pliku to zwraczasz niepowodzenie
            }
    
            plik >> wiersze >> kolumny; //pobranie rozmiarów macierzy
    
            dane = new double[wiersze*kolumny]; //alokacja pamięci
    
            for(int i = 0; i < wiersze; ++i)
                    for(int j = 0; j < kolumny; ++j)
                            plik >> dane[i * kolumny + j]; //pobieranie danych
    
    
            return true; //operacja zakończona sukcesem
    /konstruktor kopjujacy:
    Macierz::Macierz(Macierz &wzor)
    {
            nazwa_pliku=wzor.nazwa_pliku;
    }
    
    //destruktor
    Macierz::~Macierz()
    {
             for(int i = 0; i < wiersze; ++ i)
            {
                    delete []dane[i];
            }
                    delete []dane;
    }
    
    
    void Macierz::wyswietl()
    {/...}
    NIestety tak to nie dziala.

  6. #16

    Post

    Jeśli nie rozumiesz pewnych mechanizmów to powinnaś poćwiczyć najpierw na prostrzych przykładach.
    Przykładowa klasa, zawiera nazwę (pole m_name) oraz alokuje dodatkową pamięć na jednego inta (trochę bez sensu trymać taką małą ilość danych osobno ale to tylko przykład).
    Alokacja następuje w konstruktorze a zwolnienie w destruktorze. Konstruktor kopiujący alokuje dla kopii osobną pamięć, więc jeśli któryś z obiektów zostanie zniszczony to zwolni tylko swoją pamięć a drugi będzie nadal posiadać swoją.
    Kod:
    #include <iostream>
    #include <string>
    using namespace std;
    
    class Foo
    {
    	int* m_pX;
    public:
    	string m_name;
    	int getX() const { return *m_pX; }
    	void setX(int x) { *m_pX = x; }
    	Foo(string name, int x) : m_name(name), m_pX(new int)
    	{
    		cout << m_name << " Konstruktor zwykly. x=" << x << endl;
    		setX(x);
    	}
    	Foo(const Foo& o) : m_name(o.m_name + "_bis"), m_pX(new int) // konstruktor kopiujący alokuje nową pamięć
    	{
    		cout << m_name << " = " << o.m_name << " Konstruktor kopiujacy. x=" << o.getX() << endl;
    		setX(o.getX());
    	}
    	~Foo()
    	{
    		cout << m_name << " Destruktor. ox=" << getX() << endl;
    		delete m_pX; // zwolnienie pamięci,
    		//gdyby dwa obiekty posiadały ten sam wskaźnik i jeden z tych obiektów zostałby zniszczony to zwalniłby wspólną pamieć i drugi obiekt przestałby działać prawidłowo
    	}
    	Foo& operator = (const Foo& r)
    	{
    		cout << m_name << " = " << r.m_name << " Operator przypisania. ox=" << getX() << " x=" << r.getX() << endl;
    		setX(r.getX());
    		// m_name pozostaje bez zmian, jak chcesz lepiej zobrazować przepływ danych to możesz dodać zmienianie m_name
    		return *this;
    	}
    };
    
    Foo operator + (const Foo& l, const Foo& r) // operator dodawania jako funkcja globalna
    {
    	cout << "Dodawanie: " << l.m_name << ".x=" << l.getX() << " + " << r.m_name << ".x=" << r.getX() << " : ";
    	return Foo(string("(") + l.m_name + "+" + r.m_name + ")", l.getX() + r.getX());
    }
    
    Foo bar(string n, int x)
    {
    	struct cmt_t { cmt_t() { cout << "---funkcja bar()\n"; } ~cmt_t() { cout << "---koniec funkcji bar()\n"; } } cmt;
    	Foo a(n, x);
    	Foo b = a + a;
    	cout << "zmiana nazwy " << b.m_name;
    	b.m_name = n + "2";
    	cout << " na " << b.m_name << endl;
    	return b;
    }
    
    int main()
    {
    	//możesz dopisać własne testy
    	Foo A("A", 5), B("B", 10);
    	Foo C = A; // C będzie miał m_name="A_bis"
    	cout << " A.x=" << A.getX() << " C.x=" << C.getX() << endl;
    	cout << "zmiana A.x na 25" << endl;
    	A.setX(25);
    	cout << " A.x=" << A.getX() << " C.x=" << C.getX() << endl;
    	A = B;
    	B = bar("NB", 40);
    	Foo D = bar("D", 100);
    	B = B + D;
    	D = C + A;
    	Foo E = A + B;
    	cout << "\tA:" << A.m_name << ".x=" << A.getX()
    		<< " B:" << B.m_name << ".x=" << B.getX()
    		<< " C:" << C.m_name << ".x=" << C.getX()
    		<< " D:" << D.m_name << ".x=" << D.getX()
    		<< " E:" << E.m_name << ".x=" << E.getX() << endl;
    	return 0;
    }
    Dodatkowe bloki pamięci są zawsze tej samej wielkości, więc operator przypisania (operator=) nie musi realokować tego dodatkowego bloku, gdyby były różnej wielkości konieczna byłaby realokacja.
    Dobrze też dodać sprawdzenie czy nie próbujesz przypisać obiektu do samego siebie aby uniknąć niepotrzebnego kopiowania dużej ilości danych.
    Kod:
    Foo& operator = (const Foo& r)
    {
    	if(this == &r)
    		return *this;
    	/* realokacja, kopiowanie, itp. */
    	return *this;
    }
    Jeśli chcesz używać dodatkowej pamięci (czy innego zasobu) wspólnie przez kilka obiektów to nie możesz po prostu zwalniać w destruktorze, bo po zniszczeniu jednego obiektu pozostałe przestałyby działać. Ale powinnaś zaplanować kiedy zwalniać, żeby uniknąć wycieku zasobów, np. grupa obiektów należy do wspólnego właściciela (w najprostrzym przypadku może być to jakiś obiekt globalny lub funkcja main) i ten właściciel zarządza też wspólnym zasobem (np. dodatkową pamięcią).

    Jeśli nie chcesz by obiekty były kopiowane i/lub przypisywane to możesz umieścić puste deklaracje w sekcji prywatnej. Ma to sens w przypadku obiektów reprezentujących np. subsystemy, dojścia do urządzeń, itp.

    W przypadku obiektów matematycznych np. macierzy, do wykonywania działań stosuje się raczej zestaw funkcji i/lub operatorów.
    Ostatnio edytowane przez Rolek : 04-01-2013 - 13:45
    Niniejszy post przedstawia opinie autora w dniu dzisiejszym, na datę jego publikacji. Nie mogą być one wykorzystane przeciwko niemu w dniu jutrzejszym, ani innym następującym po nim dniu. Autor zastrzega sobie prawo do zmiany poglądów bez podawania przyczyn.

  7. #17

    Domyślnie

    Chyba zaczynam powoli czaic temat.

    Poprawilam kod:
    Kod:
    //konstruktor kopjujacy:
    Macierz::Macierz(Macierz &wzor)
    {
            nazwa_pliku = wzor.nazwa_pliku;
    
            dane = new double[wiersze*kolumny]; //alokacja pamieci dla wektora
    
            for(int i = 0; i < wiersze; ++i)
                    for(int j = 0; j < kolumny; ++j)
                            dane[i * kolumny +j] = wzor.dane[i * kolumny + j]; //kopiowanie danych z tablicy
    
    }
    
    //destruktor
    Macierz::~Macierz()
    {
            delete []dane;
    }
    
    //Przeladowanie operatora przypisania:
    Macierz &Macierz:: operator=(const Macierz &wzor)
    {
            if(&wzor == this) return *this;
            delete []dane;
    
            nazwa_pliku = wzor.nazwa_pliku;
    
            dane = new double[wiersze*kolumny]; //alokacja pamieci dla wektora
    
            for(int i = 0; i < wiersze; ++i)
                    for(int j = 0; j < kolumny; ++j)
                            dane[i * kolumny +j] = wzor.dane[i * kolumny + j]; //kopiowanie danych z tablicy
    
    cout<<"Tutaj pracuje operator przypisania \n";
    
            return *this;
    }
    
    //Tworze operator dodawania:
    Macierz &Macierz:: operator+ (const Macierz &wzor)
    {
            Macierz *suma;
            suma = new Macierz(nazwa_pliku);
    
            for(int i = 0; i < wiersze; ++i)
                    for(int j = 0; j < kolumny; ++j)
                            suma.Macierz[i * kolumny +j] = wzor.dane[i * kolumny +j] + dane[i * kolumny + j];
            return *suma;
    }
    Mam jeszcze problem z operatorem dodawania.
    Chcialabym dodac do siebie dwie macierze. W tym celu tworze dynamiczna alokacje pamieci:
    Kod:
    suma = new Macierz(nazwa_pliku);
    Tu pojawia sie problem, bo moj konstruktor zawiera tylko nazwe pliku. Niestety nie mam pomyslu jak wyciagnac liczbe wierszy i kolumn do alokacji pamieci.

  8. #18

    Post

    Cytat Napisał Gosik Zobacz post
    Kod:
    Macierz::Macierz(Macierz &wzor)
    {
            nazwa_pliku = wzor.nazwa_pliku;
    
            dane = new double[wiersze*kolumny]; //alokacja pamieci dla wektora
    
            for(int i = 0; i < wiersze; ++i)
                    for(int j = 0; j < kolumny; ++j)
                            dane[i * kolumny +j] = wzor.dane[i * kolumny + j]; //kopiowanie danych z tablicy
    
    }
    1. Właściwie po co Ci w macierzy nazwa pliku, z którego wczytałaś dane?
    2. Nie zauważyłem, abyś kopiowała wartości pól wiersze i kolumny (podobnie w operatorze przypisania).

    Cytat Napisał Gosik Zobacz post
    Kod:
    Macierz &Macierz:: operator+ (const Macierz &wzor)
    {
            Macierz *suma;
            suma = new Macierz(nazwa_pliku);
     /* ... */
            return *suma;
    }
    Nie zwracaj w ten sposób obiektów z operatorów bo przy normalnym używaniu będziesz miała wycieki pamięci (da się używać twojego operatora tak by nie robić wycieków, ale przeciążanie operatorów zostało wprowadzone do języka aby ułatwiać programowanie).
    Kod:
    Macierz Macierz:: operator+ (const Macierz &wzor)
    {
            Macierz suma(nazwa_pliku);
     /* ... */
            return suma;
    }
    Cytat Napisał Gosik Zobacz post
    Tu pojawia sie problem, bo moj konstruktor zawiera tylko nazwe pliku. Niestety nie mam pomyslu jak wyciagnac liczbe wierszy i kolumn do alokacji pamieci.
    To może zrób konstruktor tworzący pustą macierz o podanym rozmiarze
    Metody klasy mają dostep do jej pól prywatnych, jeśli chcesz móc je odczytać z zewnątrz powinnaś dopisać odpowiednie akcesory (metody publiczne służące do odczytu wartości pól prywatnych).
    W operatorze dodawania mogłabyś też sprawdzać czy macierze mają takie same rozmiary i jakoś reagować gdy mają różne, np. rzucać wyjątek.
    Kod:
    Macierz Macierz::operator+ (const Macierz &r)
    {
    	if(wiersze != r.wiersze || kolumny != r.kolumny)
    		throw std::invalid_argument("Niekompatybilne macierze."); // <stdexcept>
    	Macierz suma(wiersze, kolumny);
    	/* dodajesz... */
    	return suma;
    }
    Niniejszy post przedstawia opinie autora w dniu dzisiejszym, na datę jego publikacji. Nie mogą być one wykorzystane przeciwko niemu w dniu jutrzejszym, ani innym następującym po nim dniu. Autor zastrzega sobie prawo do zmiany poglądów bez podawania przyczyn.

  9. #19

    Domyślnie

    [*]Nie zauważyłem, abyś kopiowała wartości pól wiersze i kolumny (podobnie w operatorze przypisania).[/LIST]
    Nanioslam poprawki, czy o to chodzi?
    Kod:
    //konstruktor kopjujacy:
    Macierz::Macierz(Macierz &wzor)
    {
            wiersze = wzor.wiersze;
            kolumny = wzor.kolumny;
            dane = new double [wiersze*kolumny]; //alokacja pamieci dla wektora
    
    
            for(int i = 0; i < wiersze; ++i)
                    for(int j = 0; j < kolumny; ++j)
                            dane[i * kolumny +j] = wzor.dane[i * kolumny + j]; //kopiowanie danych z tablicy
    
    }

    To może zrób konstruktor tworzący pustą macierz o podanym rozmiarze
    Od razu ja wyzerowywuje.
    Kod:
    //Konstruktor pustej macierzy:
    Macierz::Macierz(int wier, int kol)
    {
            wiersze = wier;
            kolumny = kol;
    
            tablica = new double[wiersze*kolumny];
    
            for(int i = 0; i < wiersze; ++i)
                    for(int j = 0; j < kolumny; ++j)
                            tablica[i * kolumny + j] = 0;
    }
    Dodawanie jeszcze mi nie idzie:
    Kod:
    Macierz &Macierz:: operator+ (const Macierz &r)
    {
    
            if(wiersze != r.wiersze || kolumny !=r.kolumny)
                    throw invalid_argument("Niekompatybilne macierze")
    
            Macierz suma(wiersze,kolumny); //czy tak moge wywolac konstruktor??
    
            for(int i = 0; i < wiersze; ++i)
                    for(int j = 0; j < kolumny; ++j)
                            suma[i * kolumny +j] = r.dane[i * kolumny +j] + dane[i * kolumny + j];
            return suma;
    }
    Czy nie powinnam zwracac wskaznika?

  10. #20

    Post

    Cytat Napisał Gosik Zobacz post
    Nanioslam poprawki, czy o to chodzi?
    Kod:
    //konstruktor kopjujacy:
    Macierz::Macierz(Macierz &wzor)
    {
            wiersze = wzor.wiersze;
            kolumny = wzor.kolumny;
    Dokładnie (W tym przypadku mogłaś użyć listy inicjalizacyjnej ale nie jest źle).
    Cytat Napisał Gosik Zobacz post
    Dodawanie jeszcze mi nie idzie:
    Kod:
    Macierz &Macierz:: operator+ (const Macierz &r)
    Przedtem obiekt mógł istnieć za długo, teraz będzie za krótko. Zwracaj po prostu obiekt a nie referencję do niego.
    Cytat Napisał Gosik Zobacz post
    Kod:
            Macierz suma(wiersze,kolumny); //czy tak moge wywolac konstruktor??
    Tak
    Cytat Napisał Gosik Zobacz post
    Czy nie powinnam zwracac wskaznika?
    Nie w tym przypadku (no chyba, że koniecznie chcesz utrudniać sobie życie).
    Cytat Napisał Gosik Zobacz post
    Kod:
                            suma[i * kolumny +j] = r.dane[i * kolumny +j] + dane[i * kolumny + j];
    Chyba chodziło Ci o suma.dane[i * kolumny +j].
    No chyba, że przeciążyłaś operator[] dla Macierz by zwracał referencję do odpowiedniego elementu tablicy wskazywanej przez pole dane.
    Jednak dla dwuwymiarowej macierzy lepiej byłoby przeciążyć [] tak by zwracał wskaźnik do wiersza
    Kod:
    double* Mcierz::operator[] (size_t wiersz)
    {
    	return dane + wiersz * kolumny; // to samo co & dane [wiersz * kolumny]; hint: arytmetyka wskaźników
    }
    I używać
    Kod:
    macierz[nr_wiersza][nr_kolumny]
    Ostatnio edytowane przez Rolek : 04-02-2013 - 18:25
    Niniejszy post przedstawia opinie autora w dniu dzisiejszym, na datę jego publikacji. Nie mogą być one wykorzystane przeciwko niemu w dniu jutrzejszym, ani innym następującym po nim dniu. Autor zastrzega sobie prawo do zmiany poglądów bez podawania przyczyn.

Zasady Postowania

  • Nie możesz zakładać nowych tematów
  • Nie możesz pisać wiadomości
  • Nie możesz dodawać załączników
  • Nie możesz edytować swoich postów
  •  
Subskrybuj