Matematické Fórum

Nevíte-li si rady s jakýmkoliv matematickým problémem, toto místo je pro vás jako dělané.

Nástěnka
!! 17.06.2018 (Jel.) Khanova škola zve nadšence ke spolupráci na překladech návodů pro učitele a rodiče.
! 04.11.2016 (Jel.) Čtete, prosím, před vložení dotazu, děkuji!
17.01.2016 (Jel.) Rok 2016 s novými a novějšími krystaly od kolegy Pavla!
17.01.2016 (Jel.) Nabídka knih z oborů matematiky, fyziky, chemie
23.10.2013 (Jel.) Zkuste před zadáním dotazu použít některý z online-nástrojů, konzultovat použití můžete v sekci CAS.

Nejste přihlášen(a). Přihlásit

#1 30. 07. 2019 16:41 — Editoval Anonymystik (30. 07. 2019 16:44)

Anonymystik
Příspěvky: 560
Reputace:   45 
 

Dotaz k třídám v C++ (implicitní parametr typu ukazatel na objekt)

Zdravím, mám dotaz a je maličko náročnější ho položit.
--
1) Uvažme dvě třídy: Node, Tree.
2) Třída Tree obsahuje metodu Add.
3) Tato metoda předává jeden ze vstupních parametrů (root) jako referenci na ukazatel na objekt typu Node - tedy v hlavičce je Node*& root.
4) Nyní bych chtěl dosáhnout toho, aby pokud se do vstupu tento parametr nevyplní, automaticky se bral typu NULL.
5) Jenže to nejde, protože formálně parametr předávám jako referenci na ukazatel, kdežto NULL je předání konstantní hodnoty.
6) Takže se nabízí v paměti vyhradit místo pro jednu proměnnou typu Node* (tj. ukazatel) - pojmenujme si ji třeba "NodeNULL" - a v hlavičce mé metody Add vložit jako implicitní parametr tento NodeNULL (místo původního NULL).
7) Tohle funguje, ale je to prasárna v tom smyslu, že NodeNULL není zapouzdřen dovnitř do třídy Node.
8) Jenže při definici třídy nemůžu vytvářet rovnou její instance (tohle by zjevně měla být konstantní statická instance). Takže to dovnitř do definice třídy nezapouzdřím.
--
Doufám, že je aspoň trochu tušit, oč mi jde. Poradíte?


"Do you love your math more than me?"   "Of course not, dear - I love you much more."   "Then prove it!"   "OK... Let R be the set of all lovable objects..."

Offline

 

#2 30. 07. 2019 16:44

Stýv
Vrchní cenzor
Příspěvky: 5316
Reputace:   201 
Web
 

Re: Dotaz k třídám v C++ (implicitní parametr typu ukazatel na objekt)

Anonymystik napsal(a):

3) Tato metoda předává jeden ze vstupních parametrů (root) jako referenci na ukazatel na objekt typu Node - tedy v hlavičce je Node*& root.

Proč?

Offline

 

#3 30. 07. 2019 16:48

Anonymystik
Příspěvky: 560
Reputace:   45 
 

Re: Dotaz k třídám v C++ (implicitní parametr typu ukazatel na objekt)

↑ Stýv: No, chci, aby se v průběhu hodnota ukazatele mohla měnit.


"Do you love your math more than me?"   "Of course not, dear - I love you much more."   "Then prove it!"   "OK... Let R be the set of all lovable objects..."

Offline

 

#4 30. 07. 2019 17:01

Stýv
Vrchní cenzor
Příspěvky: 5316
Reputace:   201 
Web
 

Re: Dotaz k třídám v C++ (implicitní parametr typu ukazatel na objekt)

↑ Anonymystik: A nešlo by použít místo reference pointer? A když už používáš pointery, nešly by použít chytré pointery?

Offline

 

#5 30. 07. 2019 17:05

Anonymystik
Příspěvky: 560
Reputace:   45 
 

Re: Dotaz k třídám v C++ (implicitní parametr typu ukazatel na objekt)

↑ Stýv: Šlo, ale měl bych ukazatel na ukazatel. Vzhledem k rekurzivní povaze mé metody Add se toho trochu bojím, nejsem zase tak zkušený programátor. Chytré pointery neznám. Myslíš, že by mému problému nějak pomohly? (zatím neřeším mazání)


"Do you love your math more than me?"   "Of course not, dear - I love you much more."   "Then prove it!"   "OK... Let R be the set of all lovable objects..."

Offline

 

#6 30. 07. 2019 17:58

Stýv
Vrchní cenzor
Příspěvky: 5316
Reputace:   201 
Web
 

Re: Dotaz k třídám v C++ (implicitní parametr typu ukazatel na objekt)

Ukzatel na ukazatel už jsem viděl, referenci an ukazatel ještě ne. :-)
Nevím, co ti může nebo nemůže pomoct, jelikož netuším, co se to vlastně pokoušíš naprogramovat. Ale obecně je dobré se hloupým pointerům spíš vyhnout, pokud to jde.

Offline

 

#7 30. 07. 2019 18:57 — Editoval Anonymystik (30. 07. 2019 19:23)

Anonymystik
Příspěvky: 560
Reputace:   45 
 

Re: Dotaz k třídám v C++ (implicitní parametr typu ukazatel na objekt)

↑ Stýv: Pokouším se objektově implementovat binární vyhledávací strom. Když se pokouším vložit nový prvek, podívám se, jestli v daném vrcholu je prázdno nebo není. Pokud je tam prázdno, uložím prvek do daného vrcholu. Pokud není, podívám se, jestli hodnota klíče je menší/větší než klíč v daném vrcholu. Podle toho pak zavolám metodu Add rekurzivně na levý nebo pravý podstrom. Přitom jeden z parametrů Add je právě ukazatel na vrchol daného podstromu. Kdyby tam ale bylo prázdno, vlastně chci tento vrchol měnit, takže to musím předat jako referenci. Proto ta reference na ukazatel.
No a ten implicitní parametr chci proto, že když volám funkci na celý strom, jako parametr se vezme kořen stromu, jehož ukazatel je jeden z atributů stromu. Jenže samozřejmě nikomu nic do žádné adresy kořene není, tam chci jen říct "přidej prvek X do stromu Y". A právě na to použiju implicitní parametr.
(Poznámka: ano, vím, že by šly použít kontejnery a iterátory, ale to není point, chci se na tom spíš učit.)


"Do you love your math more than me?"   "Of course not, dear - I love you much more."   "Then prove it!"   "OK... Let R be the set of all lovable objects..."

Offline

 

#8 30. 07. 2019 22:09

Stýv
Vrchní cenzor
Příspěvky: 5316
Reputace:   201 
Web
 

Re: Dotaz k třídám v C++ (implicitní parametr typu ukazatel na objekt)

To mi přijde poněkud neobjektový. Já bych v tom případě prázdného podstromu nejprve vyrobil nový podstrom a na něm volal metodu Add.
A tady opravdu jsou na místě chytré ukazatele, konkrétně unique_ptr.

Offline

 

#9 30. 07. 2019 22:32

Anonymystik
Příspěvky: 560
Reputace:   45 
 

Re: Dotaz k třídám v C++ (implicitní parametr typu ukazatel na objekt)

↑ Stýv: Koukám, že ty bys nevyráběl v rámci stromu nový vrchol, ale rovnou celý podstrom ... to mě nenapadlo. Na ty chytré ukazatele kouknu.


"Do you love your math more than me?"   "Of course not, dear - I love you much more."   "Then prove it!"   "OK... Let R be the set of all lovable objects..."

Offline

 

#10 30. 07. 2019 22:58

Stýv
Vrchní cenzor
Příspěvky: 5316
Reputace:   201 
Web
 

Re: Dotaz k třídám v C++ (implicitní parametr typu ukazatel na objekt)

↑ Anonymystik: Ten podstrom, co bych vyráběl, by se skládal jenom z jednoho vrcholu. Jak na to znova koukám, nejsou mi jasný dvě věci:
1) Co má být ta třída Tree?
2) Na co má být ukazovat ten ukazatel z "Přitom jeden z parametrů Add je právě ukazatel na vrchol daného podstromu."?

Offline

 

#11 30. 07. 2019 23:01 — Editoval Anonymystik (30. 07. 2019 23:09)

Anonymystik
Příspěvky: 560
Reputace:   45 
 

Re: Dotaz k třídám v C++ (implicitní parametr typu ukazatel na objekt)

Koukám, pojmenoval jsem tu třídu hloupě Strom, nikoliv Tree; taky jsem přejmenoval NodeNULL na Nic, aby to bylo kompaktnější - občas mám problém vymýšlet názvy pro své třídy a proměnné. Nic to ale na problému nemění.

Poznámka: metody Remove, RemoveMax, RemoveMin nejsou zatím napsané.

Můj kód zatím:

Code:

#include <iostream>
#include <conio.h>

using namespace std;

struct Node
{
int obsah;
Node* lSyn;
Node* pSyn;
};

Node* Nic; //Není zapouzdřeno!

class Strom
{
private:
Node* Koren;
int PocetVrcholu;

public:
Strom();
bool Neprazdny();
void Add(int Cislo, Node*& root=Nic, bool Vnejsi=true);
void Remove(int Cislo);
bool Find(int Cislo, Node* root=Nic, bool Vnejsi=true);
void List(Node* root=Nic, bool Vnejsi=true);
int Min(Node* root=Nic);
int Max(Node* root=Nic);
void RemoveMin();
void RemoveMax();
};

Strom::Strom()
{
Koren = NULL;
PocetVrcholu = 0;
};


bool Strom::Neprazdny()
{
if(PocetVrcholu != 0) return true;
 else return false;
};

void Strom::Add(int Cislo, Node*& root, bool Vnejsi)
{
if(Vnejsi) root=Koren;
if(root==NULL) 
 {
 Node* Vrchol = new Node;
 Vrchol->obsah = Cislo;
 Vrchol->lSyn = NULL;
 Vrchol->pSyn = NULL;
 root = Vrchol;
 PocetVrcholu++; 
 cout << "Prave ukladam cislo " << Cislo << " do stromu!" << endl;
 if(PocetVrcholu==1) Koren = root;
 }
 else if(Cislo == (root->obsah)) cout << "Cislo " << Cislo << " jiz bylo ve stromu ulozeno!" << endl;
  else if (Cislo < (root->obsah)) Add(Cislo, root->lSyn, false);
   else Add(Cislo, root->pSyn, false);
};


bool Strom::Find(int Cislo, Node* root, bool Vnejsi)
{
if(Vnejsi) root=Koren;
if(root==NULL) return false;
if(Cislo==(root->obsah)) return true;
 else if(Cislo < (root->obsah)) Find(Cislo, root->lSyn, false);
  else Find(Cislo, root->pSyn, false);
};


int Strom::Max(Node* root)
{
if(root==Nic) root = Koren;
if(root==NULL)
 {
 cout << "Chybne pouziti metody Max() na prazdny strom!";
 exit(0);
 };
if(root->pSyn != NULL) return Max(root->pSyn);
 else return (root->obsah);
};


int Strom::Min(Node* root)
{
if(root==Nic) root = Koren;
if(root==NULL)
 {
 cout << "Chybne pouziti metody Min() na prazdny strom!";
 exit(0);
 };
if(root->lSyn != NULL) return Min(root->lSyn);
 else return (root->obsah);
};


void Strom::List(Node* root, bool Vnejsi)
{
if(Vnejsi) cout << "Tento strom obsahuje "<< PocetVrcholu << " vrcholu: ";
if(root==Nic) root = Koren;
if(root!=NULL) 
 {
 List(root->lSyn, false);
 cout << root->obsah << " ";
 List(root->pSyn, false);
 };
if(Vnejsi) cout << endl;
};

/*
void Strom::Remove(int Cislo, Node*& root, bool Vnejsi)
{

}; */

int main()
{
Strom T;
T.List();
//cout << "Maximum ve stromu: " << T.Min() << endl;
T.Add(4);
T.Add(4);
T.Add(2);
T.Add(1);
T.Add(6);
T.Add(5);
T.Add(8);

for(int i=0; i<10; i++) 
 if(T.Find(i)) cout << "Cislo " << i << " nalezeno!" << endl; 

T.List();

return 0;
};

"Do you love your math more than me?"   "Of course not, dear - I love you much more."   "Then prove it!"   "OK... Let R be the set of all lovable objects..."

Offline

 

#12 30. 07. 2019 23:06

Stýv
Vrchní cenzor
Příspěvky: 5316
Reputace:   201 
Web
 

Re: Dotaz k třídám v C++ (implicitní parametr typu ukazatel na objekt)

Chybí tomu začátek. Zkopíruj to radši sem a nastav syntax highliting, ať se v tom dá trochu vyznat.

Offline

 

#13 30. 07. 2019 23:10 — Editoval Anonymystik (30. 07. 2019 23:12)

Anonymystik
Příspěvky: 560
Reputace:   45 
 

Re: Dotaz k třídám v C++ (implicitní parametr typu ukazatel na objekt)

Promiň, já ten příspěvek vždycky chvilku edituju a opravuju si po sobě chyby.
A ještě: kde se dělá syntax highlighting?


"Do you love your math more than me?"   "Of course not, dear - I love you much more."   "Then prove it!"   "OK... Let R be the set of all lovable objects..."

Offline

 

#14 30. 07. 2019 23:13

Stýv
Vrchní cenzor
Příspěvky: 5316
Reputace:   201 
Web
 

Re: Dotaz k třídám v C++ (implicitní parametr typu ukazatel na objekt)

↑ Anonymystik: Za tím "sem" měl následovat odkaz na https://pastebin.com/ :-)

Offline

 

#15 31. 07. 2019 00:00

Stýv
Vrchní cenzor
Příspěvky: 5316
Reputace:   201 
Web
 

Re: Dotaz k třídám v C++ (implicitní parametr typu ukazatel na objekt)

Tady vidím velký špatný...

1) Tvůj problém se vyřeší sám, když se zbavíš zbytečný třídy Strom a metody přesuneš do třídy Node.

2)
a) Vyhoď #include <conio.h>
b) Místo NULL používej nullptr.
c) Místo hloupých ukazatelů použij chytré ukazatele.

3)
a) Zvykni si používat anglické názvy. Čeština ve zdrojáku jednak vypadá divně, jednak tomu nebude skoro nikdo kromě tebe rozumět.
b) Neboj se plýtvat místem, je to pak přehlednější. Tj. např. místo

Code:

if(Cislo==(root->obsah)) return true;
 else if(Cislo < (root->obsah)) Find(Cislo, root->lSyn, false);
  else Find(Cislo, root->pSyn, false);

piš

Code:

if(Cislo==(root->obsah))
{
    return true;
}
else if(Cislo < (root->obsah))
{
    Find(Cislo, root->lSyn, false);
}
else
{
    Find(Cislo, root->pSyn, false);
}

Offline

 

#16 31. 07. 2019 02:06 — Editoval edison (31. 07. 2019 02:08)

edison
Příspěvky: 1613
Reputace:   36 
 

Re: Dotaz k třídám v C++ (implicitní parametr typu ukazatel na objekt)

Tak třeba pro mě je ten první způsob zápisu přehlednější, protože se vejde víc řádků na obrazovku:-)

dávat { na tři řádky kvůli returnu je rozhodně zbytečné.

Offline

 

#17 31. 07. 2019 10:40 — Editoval Stýv (31. 07. 2019 10:46)

Stýv
Vrchní cenzor
Příspěvky: 5316
Reputace:   201 
Web
 

Re: Dotaz k třídám v C++ (implicitní parametr typu ukazatel na objekt)

↑ edison: Fakt to není přehlednější. Když jsem se na to podíval, viděl jsem hned větev pro případ root==NULL a divil jsem se, kde jsou ty ostatní případy. Až když jsem to začal hodně podrobně studovat, zjistil jsem, že jsou zdrcnutý tam dole.

No a co se týká jednořádkových bloků – taky jsem to dělal dřív podobně, ale co když si usmyslíš, že tam chceš přidat třeba nějakej výpis typu "Hodnota už je ve stromu." nebo cokoliv jinýho? Najednou tam ty závorky budeš muset přidat. A nebo na ně zapomeneš, a vyrobíš bug. Proto je lepší i tyhle jednořádkový bloky už od začátku obalit závorkama.

Whitespacy přidávají na přehlednosti. Pokud je nějaká metoda s tímhle formátováním příliš dlouhá (víc než třeba dvě obrazovky), tak je nejspíš blbě napsaná.

Tohle nemám z vlastní hlavy, ale z přednášky Dopručené postupy v programování.

Pokud jde o to formátování, existujou samozřejmě různý konvence, který se v detailech liší, ale ten princip je všude stejnej.

Offline

 

#18 31. 07. 2019 11:18

Anonymystik
Příspěvky: 560
Reputace:   45 
 

Re: Dotaz k třídám v C++ (implicitní parametr typu ukazatel na objekt)

↑ Stýv: No, když těch příkazů je v bloku vícero, samozřejmě přidělávám závorky a řádkuji. Ale u těch jednořádkových jsem si navyknul to dělat bez toho (pak často dodělávám nebo naopak umazávám závorky, jak je potřeba). Tvůj přístup (nejen tvůj) jsem aplikoval dříve a ustoupil jsem od něj, protože mi přišlo, že tím hrozně nabobtnává kód a tvoří se šílené vrstvy závorek. Asi je to otázka vkusu.
--
Hodně mě překvapuje tvůj přístup "smazat třídu Strom". Když jsem vymýšlel koncepci toho programu, tak jsem si říkal, že strom bude nějaká datová struktura, do které se budou ukládat data a odkud se mohou odebírat. No a ta data se v rámci toho stromu budou uchovávat v "atomických" datových jednotkách - vrcholech ("node"). Přišlo mi to v danou chvíli jako naprosto přirozený přístup. Navíc do Stromu mohu přidat atribut jako "PocetVrcholu", který se týká stromu jako celku. Kdybych zrušil třídu strom a přidal atribut PocetVrcholu do každého vrcholu, měl bych výhodu, že bych okamžitě věděl počet vrcholů v každém podstromu, nicméně by mi asi dost nabobtnala paměťová náročnost.
--
Co se týká té češtiny, jsem dost nekonzistentní, dělám si to často dost podle nálady. Už jsem začal přemýšlet nad konvencí, že bych datové třídy a funkce pojmenovával anglicky, kdežto proměnné a instance česky (abych to nějak od sebe odlišil).
--
Chytré pointery prozkoumám, díky za tip. Asi to nebylo přesně to, co jsem chtěl, ale stejně na to kouknu.


"Do you love your math more than me?"   "Of course not, dear - I love you much more."   "Then prove it!"   "OK... Let R be the set of all lovable objects..."

Offline

 

#19 31. 07. 2019 11:53

Stýv
Vrchní cenzor
Příspěvky: 5316
Reputace:   201 
Web
 

Re: Dotaz k třídám v C++ (implicitní parametr typu ukazatel na objekt)

↑ Anonymystik: Pokud ti "hrozně nabobtnává kód a tvoří se šílené vrstvy závorek", tak je problém někde jinde. Coding-style pro linuxový kernel mino jiné říká, že se odsazuje o 8 mezer (sic!) a funkce by se měla vejít na dvě stránky, které mají 80*24 znaků.

Now, some people will claim that having 8-character indentations makes the code move too far to the right, and makes it hard to read on a 80-character terminal screen. The answer to that is that if you need more than 3 levels of indentation, you’re screwed anyway, and should fix your program.

Strom = kořenový vrchol. Pokud opravdu nezbytně potřebuješ počítat vrcholy se složitostí o(1), můžeš udělat nad kořenovým vrcholem tenkou obálku, kde si to budeš pamatovat, nicméně i tak by metoda Tree.Add(n) měla v podstatě jenom volat metodu root.Add(n). Problém tohohle přístupu ovšem je, že pak podstromy toho stromu samy o sobě nejsou stromy, což je poněkud divný.

Na češtinu zapoměň. Pokud budeš někdy něco doopravdy programovat, dřív nebo později na ty zdrojáky bude koukat někdo jinej (kolega z druhýho konce světa, nezávislej vývojář opensource nebo třeba někdo, kdo ti bude chtít poradit na stackoverflow a nebude tomu rozumět). Příklad rozumné konvence je začínat typy a funkce velkým písmenem a proměnné a instance malým.

Z čeho se to C++ učíš? Zřejmě z nějakého zastaralého zdroje, jelikož C++ se zásadně změnilo ve verzi C++11 (z roku 2011).

Offline

 

#20 31. 07. 2019 12:20 — Editoval Anonymystik (31. 07. 2019 12:24)

Anonymystik
Příspěvky: 560
Reputace:   45 
 

Re: Dotaz k třídám v C++ (implicitní parametr typu ukazatel na objekt)

↑ Stýv:
Už jsem použil víc než 3x odsazení a ano, souhlasím, že pak to přestává už být přehledné.
--
Ten přístup s třídami Vrchol a Strom jsem vyřešil tím, že jsem tam u metod jako Add právě zavedl ty implicitní parametry. To znamená, že pokud nikdo žádný parametr nazadá, volá se metoda na strom jako celek. Pokud naopak je zde parametr v podobě vrcholu (resp. reference na pointer na vrchol), mohu metodu zavolat pouze na příslušný podstrom. Jiný přístup by mohl být ty metody přetížit, přičemž ta verze s parametrem by byla začleněná do sekce "private", aby na ni nešlo šahat zvenčí.
--
Programuju si jen sám pro sebe, neživím se tím. Pokud tě to zajímá, rád bych si zkusil naprogramovat jednu jednoduchou hru, pak bych si rád vyzkoušel Machine learning a konečně jako třetí projekt mám v hlavě nějakou teorii her a evoluční algoritmy. Ale zatím si zkouším takové mini-projekty, na kterých se trénuju (na Stromech se člověk krásně naučí dělat s pointery, s rekurzí a s třídami, takže ideální cvičení).
--
Mám doma tyto knížky:
1) C++ výukový kurz od Davida Matouška (poměrně vydatná příručka, obsahuje i klasické Cčko)
2) Algoritmy od autora Piotr Wróblewski (psaná přímo pro jazyk C++)
3) Průvodce labyrintem algoritmů od Martina Mareše a Tomáše Válly  (psaná v pseudokódu, ale velice dobrá)
Zbytek je googlení a internet.
--
Jako IDE používám Builder 6 a Dev C++.
--
V souvislosti s tím - neznáš nějakou knížku, která by se věnovala tomu, jak efektivně používat OOP? (tím nemyslím výuku nějakého konkrétního objektově orientovaného jazyka, ale spíše způsob, jak navrhovat složitější programy a rozsáhlejší projekty - tj. jak se lépe sžít s objektovým paradigmatem a naučit se tak myslet - občas mám dojem, že myslím dost postaru).


"Do you love your math more than me?"   "Of course not, dear - I love you much more."   "Then prove it!"   "OK... Let R be the set of all lovable objects..."

Offline

 

#21 31. 07. 2019 12:53

Stýv
Vrchní cenzor
Příspěvky: 5316
Reputace:   201 
Web
 

Re: Dotaz k třídám v C++ (implicitní parametr typu ukazatel na objekt)

Používat něco jako Add(Cislo, root->lSyn, false) není OOP. Mělo by to vypadat zhruba jako lSyn.Add(Cislo). Až na ty český názvy.

I když si programuješ pr sebe, měl by ses snažit to dělat pořádně.;-) A stackoverflow by se ti tím spíš mohlo hodit.

Znám akorát toho Průvodce labyrintem algoritmů, podle toho se učí na matfyzu.
Z toho matouška jsem našel jenom krátičkou ukázku, ael podle obsahu je tam zmínka o chytrých ukazatelích až někde vzadu, takže to moc moderním dojmen nepůsobí (přestože je to vydané 2018).

Taky neznám, ale podle obrázků to vypadá obojí dost old-schoolově. Já používám Visual Studio, které rozhodně můžu doporučit.

Možná Code Complete: A Practical Handbook of Software Construction, podle které byla koncipovaná ta přednáška  na Doporučené postupy v programování. Není jenom o OOP, vlastně ani nevím, jak moc se tam OOP reozebírá, ale určitě je tam plno užitečných informací o výrobě softwaru.

Offline

 

#22 31. 07. 2019 18:16

Anonymystik
Příspěvky: 560
Reputace:   45 
 

Re: Dotaz k třídám v C++ (implicitní parametr typu ukazatel na objekt)

Trochu ten kód předělávám za použití přetěžování funkcí. Dospěl jsem k názoru, že to bude lepší, než používat implicitní parametry.


"Do you love your math more than me?"   "Of course not, dear - I love you much more."   "Then prove it!"   "OK... Let R be the set of all lovable objects..."

Offline

 

Zápatí

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson