Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Segmentation fault atakuje ponownie!

Ostatnio zmodyfikowano 2013-04-14 22:24
Autor Wiadomość
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:
C/C++
#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;
}
P-80413
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.
P-80415
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 ;)
P-80420
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.
P-80443
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
P-80445
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:
C/C++
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ę.
P-80449
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.
P-80452
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.
P-80579
« 1 »
  Strona 1 z 1