Sortowanie wektorów struktur

0

Witam,

Mam problem z sortowaniem, ktory nie tyle dotyczy skryptu, ktory nie dziala, a problemu "jak mam sie za to zabrac"..

Otoz, w moim programie stworzylam plik na Tablice Wynikow.
Zeby go nieco uchronic przed recznym poprawianiem i uniknac zlego wyswietlania chce aby moj program wczytywal te zawartosc do pliku i sprawdzil czy jest wlasciwie posortowana. Potem wyselekcjonowal to co powinien .. i wyswietlil na ekran...

plik ma zawierac 3 kolumny danych. Imie gracza, punkty, oraz poziom

W tym celu stworzylam sobie strukture

struct WG
{
    string nazwaGracza;
    int punktyWG;
    int poziomWG;
};

te strukture wczytuje do kontenera. i z pliku zczytuje odpowiednie dane. Do tego momentu jest wszystko cacy :)

docelowo chce aby wyniki byly wyswietlane dla kazdego poziomu osobno.

Czy moge to posegregowac w ramach 1 tablicy, czy musze dane z "duzej " tablicy skopiowac do 5 mniejszych tablic ( mam 5 poziomow), czy moze jest jakis inny lepszy sposob na rozwiazanie problemu ??

P.S nie mam kompilatora c++11 wie ci lambda sie nie pobawie... prosze o pomoc jak sie za to zabrac.

Probowalam zrobic to metoda babelkowa... ale dziwnie sie ten vector zachowuje funkcje.

Moj pomysl byl taki aby porownac, wpisac do zmiennej testowej .. potem usuwac elementy i w ich miejsce wkladac nowe. Niestety uzywajac erase() lub insert() debugger zwraca blad ze nie sa to elementy struktury...

zamiana znacznika [code] na <code class="cpp"> - @furious programming

0

Zalozylam konto..

przepisze te strukture, zeby nie bylo :
Powiedzmy ze do celow testowych niech wyglada tak

 
    struct WG
    {
        string name;
        int points;
        int level;

    };

0

użyj std::set i operator<

#include <iostream>
#include <set>

struct A
{
    std::string name;

    int data;

    bool operator<(A const& o) const {
        return name < o.name ? true : name == o.name ? data < o.data ? true : false : false;
    }
};

int main()
{
    std::set<A> s;
    s.insert(A { "A", 3 });
    s.insert(A { "Z", 1 });
    s.insert(A { "B", 1 });
    s.insert(A { "A", 1 });

    for(auto const& e : s) {
        std::cout << e.name << " " << e.data << std::endl;
    }
}

chyba nie pomyliłem się w funkcji operatora

http://melpon.org/wandbox/permlink/d1kXtmECWwywBOZv

edit:
post ma na celu pokazać jak można posortować, nie wczytywałem się w nic więcej

0

eeee no chyba skrot myslowy byl za duzy.. bo niestety nie bardzo jestem w stanie to rozkminic....

0

i tu rodzi sie problem bo ja znam francuski :D

to znaczy.. poki co jestem na tym etapie n00bostwa, ze latwiej rozumiem programy ktore maja nazwy zmiennych "opisowe"...

twoj kod zawiera wiele elementow, ktore gdzies tam pojedynczo rozumiem, ale jak sa w calosci to tak jakby bylo to napisane po chinsku :D.

czy z moim pomyslem czyli struktura wlozona do vectora nie daloby sie tego rozwiazac ???

0

Przykład od @gośćabc jest nieco nieoptymalny zaś krótki. Zobacz przykład funkcji sort w dokumentacji tam jest dłuższy ale prostszy kod.

0

no juz zaczyna byc nieco lepiej... ale nie rozumiem tej czesci...

WG() {}
    WG(const string& name, int points, int level)
      : name(name), points(points), level(level) {}
 
   
 bool operator<(WG const& o) const {
    	// zwracasz true jesli obiekt "*this" ma wystepowac przed obiektem "o" po posortowaniu
        return name < o.name || (name == o.name && points < o.points);

 

program nie musi byc zbyt opytymalny, gdyz docelowo tablica ma zawierac 50 elementow, wiec jakie by to sortowanie nie bylo, czasy beda male. Oczywiscie moze sie zdarzyc ze uzytkownik wpisze do pliku wiecej rekordow ( zeby oszukac program) ale i tak bede wybierac z nich tylko 50.. wiec sortowania bede musiala miec 2.. pierwsze ktore mi wyluska poziomy.. a nastepnie posortuje punkty w ramach poziomow...

0

A po takim uproszczeniu:

bool operator<(WG const& o) const { return name!=o.name?name<o.name:points<o.points; }

jasne?

0

wstyd przyznac ale dalej nie...

sam ten zapis :

 
return name!=o.name?name<o.name:points<o.points;

jest znajomy.. chociaz sama nigdy tego nie uzywam to przypomina mi to

(warunek) ? (wyrażenie, gdy warunek jest prawdziwy) : (wyrażenie, gdy warunek jest fałszywy)
wiec zakladam ze to wlasnie to.

aha tutaj tez jest czesc niejasna

 
    for(auto const& e : s) {
        std::cout << e.name << " " << e.data << std::endl;

wczesniej pojawilo sie o ... tutaj jest e....

i wciaz mam problem ze zrozumieniem roznicy wskaznika od referencji... dla mnie to ciagle jest to samo.... mam kilka podrecznikow do C++... ale jakos nie bardzo a w tym zapisie powyzej tym bardziej juz nie kumam.. w tym drugim kodzie po co tam jest dwukropek ?

0

wskaźnik jest obiektem, a referencja nim nie jest, to jest główna różnica

a ta pętla to jest c++11 ranged for;

dla każdego elementu (e) z (:) kontenera wybiera value czyli w tym przypadku obiekty typu A i operuje sobie na nim

0

tu mam kod ktory robilam wcozraj do pobrania danych do tablicy

    struct AAA
    {
        string name;
        int points;
        int level;

    };
int main()
{
    cout << "Hello world!" << endl;


    vector < AAA > tablica;
    ifstream flux;
    flux.open( "pliczek.txt" ,ios::in);

    int i=1;
    while ( !flux.eof() & i <= 10)
    {
    tablica.push_back(AAA());
    flux >> tablica[i-1].name >> tablica[i-1].points >> tablica[i-1].level;
    if ((i == 1) && ( flux.eof() ))
    {
        cout << "nikt jeszcze nie wygral, badz pierwszy" << endl;
    } else {
        cout << i << ". " << tablica[i-1].name << " " << tablica[i-1].points << " " << tablica[i-1].level << endl;
        i++;
    }
}
for (; i <=10; i++)
{
          cout << i << ".   "<< endl;
};

 

moj kompilator nie obsluguje c++11


No ok.. no to zaczynamy.. wkleje calosc

 

void zapis_wyniku (string plik)
{
    cout << "Wynik zapisze do pliku : " << plik << endl;
    ifstream flux;
    flux.open( plik.c_str(), ios::in  );
    vector < WG > tablicaWynikow;
    int i=1;
    while ( !flux.eof() & i <= 10)
    {
        tablicaWynikow.push_back(WG());
        flux >> tablicaWynikow[i-1].nazwaGracza >> tablicaWynikow[i-1].punktyWG >> tablicaWynikow[i-1].poziomWG;

        if ((i == 1) && ( flux.eof() ))
        {
            cout << "nikt jeszcze nie wygral, badz pierwszy" << endl;
        }
        else
        {
            cout << i << ". " << tablicaWynikow[i-1].nazwaGracza << " " << tablicaWynikow[i-1].punktyWG << " " << tablicaWynikow[i-1].poziomWG << endl;
            i++;
        }
    }
    for (; i <=10; i++)
    {
        cout << i << ".   "<< endl;
    }


    vector < WG > ::iterator it_WG = tablicaWynikow.end();
    for (int a = 1; i < tablicaWynikow.size(); i++ )
        {
            for (; it_WG >= tablicaWynikow.begin(); it_WG--)
            {
                if( it_WG.poziomWG< (it_WG.poziomWG-1) )
                {
                    WG bufor;
                    bufor = (*it_WG-1);
                    * (it_WG - 1) = it_WG;
                    * it_WG = bufor;
                }
            }
        }



    flux.close();
    tablicaWynikow.clear();


}

tutaj mi sprawia to o tyle problem, ze nie jest to zwykla tablica intow, tylko mieszanych danych.. bo sa dane bedace stringami i intami. A ja do tej pory iterowalam tylko po tablicy 1 wymiarowej...

0

pierwszy błąd tutaj for (; it_WG >= tablicaWynikow.begin(); it_WG--)

!= zamiast >= wygoogluj sobie jak się iteruje po wektorze elementów

drugi tutaj 'if( it_WG.poziomWG< (it_WG.poziomWG-1) )' porównujesz iteratory a nie ich zawartość, poczytaj o dereferencji iteratorów

edit czy to się w ogóle kompiluje? :D

tak powinno być 'it_WG->poziomWG' lub '(*it_WG).poziomWG'

edit:

tutaj jest chyba mnóstwo błędów logicznych, a ja już muszę spadać, ten iterator przed forem też nie jest zbyt ciekawy, musisz sobie przemyśleć logikę bardziej dogłębnie, bo ja nie wiem co chcesz tutaj osiągnąć, jeżeli chcesz iterować od tyłu to jest reverse_iterator, dzięki niemu unikniesz tego -1 w kodzie; popróbuj

0

no wlasnie sie nie kompilowalo.. zamiana operatora porownania zostala rpzeze mnie dokonana wczesniej.. po prostu zanim to wstawilam mialam tam jeszcz eco innego ( nie iteratory) i najnormalniej w swiecie zapomnialam o tym ;) - zeby tak sie wtlumaczyc...

w drugim przypadku nie znnajduje wytlumaczenia dla swojej niewiedzy :)

dzieki za podpowiedz ;)

kombinuje wiec dalej.


Wyszlo cos takiego... teoretycznie nawet dziala :D ale brzydko wyglada :P

 
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>

using namespace std;
    struct WG
    {
        string nazwaGracza;
        int punktyWG;
        int poziomWG;

    };

int main()
{
    cout << "Hello world!" << endl;


    vector < WG > tablicaWynikow;
    ifstream flux;
    flux.open( "pliczek.txt" ,ios::in);
int i=1;

   while ( !flux.eof() & i <= 10)
    {
        tablicaWynikow.push_back(WG());
        flux >> tablicaWynikow[i-1].nazwaGracza >> tablicaWynikow[i-1].punktyWG >> tablicaWynikow[i-1].poziomWG;

        if ((i == 1) && ( flux.eof() ))
        {
            cout << "nikt jeszcze nie wygral, badz pierwszy" << endl;
        }
        else
        {
            cout << i << ". " << tablicaWynikow[i-1].nazwaGracza << " " << tablicaWynikow[i-1].punktyWG << " " << tablicaWynikow[i-1].poziomWG << endl;
            i++;
        }
    }
    for (; i <=10; i++)
    {
        cout << i << ".   "<< endl;
    }
cout << "lecimy dalej " << endl;

    vector < WG > ::iterator it_WG = tablicaWynikow.begin();
    vector < WG > ::iterator it_WG2 = it_WG+1;

    cout << "tablica wynikow size "  <<  tablicaWynikow.size() << endl;

    for ( int a = 1; a < tablicaWynikow.size() ; a++)
    {
            for (it_WG=tablicaWynikow.begin(); it_WG != tablicaWynikow.end() - 1 ; it_WG++)
            {
                if (( it_WG -> poziomWG > it_WG2 -> poziomWG))
                {

                    WG bufor;
                    bufor.nazwaGracza = it_WG2 ->nazwaGracza;
                    bufor.poziomWG = it_WG2 ->poziomWG;
                    bufor.punktyWG = it_WG2 ->punktyWG;

                    * it_WG2 = *it_WG;

                    it_WG ->nazwaGracza = bufor.nazwaGracza;
                    it_WG ->poziomWG = bufor.poziomWG ;
                    it_WG ->punktyWG = bufor.punktyWG;
                }


                it_WG2++;

            }

            it_WG = tablicaWynikow.begin();
            it_WG2 = it_WG+1;
    }

for ( int a = 1; a < tablicaWynikow.size() ; a++)
{
        for (it_WG=tablicaWynikow.begin(); (it_WG != tablicaWynikow.end() - 1 ) ; it_WG++)
            {
if (( it_WG -> punktyWG > it_WG2 -> punktyWG) && (it_WG ->poziomWG) == (it_WG2 ->poziomWG) )
                {

                    WG bufor;
                    bufor.nazwaGracza = it_WG2 ->nazwaGracza;
                    bufor.poziomWG = it_WG2 ->poziomWG;
                    bufor.punktyWG = it_WG2 ->punktyWG;

                    * it_WG2 = *it_WG;

                    it_WG ->nazwaGracza = bufor.nazwaGracza;
                    it_WG ->poziomWG = bufor.poziomWG ;
                    it_WG ->punktyWG = bufor.punktyWG;
                }

it_WG2++;
            }

  it_WG = tablicaWynikow.begin();
            it_WG2 = it_WG+1;
}

for (int i = 1; i< 10; i++)
{

cout << i << ". " << tablicaWynikow[i-1].nazwaGracza << " " << tablicaWynikow[i-1].punktyWG << " " << tablicaWynikow[i-1].poziomWG << endl;


}



flux.close();


}


Program DZIALA !!! :) jeaaaa < taniec porabanej >

niemniej jednak.. jak widzicie zajelo to spoooro lini ;) a to w sumie nie wszystko co musze z tym zrobic :P
tyle ze zastanawiam sie co moglabym zmienic, aby go ukrocic.. oczywiscie na moim poziomie n00bostwa :)
i blaagam :D tlumaczycie to blondynie.. farbowanej co prawda na rudy.. ale blond to stan umyslu :) i szpachla tego nie zakryje :) wiec powoli jak debilowi prosze tlumaczyc ;)

2

sformatuj kod na ladniejszy. Bo tego sie nie chce czytac nawet...

EDIT. Sformatowalem za Ciebie


#include <iostream>
#include <cstdlib>
#include <ctime>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
 
using namespace std;
    
struct WG
{
    string nazwaGracza;
    int punktyWG;
    int poziomWG; 
};
 
int main()
{
    cout << "Hello world!" << endl;
    vector < WG > tablicaWynikow;
    ifstream flux;
    flux.open( "pliczek.txt" ,ios::in);
	int i=1;
 
   	
    while ( !flux.eof() & i <= 10)
    {
        tablicaWynikow.push_back(WG());
        flux >> tablicaWynikow[i-1].nazwaGracza >> tablicaWynikow[i-1].punktyWG >> tablicaWynikow[i-1].poziomWG;
 
        if (i == 1) && flux.eof())
        {
            cout << "nikt jeszcze nie wygral, badz pierwszy" << endl;
        }
        else
        {
            cout << i << ". " << tablicaWynikow[i-1].nazwaGracza << " " << tablicaWynikow[i-1].punktyWG << " " << tablicaWynikow[i-1].poziomWG << endl;
            i++;
        }
    }
    for (; i <=10; i++)
    {
        cout << i << ".   "<< endl;
    }
    cout << "lecimy dalej " << endl;
 
    vector < WG > ::iterator it_WG = tablicaWynikow.begin();
    vector < WG > ::iterator it_WG2 = it_WG+1;
 
    cout << "tablica wynikow size "  <<  tablicaWynikow.size() << endl;
 
    for ( int a = 1; a < tablicaWynikow.size() ; a++)
    {
            for (it_WG=tablicaWynikow.begin(); it_WG != tablicaWynikow.end() - 1 ; it_WG++)
            {
                if (( it_WG -> poziomWG > it_WG2 -> poziomWG))
                {
                    WG bufor;
                    bufor.nazwaGracza = it_WG2 ->nazwaGracza;
                    bufor.poziomWG = it_WG2 ->poziomWG;
                    bufor.punktyWG = it_WG2 ->punktyWG;
                    * it_WG2 = *it_WG;
                    it_WG ->nazwaGracza = bufor.nazwaGracza;
                    it_WG ->poziomWG = bufor.poziomWG ;
                    it_WG ->punktyWG = bufor.punktyWG;
                }
                it_WG2++;
            }
            it_WG = tablicaWynikow.begin();
            it_WG2 = it_WG+1;
    }
 
    for ( int a = 1; a < tablicaWynikow.size() ; a++)
    {
        for (it_WG=tablicaWynikow.begin(); (it_WG != tablicaWynikow.end() - 1 ) ; it_WG++)
        {
            if (( it_WG -> punktyWG > it_WG2 -> punktyWG) && (it_WG ->poziomWG) == (it_WG2 ->poziomWG) )
            {
 
                WG bufor;
                bufor.nazwaGracza = it_WG2 ->nazwaGracza;
                bufor.poziomWG = it_WG2 ->poziomWG;
                bufor.punktyWG = it_WG2 ->punktyWG;

                * it_WG2 = *it_WG;

                it_WG ->nazwaGracza = bufor.nazwaGracza;
                it_WG ->poziomWG = bufor.poziomWG ;
                it_WG ->punktyWG = bufor.punktyWG;
            }
            it_WG2++;
        }
        it_WG = tablicaWynikow.begin();
        it_WG2 = it_WG+1;
    }
 
    for (int i = 1; i< 10; i++)
    {
        cout << i << ". " << tablicaWynikow[i-1].nazwaGracza << " " << tablicaWynikow[i-1].punktyWG << " " << tablicaWynikow[i-1].poziomWG << endl;
    }
    flux.close();
}

teraz kod podziel na funkcje, funkcje powinny robic JEDNO ZADANIE nie wiecej. Czyli np WyswietlanieWynikow(); Jak podzielisz kod na fukncje to zobaczysz ile bezsensowych rzeczy zrobilas i jak mozna to uproscic ;)

W main powinno byc ja wiem? z 5 lini kodu. Funkcje moga miec poziomy abstrakcji np
Masz jedna funkcje
ZrobKanapke()
a w tej funkcji masz
WyciagnijChleb()
PosmarujMaslem()
PolozSzynke()
NawalKeczupu()

a w tamtych masz kolejne warstwy jak w masle sprawdzic czy maslo jest i nie jest twarde itd itp

0

formatu dokona program, aczkolwiek wydawalo mi sie ze przepuszczalam go przez format autmatyczny code blocksa.. ale mniejsza z tym. To tutaj to jest wersja testowa. Docelowo jest to wlasnie funkcja ktora pozniej wywolam z poziomu main

0
struct WG
  {
   char player[32];
   unsigned points,level;
   bool operator<(const WG &w)const
     {
      if(points!=w.points) return points<w.points;
      if(level!=w.level) return level<w.level;
      return this<&w;
     }
  };
WG *HallOfFame(const char *player,unsigned points,unsigned level) // wywołanie: HallOfFame(NULL,0,0) zwróci aktualną tablice
  {
   static WG tb[]={{"none",0,0},{"none",0,0},{"none",0,0},{"none",0,0},{"none",0,0},{"none",0,0},{"none",0,0},{"none",0,0},{"none",0,0},{"none",0,0},{"none",0,0}};
   const unsigned tbLast=sizeof(tb)/sizeof(*tb)-1;
   ifstream fin("HallOfFame.bin",ios::in|ios::binary);
   fin.read((char*)tb,sizeof(tb));
   fin.close();
   if(player)
     {
      strcpy(tb[tbLast].player,player);
      tb[tbLast].points=points;
      tb[tbLast].level=level;
      sort(tb,tb+tbLast+1);
      ofstream fin("HallOfFame.bin",ios::out|ios::binary);
      fin.write((char*)tb,sizeof(tb));
     }
   return tb;
  }
0

@_13th_Dragon eeee noooo yyyy i to sa te momenty kiedy ja zastanawiam sie czy programujemy w tym samym jezyku :)

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