Přidat otázku mezi oblíbenéZasílat nové odpovědi e-mailemVyřešeno Pomozte s programem v C++...

Zdravím,
potřebuju tuhle: http://java.sun.com/j2se/1.4.2/docs/api/java/util/A rrayList.html třídu pro C++, asi by nebyl problém si něco takového napsat, ale raději se zeptám jesti už něco takového neexistuje, abych si ušetřil psaní...:-) Nemusí to být úplně stejné alespoň principiálně. Řeším příklad Malý vysokoškolský studijní systém. Rozvrhl jsem si to nějak takto:
1. třída: Osoba
2. třídy: Zaměstnanec, Student - dědí z třídy Osoba
3. třída: Doktorand - dědí z třídy Zaměstnanec i Student (doktorand je v podstatě i zaměstnanec, dostává plat) :-)
4. třída: Zkouška
5. třídy: SeznamStudentů, SeznamZaměstnanců, SeznamZkoušek, SeznamDoktorandů - dětí z třídy ArrayList, a doplním pouze metody, jako např. najdiStudenta(int id), tiskSeznamu() apod.

Každý student a doktorand bude mít privatní atribut kolekci (ArrayList) zkoušek na které se zapsal.

PS: Snad jsem to napsal srozumitelně. Jedná se o projekt k zápočtu z C++...:-) Budu vděčný za každé připomínky k mojí úvaze... Má někdo podobnou třídu, jako je zmiňovaný Javovský ArrayList pro C++ (měla by to být třída, která je Template)?

Díky! :beer:
MaSo

Jsou zobrazeny jen nové odpovědi. Zobrazit všechny
Předmět Autor Datum
Jak udělat v C++ aby metoda vracela odkaz na null? Mám toto: Student SeznamStudentu :: najdiStudent…
MaSo 01.06.2007 20:59
MaSo
NULL je ukazovateľ, zatiaľ čo tvoja funkcia má vrátiť inštanciu triedy Student a nie ukazovateľ na i…
los 02.06.2007 10:09
los
Díky, za obsáhlou odpověď. :beer: 2. Prerobiť zoznam študentov tak, aby obsahoval ukazovatele. V pr…
MaSo 02.06.2007 14:41
MaSo
Keď to prerobíš na ukazovatele, budeš musieť k vlastnostiam a metódam objektu pristupovať cez operát…
los 02.06.2007 21:00
los
Losi, díky moc! :beer: Nevím, co bych si bez tebe počal... Předělal jsem to teda tak, aby seznamy ob…
MaSo 03.06.2007 14:34
MaSo
Po tom ako odstrániš študenta zo zoznamu, nemôžeš ďalej zvyšovať iterátor, takže tam musíš dať break…
los 03.06.2007 17:37
los
Tak hlavně díky tobě, jsem program dokončil. Zítra (vlastně už dneska :-)) ho předvedu u zkoušky, sn…
MaSo 04.06.2007 00:06
MaSo
Tak program se líbil, ale u zkoušky jsem trochu domotal včasnou a pozdní vazbu, takže nakonec za dvě… poslední
MaSo 04.06.2007 10:23
MaSo

Jak udělat v C++ aby metoda vracela odkaz na null? Mám toto:

Student SeznamStudentu :: najdiStudenta(int id)
{
      list<Student>::iterator i;
     
      for(i=studenti.begin(); i != studenti.end(); ++i)
      {
       if ((*i).getId() == id) return (*i);
      }
      return null; // toto samozdrejme neprojde kompilaci :-(, tohle jsem si pujcil z Javy :-)
}

Když se student nenajde, tak chci vrátit null. Ví někdo, jak na to?

NULL je ukazovateľ, zatiaľ čo tvoja funkcia má vrátiť inštanciu triedy Student a nie ukazovateľ na inštanciu.

Riešení je viacero:
1. Použiť namiesto triedy std::list triedu std::map, ktorá má funkciu pre hľadanie podľa kľúča.
2. Prerobiť zoznam študentov tak, aby obsahoval ukazovatele. V prípade neúspechu sa vráti NULL.
3. Zmeniť vyhľadávaciu funkciu tak, aby vrátila iterátor. V prípade neúspechu sa vráti studenti.end().
4. Použiť vzor Null Object. V prípade neúspechu sa vráti nejaká dohodnutá inštancia, reprezentujúca žiadneho študenta.

Edit: Asi si už na to prišiel, ale pre istotu: Ak máš kontajner (std::list, std::map, ...), do ktorého vkladáš priamo inštancie nejakej triedy a nie ukazovatele, tak tá trieda musí implementovať minimálne kopírovací konštruktor, aby to vôbec fungovalo.

Díky, za obsáhlou odpověď. :beer:

2. Prerobiť zoznam študentov tak, aby obsahoval ukazovatele. V prípade neúspechu sa vráti NULL.

Když to předělám na ukazatele, budu moc při procházení seznamem volat metody? Např.:

void SeznamStudentu :: vypisSeznam()
{
     list<Student>::iterator i;
      for(i=studenti.begin(); i != studenti.end(); ++i)
      {
        (*i).vypisStudenta();
      }
}

Nějak mi taky neleze do hlavy jak ten seznam zadefinovat, aby obsahoval pointery... Zřejmě takto:

std::list<Student*> studenti

Ale jak pak udělat metodu přidej studenta? Teď to mám takhle:

void SeznamStudentu :: pridejStudenta(Student s)
{
     studenti.push_back(s);
     pocetStudentu++;
}

4. Použiť vzor Null Object. V prípade neúspechu sa vráti nejaká dohodnutá inštancia, reprezentujúca žiadneho študenta.

Tohle se mi zamlouvá... viz: http://blog.vyvojar.cz/lazo/archive/2005/06/20/6177 .aspx

Keď to prerobíš na ukazovatele, budeš musieť k vlastnostiam a metódam objektu pristupovať cez operátor -> namiesto obyčajnej bodky. Takže ten kód bude vyzerať nejako takto:

void SeznamStudentu::vypisSeznam() {
  list<Student*>::iterator i;

  for (i = studenti.begin(); i != studenti.end(); ++i)
    (*i)->vypisStudenta();
}

A ďalej:

void SeznamStudentu::pridejStudenta(Student* s) {
     studenti.push_back(s);
     ++pocetStudentu; // pocetStudentu == studenti.size()
}

Použitie:

Student* s = new Student();
seznamStudentu.pridejStudenta(s);

Študentov potom samozrejme treba niekedy uvoľniť z pamäte.

Použitiu Null objektu by som sa vyhol, ak na to nemáš nejaký pádny dôvod (.šámeN).

Losi, díky moc! :beer: Nevím, co bych si bez tebe počal... Předělal jsem to teda tak, aby seznamy obsalovaly pointery, ale ještě se mi nepodařilo zprovoznit odebrání studenta ze seznamu na základě jeho id...:-(

Napadly mě dvě varianty, bohužel ani jedna mi nepracuje...
1.

void SeznamStudentu :: odeberStudenta(int id)
{
     list<Student*>::iterator i;
     for(i=studenti.begin(); i != studenti.end(); i++)
      {
       if (((*i)->getId()) == id) studenti.remove((*i));
      }
}

2.

void SeznamStudentu :: odeberStudenta(int id)
{
     list<Student*>::iterator i;
     for(i=studenti.begin(); i != studenti.end(); i++)
      {
       if (((*i)->getId()) == id) studenti.erase(i));
      }
}

Program jde normálně zkompilovat, ale když se pokusím zavolat metodu na odebrání, končím na Windows hlášce, že program provedl neplatnou operaci...:-|

PS: V metodách ještě nemám zohledněné co dělat když se student s daným id nenajde... To dodělám, až mi to bude chodit aspoň takhle.

PSS:
Medota najdiStudenta(int id) mi jede, nedalo by se ji nějak využit při odebíraní?

Student* SeznamStudentu :: najdiStudenta(int id)
{
     list<Student*>::iterator i;
     for(i=studenti.begin(); i != studenti.end(); i++)
      {
       if (((*i)->getId()) == id) return (*i);
      }
      return NULL;
}

Javě by to šlo napsat třeba takto:

 public void odeberStudenta(int id)
 {
    Student s;
    ListIterator <Student> i = studenti.listIterator();
    while(i.hasNext())
      {
        s = (Student)i.next();
        if (s.getId() == id)
        {   
           studenti.remove(studenti.indexOf(s));
        }
        else System.out.println("Student s ID "+id+" nenalezen"); // vyjimka by byla asi lepsi
      }
}

Po tom ako odstrániš študenta zo zoznamu, nemôžeš ďalej zvyšovať iterátor, takže tam musíš dať break. Debugger by ti mal ukázať presne, kedy to spadne.

void SeznamStudentu::odeberStudenta(int id) {
  list<Student*>::iterator i;

  for (i = studenti.begin(); i != studenti.end(); ++i)
    if ((*i)->getId() == id) {
      studenti.erase(i);
      break;
    }
}

Zpět do poradny Odpovědět na původní otázku Nahoru