imralav Temat założony przez niniejszego użytkownika |
Segmentation fault atakuje ponownie! » 2013-04-11 23:20:11 Witam. Nie potrafię znaleźć błędu w tym kodzie, nawet debugger mi nie pomógł. Czuję, że to głupota a ja po prostu już nie myślę. Ten błąd to oczywiście segmentation fault (w Javie, gdzie samemu pamięcią zarządzać nie trzeba kod udało się zrobić, więc coś we wskaźnikach skopałem). Oto kod: #include <iostream> #include <string> #include <sstream>
using namespace std;
class Punkt { public: int x; int y; Punkt() { x = y = 0; }; Punkt( int xx, int yy ) { x = xx; y = yy; } Punkt( const Punkt & p ) { this->x = p.x; this->y = p.y; } string toString() { ostringstream sx, sy; sx << x; sy << y; return "X: " + sx.str() + " Y: " + sy.str(); } void przesun( int dx, int dy ) { x += dx; y += dy; } };
class Linia { private: Punkt * A; Punkt * B; public: Linia() { A = new Punkt( 0, 0 ); B = new Punkt( 0, 0 ); } Linia( Punkt a, Punkt b ) { A = new Punkt( a ); B = new Punkt( b ); } Linia( const Linia & l ) { this->A = new Punkt( * l.A ); this->B = new Punkt( * l.B ); } ~Linia() { delete A; delete B; } string toString() { ostringstream sx1, sy1, sx2, sy2; sx1 << A->x; sx2 << B->x; sy1 << A->y; sy2 << B->y; return "P1: " + A->toString() + "\nP2: " + B->toString(); } void przesun( int dx, int dy ) { A->przesun( dx, dy ); B->przesun( dx, dy ); } };
class Trojkat { private: Linia * a; Linia * b; Linia * c; public: Trojkat() { Punkt * p1 = new Punkt( 0, 0 ); Punkt * p2 = p1; Punkt * p3 = p2; a = new Linia( * p1, * p2 ); b = new Linia( * p2, * p3 ); c = new Linia( * p3, * p1 ); } Trojkat( Punkt p1, Punkt p2, Punkt p3 ) { a = new Linia( p1, p2 ); b = new Linia( p2, p3 ); c = new Linia( p3, p1 ); } Trojkat( const Trojkat & t ) { a = new Linia( * t.a ); b = new Linia( * t.b ); c = new Linia( * t.c ); } ~Trojkat() { delete a; delete b; delete c; } void przesun( int dx, int dy ) { a->przesun( dx, dy ); b->przesun( dx, dy ); c->przesun( dx, dy ); } string toString() { return "A:\n" + a->toString() + "\nB:\n" + b->toString() + "\nC:\n" + c->toString(); } };
class Czworokat { private: Linia * a, * b, * c, * d; public: Czworokat() { Punkt p1( 0, 0 ), p2 = p1, p3 = p2, p4 = p3; a = new Linia( p1, p2 ); b = new Linia( p2, p3 ); c = new Linia( p3, p4 ); d = new Linia( p4, p1 ); } Czworokat( Punkt p1, Punkt p2, Punkt p3, Punkt p4 ) { a = new Linia( p1, p2 ); b = new Linia( p2, p3 ); c = new Linia( p3, p4 ); d = new Linia( p4, p1 ); } ~Czworokat() { delete a; delete b; delete c; delete d; } Czworokat( const Czworokat & czw ) { a = new Linia( * czw.a ); b = new Linia( * czw.b ); c = new Linia( * czw.c ); d = new Linia( * czw.d ); } void przesun( int dx, int dy ) { a->przesun( dx, dy ); b->przesun( dx, dy ); c->przesun( dx, dy ); d->przesun( dx, dy ); } string toString() { return "A:\n" + a->toString() + "\nB:\n" + b->toString() + "\nC:\n" + c->toString() + "\nD:\n" + d->toString(); } };
class Obraz { private: int wierzch_tr, wierzch_cz, rozmiar; Trojkat * trojkaty; Czworokat * czworokaty; public: Obraz( int rozm = 10 ) { rozmiar = rozm; trojkaty = new Trojkat[ rozmiar ]; czworokaty = new Czworokat[ rozmiar ]; wierzch_tr = wierzch_cz = - 1; } Obraz( const Obraz & ob ) { this->wierzch_tr = ob.wierzch_tr; this->wierzch_cz = ob.wierzch_cz; this->rozmiar = ob.rozmiar; trojkaty = new Trojkat[ rozmiar ]; czworokaty = new Czworokat[ rozmiar ]; for( int i = 0; i <= wierzch_tr; i++ ) { trojkaty[ i ] = ob.trojkaty[ i ]; } for( int i = 0; i <= wierzch_cz; i++ ) { czworokaty[ i ] = ob.czworokaty[ i ]; } } void dodaj( Trojkat tr ) { if( wierzch_tr != rozmiar - 1 ) { trojkaty[ ++wierzch_tr ] = tr; } } void dodaj( Czworokat cz ) { if( wierzch_cz != rozmiar - 1 ) { czworokaty[ ++wierzch_cz ] = cz; } } void przesun( int dx, int dy ) { for( int i = 0; i <= wierzch_tr; i++ ) { trojkaty[ i ].przesun( dx, dy ); } for( int i = 0; i <= wierzch_cz; i++ ) { czworokaty[ i ].przesun( dx, dy ); } } string toString() { string napis = ""; for( int i = 0; i <= wierzch_cz; i++ ) { napis += czworokaty[ i ].toString() + "\n"; } for( int i = 0; i <= wierzch_tr; i++ ) { napis += trojkaty[ i ].toString() + "\n"; } return napis; } };
int main() { Punkt p1( 0, 0 ), p2( 0, 3 ), p3( 3, 3 ), p4( 3, 0 ); Trojkat t1( p1, p2, p3 ); Czworokat c1( p1, p2, p3, p4 ); Obraz obraz( 5 ); obraz.dodaj( c1 ); c1.przesun( - 5, 0 ); obraz.dodaj( c1 ); obraz.dodaj( t1 ); cout << c1.toString() << endl; cout << obraz.toString() << endl; return 0; }
|
|
Monika90 |
» 2013-04-11 23:59:03 W C++ też nie trzeba samemu zarządzać pamięcią. Twój program jest o wiele za długi i ma w sobie mnóstwo zbędnych rzeczy. Najbardziej zbędną rzeczą w twoim programie jest operator new. Napisz bez tego operatora (i bez konstruktorów kopiujących), to nie będzie segfaultów.
PS. Jako tablicy dynamicznej możesz użyć std::vector. |
|
imralav Temat założony przez niniejszego użytkownika |
» 2013-04-12 06:52:26 W poleceniu miałem podane, że muszą znaleźć się konstruktory kopiujące, więc.. Te new też jest odgórnie narzucone, muszę korzystać z obiektów dynamicznych ;) |
|
imralav Temat założony przez niniejszego użytkownika |
» 2013-04-12 14:35:03 Co sam do tej pory wyszukałem? Coś jest nie tak z konwersją int -> string w metodzie toString() klasy Punkt. Nie wiem tylko czemu, zrobiłem to samo w mainie i jest spoko, a w metodzie toString() klasy Punkt już coś nie działa. |
|
Monika90 |
» 2013-04-12 14:48:51 W poleceniu było, że masz zrobić źle? Co za czasy... Twój program nie działa, bo twoje klasy nie mają operatora przypisania(*). Oczywiście najlepiej byłoby napisać bez operatora przypisania, i bez konstruktora kopiującego, i bez tych wszystkich wskaźników. Ale skoro już używasz wskaźników, to musisz mieć operator przypisania(*).
(*) chodzi oczywiście o zdefiniowany przez użytkownika operator przypisania |
|
imralav Temat założony przez niniejszego użytkownika |
» 2013-04-12 15:07:39 Treść polecenia: Wykorzystując technikę kompozycji stwórz następujące klasy (język dowolny, w C++ użyj obiektów dynamicznych, nazwy 'toString/ToString' i 'String/string' w różnych językach zaczynają się od litery o różnej wielkości):
klasa Punkt reprezentująca punkt na płaszczyźnie ze współrzędnymi x i y. Powinna posiadać 3 konstruktory: domyślny, dwuparametrowy (int, int) i kopiujący.
klasa Linia składająca się z 2 punktów. Linia powinna posiadać 3 konstruktory: domyślny, dwuparametrowy (Punkt, Punkt) oraz kopiujący.
klasa Trojkąt skłądająca się z 3 linii.
klasa Czworokąt składająca się z 4 linii
klasa Obraz zawierająca przywatną kolekcję (tablicę, listę) figur - trójkątów i czworokątów oraz metody umożliwiające dodawanie nowych figur do kolekcji
W konstruktorze każdej z klas zbudowanych z obiektów innych klas - komponentów powinno się budować również obiekty komponentów. Warto pamiętać przy tym, że w Javie/C# z jednego konstruktora danej klasy można wywołać inny konstruktor danej klasy, aby uniknąć duplikacji kodu.
Jakie parametry powinny przyjmować konstruktory Czworokąta i Trójkąta, aby zapewnić, że każdy z nich będzie spójny (tzn. ich linie będą się łączyć końcami) ?
Każda z klas powinna mieć
metodę 'przesun(int dx, int dy)', przy czym w klasach składających się z obiektów innych klas powinna ona wywoływać metody 'przesun' swoich obiektów składowych.
metodę 'String toString()' zwracające tekstową reprezentację danego obiektu, przy czym w klasach składających się z obiektów innych klas powinna ona wywoływać metody 'toString' swoich obiektów składowych.
W klasach powinno się oczywiście używać zasad hermetyzacji.
Uwaga: W programie głównym poniższy kod powinien wykazać, że przesunięcie np. jednej linii (i podobnie innych figur) nie przesuwa innej:
Punkt p1 = new Punkt( 0, 0 ), p2 = new Punkt( 1, 1 ); Linia l1 = new Linia( p1, p2 ), l2 = new Linia( p1, p2 ); l1.przesun( 5, 5 ); System.out.println( l1 ); System.out.println( l2 ); Oprócz tego program powinien umożliwić użytkownikowi dynamiczne "tworzenie" obrazu przez dodawanie nowych figur oraz jego "rysowanie" (poprzez wywołanie metody 'toString');
|
W javie zakodzić się to udało, pięknie działa, tego jakoś przejść nie mogę. |
|
Monika90 |
» 2013-04-12 15:47:29 w C++ użyj obiektów dynamicznych, |
czyli co? int też ma być dynamiczne? U ciebie nie jest. klasa Obraz zawierająca przywatną kolekcję (tablicę, listę) figur - trójkątów i czworokątów oraz metody umożliwiające dodawanie nowych figur do kolekcji |
czyli ma zawierać jedną kolekcję (co w jakiś sposób uzasadnia te obiekty dynamiczne), ty masz dwie tablice. A odpowiedź już dostałeś: zaimplementuj operatory przypisania. Klasa która ma zdefiniowany przez użytkownika konstruktor kopiujący prawie zawsze musi mieć też zdefiniowny przez użytkownika operator przypisania. Z drugiej strony, jeżeli używa się obiektów dynamicznych i dziedziczenia to najlepiej wyłączyć kopiowanie w ogóle. |
|
imralav Temat założony przez niniejszego użytkownika |
» 2013-04-14 22:24:37 Dziękuję, właśnie operatorów przypisania brakowało. Problem rozwiązany. |
|
« 1 » |