Zamiana struktury na klasy

0

Witam, jakiś czas temu oddawałem zadanie na spoja (sort1). zadanie polegało na tym, żeby podać współrzędne punktu, które następnie zostaną posortowane i wyświetlone ze względu na odległość od początku układu współrzędnych (najpierw wyświetlane są punkty bliżej początku). program działał, został zaakceptowany, był ok -> wygląda o tak:

#include <iostream>
using namespace std;

const int Tib = 10;
struct punkt
{
    char ch [Tib];
    int x;
    int y;
    float odl;
};
inline double odleg (punkt t1) {return t1.x * t1.x + t1.y*t1.y;}
void sortuj(punkt *t1, int n);

int main()
{
    using namespace std;
    int test, liczba_punktow;
    punkt t1[1000];
    char ch;

    cin>> test;
    for (int i = 0; i < test; i++)
    {
        int j;
        cin>>liczba_punktow;
        for (j = 0; j < liczba_punktow; j++)       //wpisywanie wartosci punktow do tablicy i oblicznaie odleglosci za pomoca funkcji.
        {
            cin>>t1[j].ch;
            cin>>t1[j].x >> t1[j].y;
            t1[j].odl = odleg (t1[j]);
        }

        sortuj(t1, j);
        for (int w = 0; w < j; w ++)
            cout<< t1[w].ch<<" "<<t1[w].x<<" "<<t1[w].y<<endl;
    }
}

void sortuj(punkt *t2, int n)
{
    punkt tmp;
    for (int i=0; i<n; i++)
    {
        for (int j = 0; j < n - 1; j++)
        {
            if (t2[j].odl > t2[j+1].odl)
            {
                tmp=t2[j];
                t2[j]=t2[j+1];
                t2[j+1]=tmp;
            }
        }
    }
}

teraz chciałbym przepisać program tak, żeby zamiast na strukturze operował na klasie (co może i jest bez sensu i tylko komplikuje program, ale chcę poćwiczyć) . Chcę stworzyć klasę i wyposażyć ją w funkcje która liczy odległość. Teraz wygląda tak:

#include <iostream>
#include <string>


const int TIB = 10;
class Punkt
{
private:
    std::string ch;
    int x;
    int y;
    double odleg;
    double odl(int a, int b) { odleg = a * a + b * b;} 
public:
    Punkt ();
    Punkt (std::string ch1, int xx, int yy); //konstruktor
};

void sortuj(Punkt t3, int n);

int main()
{
    using namespace std;
    int test, liczba_punktow;
    Punkt t2[1000];  //czyli tu musi byc konstruktor domyslny?

    cin>> test;
    for (int i = 0; i < test; i++)
    {
        string ch;
        int x, y;
        int j;
        cin>>liczba_punktow;
        for (j = 0; j < liczba_punktow; j++)       
        {
            cin>>ch>>x>>y;
            t2[j] = Punkt (ch,x,y);  // a dlaczego nie Punkt::Punk (ch,x,y)t???
        }
        // jeszcze nic nie sortuje. na tym skonczyłem
    }
}
// tu był alfgorytm sortujący, ale jeszcze do struktur. Nic z nim nie robiłem


Punkt::Punkt () //konstruktor domyslny
{
    ch = "bez nazwy";  // chciałem tutaj wpisac do tablicy char ale wyskakiwaly bledy . strcpy nie dzialalo
    x = 0;
    y = 0;
}

Punkt::Punkt (string ch1, int xx, int yy)
{
    ch = ch1;
    x=xx;
    y=yy;
    odl(xx,yy);
}

Teraz mam kilka pytań - oprócz tych zawartych w komentarzach

  1. jak to zrobić lepiej i ładniej. Wiem, ze ktoś mi zaraz wklei poprawiony kod, natomiast prosiłbym o jakies komentarze
  2. jak to postortowac wg wartosci prywatnej (odleg)? Wiem, ze nie korzystam ze specjalnej funkcji, do tego stosuje sortowanie bąbelkowe ale che wiedziec co się dzieje w srodku
1

Wiem, ze ktoś mi zaraz wklei poprawiony kod

Optymista. :p

double odl(int a, int b) { odleg = a * a + b * b;}

Kontrola dochodzi do końca funkcji zwracającej double, ale niczego nie zwracasz. :P

Punkt t2[1000];  //czyli tu musi byc konstruktor domyslny?

Może nie tyle "tu" tylko "dlatego". Alokujesz tablicę (yuck), więc musisz mieć domyślny konstruktor.

t2[j] = Punkt (ch,x,y);  // a dlaczego nie Punkt::Punk (ch,x,y)t???

Bo to konstruktor, a nie metoda statyczna.

void sortuj(Punkt t3, int n)

...jeden punkt chcesz sortować? (Raczej użyj std::sort, a żeby to działało zdefiniuj operator< dla Punkt)

if (t3[j].odl > t3[j+1].odl)

odl? Co tu próbujesz zrobić?

ch = "bez nazwy";  // chciałem tutaj wpisac do tablicy char ale wyskakiwaly bledy . strcpy nie dzialalo 

std::string i tak wygodniejszy, ale jakie błędy Ci wyskakiwały? Poza tym, użyj listy inicjalizacyjnej konstruktora: Punkt::Punkt() : ch("bez nazwy"), x(0), y(0) { } - dzięki niej możesz przeprowadzić inicjalizację zmiennych.

Punkt::Punkt (string ch1, int xx, int yy)

Brakuje std:: przed string co może w rezultacie dać dość mało czytelny komunikat: error: expected constructor, destructor, or type conversion before '(' token [...]

1

Uparłem się na tablice char w klasie.

Mój błąd, nie optymista - masochista. ;)

char *ch;
//...
cin>>ch;

Co ten kod robi? Opisz ze szczegółami.

class Punkt
{
private:
    char *ch[];

To się w ogóle kompiluje? Możesz napisać jakiego typu jest zmienna ch?

*ch = new char [...]; 

Możesz napisać co ten kod robi? Najlepiej ze szczegółami.

0

Teraz program wygląda tak:

 #include <iostream>
#include <cstring>

const int TIM = 10;
const int TAB = 1000;
class Punkt
{
private:
    char ch[TIM];
    int x;
    int y;
    double odleg;
    void odl(int a, int b) {odleg = a * a + b * b;}
public:
    Punkt (const char *ps = "bez nazwy", int xx = 0, int yy = 0); //konstruktor

};


int main()
{
    using namespace std;
    int test, liczba_punktow;
    Punkt *t1 = new Punkt [TAB];  //czy tu musi byc konstruktor domyslny?

    cin>> test;
    for (int i = 0; i < test; i++)
    {
        char *ch = new char;
        int x, y;
        int j;
        cin>>liczba_punktow;
        for (j = 0; j < liczba_punktow; j++)       //wpisywanie wartosci punktow do tablicy i oblicznaie odleglosci za pomoca funkcji. teraz to treba posotrowac
        {
            cin>>ch>>x>>y;
            t1[j] = Punkt (ch,x,y);  // a dlaczego nie Punkt::Punkt???
        }

    }
}


Punkt::Punkt (const char *ps , int xx, int yy)
{
    strcpy(ch, ps);
    ch[10] = '\0';
    x=xx;
    y=yy;
    odl(xx,yy);
}

Ten działa. Kod który usunąłem przed chwilą zupełnie się sypał.

*ch = new char [...];

kiedy deklaruję tylko char ch mam błąd w pętli -> invalid conversion from 'char' to 'const char*'.
kiedy deklaruje char *ch; to program się sypie przy wprowadzaniu wartosci ch - wydaje mi się to logiczne, w końcu nie mam zaalookowanej pamięci.
To jest jedyny sposób żeby kod mi się nie posypał i działał tak jak chcę, chociaż wiem, że wygląda to brzydko.
Zastanawiam się czy dobrze zaalokowałem dynamiczną tablicę klas w funkcji main.

1

double odleg;
void odl(int a, int b) {odleg = a * a + b * b;}

Dlaczego zamiast tego nie zwrócisz odległości jako wartość funkcji i nie użyjesz swoich pól? tj.

int length() const { return x*x + y*y; }
2
strcpy(ch, ps);

Co się stanie, jeżeli wywołam z cstringiem "lalalala nie powstrzymasz mnie przed wpisaniem wiecej niz dziesieciu liter (a wlasciwie dziewieciu plus terminator) lalala"?

ch[10] = '\0';

Przypomnij mi, ilu elementowa jest ta tablica? Jaki jest dla niej najwyższy poprawny indeks?

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.