[C++] Macierz o zadanym wymiarze

Awatar użytkownika
Bierut
Użytkownik
Użytkownik
Posty: 686
Rejestracja: 26 paź 2006, o 17:11
Płeć: Mężczyzna
Lokalizacja: Wrocław
Podziękował: 15 razy
Pomógł: 84 razy

[C++] Macierz o zadanym wymiarze

Post autor: Bierut »

Chcę, aby podczas działania programu, użytkownik mógł wybrać rozmiar macierzy kwadratowej, a potem robić na niej inne operacje.

Operator new[] nie zadziała dla tablicy dwuwymiarowej. Próbowałem też zrobić najpierw klasę Wektor, a potem na podstawie tego klasę Macierz, ale nic z tego. Widać, używa się tego na innej zasadzie:

Kod: Zaznacz cały

int rozmiar;

class Wektor {
    float * wektor = new float[Rozmiar];
    
    // dalsza część
}

class Macierz {
    Wektor * macierz = new Wektor[Rozmiar];
    
    // dalsza część
}
Podejrzewam, że moje próby napisania sensownego kodu powyżej są pośmiewiskiem. Jeśli tak jest, to zapomnijcie o tym co jest tam napisane i podajcie jakiś sposób na stworzenie macierzy o zadanym przez użytkownika rozmiarze.
Awatar użytkownika
N4RQ5
Użytkownik
Użytkownik
Posty: 421
Rejestracja: 15 lis 2006, o 16:22
Płeć: Mężczyzna
Lokalizacja: Suwałki/Wawa
Pomógł: 104 razy

[C++] Macierz o zadanym wymiarze

Post autor: N4RQ5 »

Zawsze możesz zaimplementować macierz jako wektor o rozmiarze \(\displaystyle{ n^2}\) i przy dalszych operacjach po prostu tłumaczyć indeksy w macierzy na odpowiedni indeks w wektorze.
\(\displaystyle{ (x,y) = nx + y}\)
to chyba prostsze niż alokowanie n wektorów po n liczb i wkładanie ich w tablicę takich wektorów.
Jeden dłuższy wektor łatwiej zaalokować i łatwiej po nim posprzątać.
Problem może być przy dużych macierzach bo możesz przekroczyć górne wartości indeksu ale wszystko zależy od tego jakich rozmiarów planujesz używać i jakie są Ci potrzebne.
Awatar użytkownika
Bierut
Użytkownik
Użytkownik
Posty: 686
Rejestracja: 26 paź 2006, o 17:11
Płeć: Mężczyzna
Lokalizacja: Wrocław
Podziękował: 15 razy
Pomógł: 84 razy

[C++] Macierz o zadanym wymiarze

Post autor: Bierut »

Rozumiem o co chodzi. Jak z tego zrobić klasę macierzy? Kompilator informuje, że nie można używać operatora new w tym miejscu, gdzie go użyłem w podanym wyżej przykładzie.
Awatar użytkownika
erina
Użytkownik
Użytkownik
Posty: 230
Rejestracja: 29 mar 2010, o 20:14
Płeć: Kobieta
Lokalizacja: Pruszków
Pomógł: 38 razy

[C++] Macierz o zadanym wymiarze

Post autor: erina »

Bo new używasz w konstruktorze, znajdź sobie jakiś tutorial do klas i zobacz, jak to jest tam robione. Zwłaszcza doczytaj sobie o konstruktorach i destruktorach, będą Ci potrzebne.
Awatar użytkownika
kadiii
Użytkownik
Użytkownik
Posty: 642
Rejestracja: 20 gru 2005, o 21:04
Płeć: Mężczyzna
Lokalizacja: Wrocław
Pomógł: 130 razy

[C++] Macierz o zadanym wymiarze

Post autor: kadiii »

Bierut pisze: Operator new[] nie zadziała dla tablicy dwuwymiarowej.
Zależy w jakim sensie chcesz go użyć.
Bierut pisze: Próbowałem też zrobić najpierw klasę Wektor, a potem na podstawie tego klasę Macierz, ale nic z tego. Widać, używa się tego na innej zasadzie:

Kod: Zaznacz cały

int rozmiar;

class Wektor {
    float * wektor = new float[Rozmiar];
    
    // dalsza część
}

class Macierz {
    Wektor * macierz = new Wektor[Rozmiar];
    
    // dalsza część
}
Podejrzewam, że moje próby napisania sensownego kodu powyżej są pośmiewiskiem. Jeśli tak jest, to zapomnijcie o tym co jest tam napisane i podajcie jakiś sposób na stworzenie macierzy o zadanym przez użytkownika rozmiarze.
Ogólnie sprawa wygląda tak - ten powyżej pomysł jest niestety nietrafiony z jednego drobnego, ale fundamentalnego powodu - dynamicznie mozna alokować pamięć tylko za pomocą konstruktora domyślnego.
Uprzedzajać fakty linijka:

Kod: Zaznacz cały

macierz=new Wektor(rozmiar)[rozmiar]

byłaby niepoprawna
mamy dwa podstawowe rozwiązania o podobnej konstrukcji zaleznie od tego co akurat potrzebujemy:
-jesli zalezy nam na dodatkowych polach w komórkach macierzy i chceamy mieć wielowymiarową tablice obiektów zawartą w innej klasie

Kod: Zaznacz cały

class Wektor{
 ... parametry klasy
};
class Macierz{
 public:
 Wektor ** macierz;
 ... pozostałe parametry
 Macierz(int rozmiar=1)
 {
  macierz=new Wektor*[rozmiar]; 
  for(int i=0;i<rozmiar;i++)
   macierz[i]=new Wektor;
 }
};
-jeśli zalezy nam na samej macierzy, której komórki będa typami standardowymi to działamy podobnie:

Kod: Zaznacz cały

class Macierz{
 public:
 float ** macierz;
 ... pozostałe parametry
 Macierz(int rozmiar=1)
 {
  macierz=new float*[rozmiar]; 
  for(int i=0;i<rozmiar;i++)
   macierz[i]=new float[rozmiar];
 }
};
Dobrym rozwiązaniem jest również tablica jednowymiarowa z indeksowaniem - to w sumie najwydajniejsze rozwiązanie - podane tu już przez N4RQ5.
Problem może być przy dużych macierzach bo możesz przekroczyć górne wartości indeksu ale wszystko zależy od tego jakich rozmiarów planujesz używać i jakie są Ci potrzebne.
NIe zaalokuje się w standardowych warunkach tablicy przekraczającej górną wartość typu całkowitego.
Awatar użytkownika
Bierut
Użytkownik
Użytkownik
Posty: 686
Rejestracja: 26 paź 2006, o 17:11
Płeć: Mężczyzna
Lokalizacja: Wrocław
Podziękował: 15 razy
Pomógł: 84 razy

[C++] Macierz o zadanym wymiarze

Post autor: Bierut »

Myślę, że odpowiednia będzie tablica jednowymiarowa z indeksowaniem. Niestety, przy pomocy udzielonych wskazówek, nie potrafię napisać takiej klasy oraz stworzyć zmiennych typu Macierz. Próbowałem robić na zasadzie podanych przykładów, ale zawsze wyskakują jakieś błędy.

Mógłby ktoś podać, jak to ma wyglądać:

Kod: Zaznacz cały

class Macierz {
       /* nie wiem co tutaj trzeba umieścić, żeby można było zastosować:
          float * macierz = new float[rozmiar*rozmiar]  */
}

int main() {
   int rozmiar;
   cout <<  "Wymiary: ";
   cin >> rozmiar;

   Macierz kwadrat;       /*zmienna typu Macierz o nazwie kwadrat*/
}
Awatar użytkownika
argv
Użytkownik
Użytkownik
Posty: 569
Rejestracja: 27 maja 2009, o 01:27
Płeć: Mężczyzna
Podziękował: 51 razy
Pomógł: 66 razy

[C++] Macierz o zadanym wymiarze

Post autor: argv »

W innym temacie odsyłałem już:
i pierwszy link.

Bardzo dobra implementacja wraz z przykładem użycia, polecam.
Awatar użytkownika
kadiii
Użytkownik
Użytkownik
Posty: 642
Rejestracja: 20 gru 2005, o 21:04
Płeć: Mężczyzna
Lokalizacja: Wrocław
Pomógł: 130 razy

[C++] Macierz o zadanym wymiarze

Post autor: kadiii »

Tak jeszcze wrócę do poprzedniego rozwiazania bo jest jednak dość proste i warto żebyś zrozumiał.

Kod: Zaznacz cały

class Macierz{
public:
float ** macierz;
... pozostałe parametry
Macierz(int rozmiar=1)
{
  macierz=new float*[rozmiar];
  for(int i=0;i<rozmiar;i++)
   macierz[i]=new float[rozmiar];
}
};
I teraz wytłumaczę kolejne fragmenty:

Kod: Zaznacz cały

float ** macierz;
To jest wskaźnik na wskaźnik na float czyli de facto tablica wskaźników(taka niezaalokowana, sam adres). Masz więc najpierw zaalokowac jej miejsce żeby kompilator wiedział ile chcesz mieć tych wskaźników. mamy więc:

Kod: Zaznacz cały

macierz=new float*[rozmiar];
Czyli alokujemy tyle wskaźników jaką ma wartość zmienna rozmiar. Teraz mamy juz naszą tablicę o ustalonej liczbie wskaźników. Każda komórka tablicy macierz macierz[0],macierz[1],...,macierz[rozmiar] ma wartosć, która nie jest zwykłą wartoscia tylko wskaźnikiem. Teraz zostaje już zwykła alokacja tylu tablic jednowymiarowych jaka wartość ma zmienna rozmiar:
Zwykła alokacja pamięci na dynamiczna tablicę jednowymiarową wygląda tak:

Kod: Zaznacz cały

float * wskaznik=new flaot[rozmiar]
My chcemy jednak miec rozmiar-razy takich tablic aby uzyskać macierz, robimy więc w pętli:

Kod: Zaznacz cały

  for(int i=0;i<rozmiar;i++)
   macierz[i]=new float[rozmiar];
Oczywiście jest to jeden ze sposobów dynamicznej alokacji pamięci, ale sądzę, że warto go znać i rozumieć.
Teraz możemy skorzystać juz z naszego konstruktora i utworzyć w main obiekt klasy Macierz.

Kod: Zaznacz cały

Macierz Nasza_macierz(10);
i odwołujemy sie do naszych komórek:

Kod: Zaznacz cały

Nasza_macierz.macierz[1][1]=15;
Myślę, że teraz powinno być już jasne.
Awatar użytkownika
Bierut
Użytkownik
Użytkownik
Posty: 686
Rejestracja: 26 paź 2006, o 17:11
Płeć: Mężczyzna
Lokalizacja: Wrocław
Podziękował: 15 razy
Pomógł: 84 razy

[C++] Macierz o zadanym wymiarze

Post autor: Bierut »

argv, widziałem tamten temat i nawet ściągnąłem podany plik.
Ostatecznie skorzystałem ze sposobu, który kadiii opisał w ostatnim poście. Myślę, że teraz już rozumiem o co w tym chodzi.
ODPOWIEDZ