Przeciążanie operatorów i crash

Odpowiedz Nowy wątek
2012-06-08 11:58

Rejestracja: 8 lat temu

Ostatnio: 7 lat temu

0

Witam wszystkich serdecznie, jako że jest to mój pierwszy post.
Mam problem z następującym zadaniem:

Napisz klasę Set opisującą podzbiór liczb całkowitych. Definicja klasy powinna zawierać implementację następujących funkcji:
konstruktor, przyjmujący dwa parametry (ilość elementów zbioru i tablicę zawierającą te elementy)
konstruktor kopiujący
destruktor
operator +() - suma zbiorów (elementy zawarte w przynajmniej jednym zbiorze)
operator -() - różnica zbiorów (elementy zawarte w pierwszym ale nie w drugim zbiorze)
operator *() - iloczyn zbiorów (elementy zawarte w obu zbiorach)
operator =() - operator przypisania zbiorów
Pamiętaj o usunięciu powtarzających się elementów ze zbiorów wynikowych. Zaimplementuj operator << wypisujący elementy zbioru oraz funkcję main() pokazującą działanie klasy.

Niestety po napisaniu dostaje crash już w momencie sumowania zbiorów, a nie mogę znaleźć w czym jest problem. Prosiłbym o rzucenie okiem na kod:

#include<iostream>
#include<cstdlib>
#include<vector>
#include<ctime>
#include<iomanip>

using namespace std;

class Set {
    private:
        int amnt;
        vector<int> vals;
    public:
        Set(int a): amnt(a) {};
        Set(int a, vector<int> v): amnt(a),vals(v) {};
        Set(const Set& s); 
        ~Set() {   
            vals.clear();
            amnt=0;
        }

        Set operator +(const Set& s) const;
        Set operator -(const Set& s) const;
        Set operator *(const Set& s) const;
        Set& operator =(const Set& s);

        friend bool not_inside(int a, const Set& b);
                friend ostream& operator <<(ostream& os, const Set& s);
                friend void insertionSort(Set& s);
};

bool not_inside(int a, const Set& b) {
    int n=b.amnt;
    int l=0;
    int p=n-1;
    while(l<=p) {
        int s=(l+p)/2;
        if(b.vals[s] == a)
            return false;
        else if (b.vals[s] < a)
            l=s+1;
        else
            p=s-1;
    }
    return true;
}

void insertionSort(Set& s) {

    for(int j=s.amnt-2;j>=0;j--) {
        int x=s.vals[j];
        int i=j+1;
        while((i<s.amnt) && (x>s.vals[i])) {
            s.vals[i-1]=s.vals[i];
            i++;
        }
        s.vals[i-1]=x;
   }
}

Set::Set(const Set& s) {
        amnt = s.amnt;
        for (int i=0;i<amnt;i++)
            vals[i] = s.vals[i];
        }

Set Set::operator +(const Set& s) const{
        int size_min=min(this->amnt,s.amnt);
        int size_max=max(this->amnt,s.amnt);
        Set ret(0);

        for(int i=0;i<min(this->amnt,s.amnt);i++) {
            if(this->vals[i]==s.vals[i]) {
                ret.vals.push_back(s.vals[i]);
                                ret.amnt++;
                        }
            else {
                ret.vals.push_back(this->vals[i]);
                ret.amnt++;
                ret.vals.push_back(s.vals[i]);
                ret.amnt++;
            }
        }

        if(this->amnt != s.amnt)
            for(int j=min(this->amnt,s.amnt);j<size_max;j++) {
                ret.vals.push_back(this->amnt>s.amnt?this->vals[j]:s.vals[j]);
                ret.amnt++;
            }

        insertionSort(ret);
        int i=0;
        while(i<ret.amnt-1) {
            if(ret.vals[i]==ret.vals[i+1]) {
                ret.vals.erase(ret.vals.begin()+i+1);
                ret.amnt--;
            }
            else i++;
        }
        return ret;
}

Set Set::operator -(const Set& s) const{
        Set ret(-1);
        for(int j=0;j<this->amnt;j++)
            if(not_inside(this->vals[j],s)) {
                ret.vals.push_back(this->vals[j]);
                ret.amnt++;
            }
        return ret;
}

Set Set::operator *(const Set& s) const{
    Set ret(0);
    for(int j=0;j<max(this->amnt,s.amnt);j++)
        if(!not_inside((this->amnt>s.amnt?this->vals[j]:s.vals[j]),(this->amnt<s.amnt?*this:s))) {
            ret.vals.push_back(this->amnt>s.amnt?this->vals[j]:s.vals[j]);
            ret.amnt++;
        }
        return ret;
}

Set& Set::operator =(const Set& s) {
    this->vals.clear();
    this->amnt=s.amnt;
    this->vals.resize(sizeof(int)*s.amnt);
    for(int i=0;i<s.amnt;i++)
        this->vals[i]=s.vals[i];
    return *this;
}

ostream& operator <<(ostream& out, const Set& s) {
        out << setprecision(4) << "{";
        for (int i=0;i<s.amnt-1;i++)
            out << setw(10) << s.vals[i] << " ";
        out << setw(10) << s.vals[s.amnt-1] << "}" << endl;
        return out;
}

int main() {
    srand(time(NULL));
    int n=rand()%10;
    vector<int> v1(n), v2(n);
    for(int i=0;i<n;i++) {
        v1[i]=rand()%10;
        v2[i]=rand()%10;
    }
    Set s1(n,v1), s2(n,v2);
    cout.setf(ios::fixed, ios::floatfield);
    cout << endl;
    cout << s1;
    cout << s2;
    Set s3(n);
    s3=s1+s2;
    cout << s3 << endl;
    s3=s3-s1;
    cout << s3 << endl;
    s3=s1*s2;
    cout << s3 << endl;
    return 0;
}

Dzięki wielkie za wszelkie rady.

edytowany 1x, ostatnio: s0ull, 2012-06-08 12:57

Pozostało 580 znaków

2012-06-08 14:36

Rejestracja: 11 lat temu

Ostatnio: 6 lat temu

Set::Set(const Set& s) {
                amnt = s.amnt;
                for (int i=0;i<amnt;i++)
                        vals[i] = s.vals[i];
                }

W konstruktorze nie alokujesz miejsca w wektorze, więc nie możesz w ten sposób wprowadzać elementów. Jeśli już to korzystaj z funkcji push_back()


Potrzebujesz programy do szkoły/na zaliczenie? Pomocy podczas kolosa lub egzaminu?
Zamów go!

http://proogramy.c0.pl

Pozostało 580 znaków

2012-06-08 22:21

Rejestracja: 14 lat temu

Ostatnio: 1 minuta temu

0

czemu nie zrobić po ludzku:

class Set:public vector<int>
  {
   public:
  };

Czyli całość dotyczącą wypełnienia już masz.


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.

Pozostało 580 znaków

2012-06-11 22:16

Rejestracja: 8 lat temu

Ostatnio: 7 lat temu

0

Dzięki, poszło.

Pozostało 580 znaków

asdfsdf
2012-06-12 09:12
asdfsdf
0
_13th_Dragon napisał(a):

czemu nie zrobić po ludzku:

class Set:public vector<int>
{
public:
};

Czyli całość dotyczącą wypełnienia już masz.

Bo dziedziczenia należy unikać i preferować składanie?

Kto ci takie bzdury do głowy powkładał? - _13th_Dragon 2012-06-12 09:30

Pozostało 580 znaków

fhdghgfhgf
2012-06-12 10:23
fhdghgfhgf
afsdfsdf
2012-06-12 10:53
afsdfsdf
0

Eh, jak by ci sie chciało chociaż kilka artykułów przeczytać w tej tematyce. Ale prościej spamować.
Składanie nie jest lepsze, jest preferowane przez OOP, dlaczego? ponieważ zapewnia lżejsze powiązanie między klasami i wymusza inne relacje pomiędzy klasami, mniej spójne przez co łatwiej wymieniać poszczególne bloczki. Dziedziczenie można stosować, kiedy chcemy mieć powiązania na etapie kompilacji i obiekty mają ze sobą silne powiązanie.

A w tym przypadku oczywiście niema silnego powiązania, zastanów się: Set(int a, vector<int> v): amnt(a),vals(v) {}; - _13th_Dragon 2012-06-12 10:59

Pozostało 580 znaków

jhafjksdfh
2012-06-12 11:05
jhafjksdfh
0

Chyba że za jakiś czas zmieni implementacje set z vector na chociażby map. Wystawiając własne funkcje wystarczy że zmieni bebechy klasy, w przypadku dziedziczenia już będzie większy kłopot, ktoś moze sie pokusic o używanie bezpośrednio metod z klasy vector.
Odniosłem sie tylko do informacji "dlaczego nie dziedziczenie", bo nie wiemy co autor chciał uzyskać.

To co autor chciał uzyskać to wielka tajemnica. Używanie vectora dla realizacji Set generalnie jest bezsensowne. Skoro już używamy STL to powinno się użyć normalnego set'a który jest tam zaimplementowany. Jeżeli nie używamy STL to nie powinno tam być vector'a. Jedyne rozsądne wytłumaczenie to: jest to projekt w którym trzeba pokazać umiejętność sortowania i umiejętność wyszukiwania przez połowienie. Uwzględniając ten fakt napisałem że w tym przypadku rozwiązanie class Set:public vector<int> uprości zadanie. Powiedz, proszę, na jakich założeniach ty bazujesz tą dyskusję? - _13th_Dragon 2012-06-12 12:55

Pozostało 580 znaków

2012-06-12 13:19

Rejestracja: 9 lat temu

Ostatnio: 1 rok temu

0

dla mnie brak wirtualnego destruktora w implementacji std::vector jest wystarczającym dowodem na to iż stl nie został opracowany "w duchu obiektowości".


"..."
"odp"
"qtMaster"

Pozostało 580 znaków

afdhsdlk
2012-06-12 13:39
afdhsdlk
0

@_13th_Dragon naprawdę nie rozumiem czemu zawsze cie to tak boli jak ktoś ci pokaże inne rozwiązanie? Pytałeś czemu nie użył dziedziczenia, dostałeś odpowiedź że może dlatego że preferuje składanie w myśl OOP?
Powiedziałeś że to bzdury, które ktoś mi nawkładał do głowy(znaczy co nie mogę tak uważać? bo ty masz na ten temat inne zdanie?) ... wysłałem ci linki plus zapytanie do google, którego ci sie chyba nie chciało wpisać, i które omawia to zagadnienie, jak widać nie jest to tylko mój wymysł.
Ty natomiast dalej ciągniesz durne dyskusje.

Czy naprawdę myślisz że autor tego kodu "preferuje składanie w myśl OOP"!? Czy ty popatrzyłeś na ten kod, czy zwyczajnie jaja sobie robisz? - _13th_Dragon 2012-06-12 13:51

Pozostało 580 znaków

asdasd
2012-06-12 14:01
asdasd
0

Tak, teraz to juz sobie jaja robie.... ale chyba jasne o co mi chodzi, do każdego alternatywnego podejścia musisz doczepić bagaż dyskusji i usilnie wykazać, że tylko twoje podejście jest zajebiste, a innych to w ogóle ścierwo, a nie kod zamiast dopuścić do siebie informacje że może te inne rozwiązanie będzie bardziej odpowiadać autorowi? Zamiast wykazać różnice i zastosowanie ty po prostu dyskredytujesz opinie innych bo jest inna niż twoja. Rzucona została informacja że według OOP powinno sie preferować składanie nad dziedziczenie. Z jakichś powodów to cie rozdrażniło i próbowałeś wcisnąć mi ze jakieś bzdury pisze, dostałeś masę linków.
Wystarczyło napisać że w tym przypadku prościej będzie użyć dziedziczenia i byłby koniec dyskusji, ktoś kogo by zainteresowało składanie poczytałby o tym. Nie zgadasz sie z tą tezą OOP? wystarczy napisać swoje argumenty przeciw, wtedy twoje posty miały by jakąś wartość.

No właśnie jaja sobie robisz ... Nie pokazałeś alternatywy, to co powiedziałeś o wersji bez dziedziczenia jest zrobione w poście otwierającym temat, to ja pokazałem alternatywę z wyjaśnieniem "Czyli całość dotyczącą wypełnienia już masz", ale nie oznacza to wg ciebie: - "że w tym przypadku prościej będzie użyć dziedziczenia". Przecież to co piszesz: - "...usilnie wykazać, że tylko twoje podejście jest zajebiste, a innych to w ogóle ścierwo, a nie kod zamiast dopuścić do siebie informacje że może te inne rozwiązanie będzie bardziej odpowiadać autorowi" - to apel do ciebie. - _13th_Dragon 2012-06-12 14:18
"wystarczy napisać swoje argumenty przeciw, wtedy twoje posty miały by jakąś wartość" - to też dotyczy przede wszystkim ciebie. A to: - "Zamiast wykazać różnice i zastosowanie ty po prostu dyskredytujesz opinie innych bo jest inna niż twoja." - znowu jak ulał do ciebie. - _13th_Dragon 2012-06-12 14:21

Pozostało 580 znaków

Odpowiedz

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0