Hirdetés
- Felháborodott az Apple, a Meta az iPhone-felhasználók üzeneteit akarja olvasni
- A luxusmárkáknak kell a bitcoin, az USA jegybankjának nem
- Letiltja az USA a politikusokat a telefonhívásokról és szöveges üzenetekről
- Nagy áttörés jön a napelemek piacán, nem kell annyi hely a paneleknek
- Belenyúlt az USA az Epic Games igazgatótanácsába, nyomoz az NVIDIA
Új hozzászólás Aktív témák
-
Mikeboy666
csendes tag
Ez milyen ???
int TOMB[10], maxindex=0, maxertek, i, db, seged;
do
{
cout<<"Adja meg a tomb elemszamat (1-0) ";
cin>>db;
} while(db<1||db>10);
for(i=0;i<db;i++) {
do
{
cout<<"Adja meg a tomb "<<i+1<<". elemet (0-10) ";
cin>>TOMB[i];
}while(TOMB[i] < 0 || TOMB[i] > 10);
}
for(i=0;i<db;i++) // tömb elemeinek kiíratása
{
cout<<"A tomb "<<i+1<<". eleme \t"<<TOMB[i]<<endl;
}[ Módosította: Karma ]
-
EQMontoya
veterán
válasz Mikeboy666 #2998 üzenetére
Így tudsz randomot generálni.
Nyilván Neked 11-gyes maradék kell majd, hogy 0-10 közé essenek a random számok.A megvalósítás:
Fogsz egy for ciklust, ami 0-től 9-ig fut.
Generálsz egy randomot.
Beteszed a tömbbe.
Hozzáadod az eddigi összeghez.
Ha kisebb, mint az eddigi legkisebb, akkor felülírod az eddigi legkisebbet.
Ha páros, növeled a párost számláló változódat.Nem túl bonyolult.
[ Szerkesztve ]
Same rules apply!
-
EQMontoya
veterán
-
Mikeboy666
csendes tag
Hello!!! Kérlek segítsetek ebben...Totál kezdő vagyok a C++-ban...
Feladat: egy versenyen 10 guritást csinálnak. Gurításonként 0-10 pontot kapnak. Kérje be véletlen generátorral, úgy hogy azok 0 és 10 közé eshetnek és tárolja az eredményeket a Gurítások [10] tömben. Írja ki táblázatos formában a guritások eredményeit. Számítsa ki mennyi a 10 guritás összege. Írassa ki a képernyőre a legkisebb guritás sorszámát. Írja ki a képernyőre a páros dobások számát.
Előre is köszönöm,aki segít...[ Szerkesztve ]
-
ToMmY_hun
senior tag
Jól összefoglaltad a lényeget. Nekem az a tapaszlatom (igaz nem C++ tekintetében) hogy sokszor a program logikája is hibás, redundáns kódrészeket, felesleges műveleteket tartalmaz. Egyik nap egy éles kódban láttam egy ilyet: if(a != b) a = b; Nyilván ez nem olyan nagy overhead, de ha kicsiben ilyen hiba van, akkor nem szeretném tudni hogy mi van magasabb szinteken. Ezek sokkal komolyabb programozási/tervezési hibák, mint egy pre/post increment felcserélés és nagyobb a miatta keletkező overhead is. A kód futási ideje nem olyan kritikus, de minek kell nyüstölni a hardvert ha egy kicsi gondolkodás árán lehet kímélni is? Kár, hogy egyetemeken nem fordítanak kellő figyelmet arra, hogy hatékony, könnyen érthető de mellette robosztus kódot írjanak a diákok. Mi villmérnökök mikrokontrolleren kezdtük el programozni, ráadásul 8 bites csodákon. Szerintem azok rettenetesen jók arra, hogy lássa és tapasztalja az ember azt, hogy miért fontos optimális kódot írni.
C programmers never die, they are just cast into void.
-
LordX
veterán
válasz jattila48 #2992 üzenetére
Jó, persze ez sarkított példa, én is alapból ++x-et gépelek mindenhol, csak rossz reflexet fejleszt ki a kezdő programozóban, hogy figyelni kell mindenre, különben leharapja a C++ a lábad: "Használj pre-incrementet. Ne adj át érték szerint paramétert függvénynek, adj át const referenciát. Ha lemásolod a paramétert inkább add át érték szerint. Csinálj így, csinálj úgy."
Ha már dolgozol egy éve, akkor amúgy is rájössz, hogy mi az, ahogy elsőre érdemes csinálni.
-
jattila48
aktív tag
Ok, ebben nem értünk egyet. Nyilván elsősorban a programom logikájára figyelek, de tőlem abszolút nem igényel semmiféle "görcsölést", hogy alapból a pre op-ot használjam. Persze mások vagyunk, lehet hogy neked ez fölöslegesen elvonja a figyelmed az alkotástól. Mindenesetre szerintem általában javasolható a pre op használata.
Egyébként viszonylag ritkán van szükség kifejezetten a post op alkalmazására. Én leginkább konténer kiürítésénél használtam.„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
dobragab
addikt
Ezért van rossz híre a nyelvnek - valójában non-issue az összes ilyen; ha nem akarsz vele foglalkozni, nem kell, semmi nem kötelező.
+1
C++-ban szerintem nincsenek ökölszabályok, max. jól bevált módszerek. Pl. a 3-5-ös szabály sincs kőbe vésve: gondolj csak egy rejtett proxy objektumra, pl. az std::vector<bool> indexelő operátorának visszatérési értékére. op= tuti kell, hogy jól menjen az egymásnak értékadás, míg dtor-ra tuti nincs szükség.
Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
-
LordX
veterán
válasz jattila48 #2987 üzenetére
Csak azt mondom, hogy amikor írod a kódot, akkor nem kell görcsölni rajta. Csináld ahogy sikerül, ha hibáztál is, ez soha nem olyan nagy hiba, hogy probléma legyen. Ahol probléma, ott úgyis kiderül az első profilozás után, ahol nem profilozol, ott meg nem probléma.
A program logikájára figyelj, ne arra, hogy itt van egy a kismillió "kötelező" szabály között, ha C++-ban programozol. Ezért van rossz híre a nyelvnek - valójában non-issue az összes ilyen; ha nem akarsz vele foglalkozni, nem kell, semmi nem kötelező.
A programot írjad C++-ban, ne C++ kódot, ami mellékesen megvalósítja a programod.
[ Szerkesztve ]
-
-
LordX
veterán
válasz jattila48 #2986 üzenetére
Egyébként én szívem szerint leszedném a publikus verziót, többet árt az egész iparnak, mint használ. Olyan döntések vannak benne (legkirívóbb a kivételek teljes tiltása), amiről már a cégen belül is tudja mindenki, hogy rossz, de a masszív mennyiségű kód miatt nem lehet változtatni.
-
jattila48
aktív tag
Én csak azt nem értem, hogy szerinted miért olyan nagy fáradság figyelni rá, mi nem ér annyit? Mennyit? Ha tudod, hogy a pre verziót is lehetne használni, akkor "véletlenül" nem fogod a post-ot. Vagy annyira erős koncentrációt igényel tőled, hogy erre figyelj, ezért random hol ezt, hol azt használod? Ha meg tudod, hogy elvileg mindegy melyiket használod, akkor "csak azért is" néha a post-ot?
"Ha code review-n megjelenik okoska, hogy hé, véletlenül másikat használtad, 5 billentyű leütés kijavítani."
Ha kijavítani csak ennyi, akkor "jól" írni még ennyi sem.[ Szerkesztve ]
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
jattila48
aktív tag
"Így most azt mondod, hogy a fordító egy függvényhívást lecserélhet egy másik függvény hívására, ha bizonyos feltételek teljesülnek"
Végül is igen. Persze csak akkor, ha post verzió a "szokásos módon" mellékhatások nélkül van megvalósítva.
"Ha másik fordítási egységben van definiálva, akkor teljesen más dolgot csinálhat a kettő, és erről a fordító SEMMIT nem tud."
Hát ez valóban probléma! Igazából úgy lehetne ezt elképzelni, ha megadható lenne, hogy a fordító automatikusan generáljon post verziót a pre verzióból. Ilyen persze tényleg nincs.
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
LordX
veterán
válasz jattila48 #2975 üzenetére
Az operator++() és az operator++(int) csak egy fancy név egy-egy függvénynek. Így most azt mondod, hogy a fordító egy függvényhívást lecserélhet egy másik függvény hívására, ha bizonyos feltételek teljesülnek. Ilyen nincs. Ha másik fordítási egységben van definiálva, akkor teljesen más dolgot csinálhat a kettő, és erről a fordító SEMMIT nem tud.
Ha postfixet írtál a kódba, hót zicher, hogy postfix lesz belefordítva.
-
jattila48
aktív tag
Az általam írt optimalizáció megvalósításában valószínűleg annak eldöntése lehet a legnehezebb (esetleg lehetetlen), hogy van-e a post verziónak mellékhatása. A szokásos megvalósításban ez a mellékhatás csak a copy ctor-ban lehet. Elképzelhető, hogy a szabvány nem engedi meg a mellékhatás kioptimalizálását (ellentétben az RVO-val, ahol a copy ctor mellékhatását engedi figyelmen kívül hagyni). Ez esetben tényleg nem ez a járható út. Ha viszont a post verziónak van mellékhatása, akkor a programozónak főleg foglalkoznia kell azzal, hogy melyiket használja.
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
jattila48
aktív tag
Ha már a Google-nál dolgozol, nyilván ismered:
Google C++ Style Guide
Preincrement and Predecrement
Use prefix form (++i) of the increment and decrement operators with iterators and other template objects.
When a variable is incremented (++i or i++) or decremented (--i or i--) and the value of the expression is not used, one must decide whether to preincrement (decrement) or postincrement (decrement).
When the return value is ignored, the "pre" form (++i) is never less efficient than the "post" form (i++), and is often more efficient. This is because post-increment (or decrement) requires a copy of i to be made, which is the value of the expression. If i is an iterator or other non-scalar type, copying i could be expensive. Since the two types of increment behave the same when the value is ignored, why not just always pre-increment?
The tradition developed, in C, of using post-increment when the expression value is not used, especially in for loops. Some find post-increment easier to read, since the "subject" (i) precedes the "verb" (++), just like in English.
For simple scalar (non-object) values there is no reason to prefer one form and we allow either. For iterators and other template types, use pre-increment.
Úgy látszik, hogy a céged mégiscsak elvárja, hogy foglalkozz ezzel.
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
jattila48
aktív tag
Nem feltétlenül iterátorra gondoltam. Más bonyolultabb objektumnak is lehet inkrementáló operátora, amit esetleg tényleg nem lehet inline-olni (más kérdés, hogy van-e értelme). Az RVO-t csak arra írtam, hogy ha azt a fordító (és nem külön menetben az optimalizáló) végzi, akkor akár ezt is elvégezheti, amit írtam, Egyáltalán nem biztos hogy megcsinálja, de számomra ez még egyszerűbb feladatnak tűnik mint az RVO. Persze az igaz, hogy csak akkor, ha a ctor, dtor-nak nincs mellékhatása.
"Ahhoz, hogy úgy működjön a fordító, hogy detektálja, hogy most ki lehet cserélni a pre-t post-ra, úgy, hogy minden esetben működjön, ahogy te leírod, nagyon okosnak kell lennie"
Ahol nem használja a post visszatérő értékét ott kicseréli, máshol meg nem. Vagy ez nem ilyen egyszerű?
Akárhogy is van, azzal hogy "akkor ne foglalkozz vele, mert nem ér annyit", nem értek egyet. Szerintem ez nem különösebben teszi próbára a programozót, hogy adott esetben el tudja dönteni, tényleg szüksége van-e a post verzióra, vagy elég a pre is. Vagyis igenis foglalkozzon vele , mert megér annyit. Szerintem ezt hogy a post lassabb lehet, illik tudni egy programozónak. Kód review-ban én szóvá tenném, míg azt a valóban szerencsétlen bool értékadást nem.
Más, nem csak neked címezve:
Makrók és template metaprogramming használatával olyan programot szeretnék írni, amit újra fordítva, az előzőleg fordítottal funkcionálisan megegyező, azonban bináris kódjában erősen különböző kódot kapok. Ez egy kicsit bonyolult mondat lett, tehát a lényeg: makrókkal és TMP-vel bináris kód obfuszkáció. Hatékonyság nem lényeg, lehet bele (sőt...) redundáns kódot injektálni, hadd legyen minél nehezebben követhető a kód. Olyanokra gondoltam mint értékadás, függvényhívás, bool kifejezések bonyolítása, loop unrolling, stb. Ha van ezzel kapcsolatban ötletetek, ne tartsátok magatokban. Ja, és ne akarjatok lebeszélni róla, hogy ugyan minek ez nekem. Köszi előre is.
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
LordX
veterán
válasz jattila48 #2967 üzenetére
Ha az iterátorod inkrementálása nem inline, akkor ott valami nagy gáz van..
Ahhoz, hogy úgy működjön a fordító, hogy detektálja, hogy most ki lehet cserélni a pre-t post-ra, úgy, hogy minden esetben működjön, ahogy te leírod, nagyon okosnak kell lennie. Van egy rossz hírem: nem az. Követi a kis szabályait, és az alapján generál/módosít kódot.
Kipróbálni egyszerű, mi van, ha nincs inline __attribute__((noinline)) a függvény definíciója elé GCC/Clang esetében - MSVC-ben meg valami force_no_inline?
Itt nincs RVO, se copy elision - nincs objektum, aminek temporálisból való konstruálása van eltüntetve, hanem bármi objektum konstruálása teljesen - ez már túllép azon, amit ez a szabály enged, és csak azért megoldható, mert se a konstruktor, se a destruktor nem tartalmaz mellékhatást. Ha kikapcsolod az optimalizálást, de force-olod az inline-t a példámban (kapcsolókkal kell játszani, most nincs rá időm kitalálni mit kell), akkor szépen látszana, hogy van pár extra MOV a konstruktor miatt a post-nál (a destruktor meg no-op).
-
-
ToMmY_hun
senior tag
válasz jattila48 #2969 üzenetére
Erre irányult a kérdés, de én csak azt szerettem volna tudni hogy primitív típusok esetén, mint pl int miért preincrementet használnak/használtok. Persze én csak örülök, hogy ilyen részletesen ki lett vesézve a téma.
C programmers never die, they are just cast into void.
-
jattila48
aktív tag
Egyébként meg akárhogy is van, annyit foglalkozni vele, hogy ha nem szükséges akkor nem a post verziót használom, mindenképpen megér. Jó tudni, hogy elvileg a post verzió sokkal lassabb is lehet. Szerintem a kérdező csak ezt kérdezte.
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
ToMmY_hun
senior tag
Ha publikus akkor megosztanád hogy milyen területen programozol? Érdekelne hogy mi az, ahol ennyire ügyelni kell az optimális kódra. Persze, elméletileg mindenhol, de nem mindenhol van idő/lehetőség a kód optimalizálására és én örülnék neki ha csak ilyen overheadek lennének a kódokban amiket nap-mint-nap látok.
[ Szerkesztve ]
C programmers never die, they are just cast into void.
-
jattila48
aktív tag
Ez még csak OK lenne, ha inlineolható az operátor és a copy ctor. De mi van, ha fv. hívásokként kell befordítani? Akkor ez már nem működik. Viszont az könnyen eldönthető, hogy valójában nincs is szükség a post inkrement verzióra, ezért egyszerűen a pre verziót fordítja be. Ez is egyfajta optimalizáció. Természetesen, ha post verziónak mellékhatása van (akár a copy ctor miatt), akkor a fordító úgy ítéli meg, hogy igenis szükség van rá, ezért valóban a post verziót fordítja be. Ez akkor is működik, ha a post verzió nem inlineolható, míg amit te írtál, az kénytelen lesz az egyébként szükségtelen post verziót használni, ha máshol pedig okkal használják a post verziót. Nem tudom, hogy így vagy úgy van-e, ki kéne próbálni. Valahogy biztos meg lehet tiltani az inline-olást, abból kiderülne. Azt írod, hogy a "generált kódra rámozdul az optimalizáló", ami egész biztos, hogy jórészt így is van. Azonban pl. pont az RVO-nál gondolom már a fordító generál optimalizált (akár köztes) kódot, amivel a köztes kódon operáló optimalizációnak már nem lesz dolga (legalábbis nem az RVO tekintetében). Most úgy gondolom (nem biztos hogy így van), hogy az RVO-t nem is lehet másként, mint elve a fordítóra bízni (nem pedig a külön menetes optimalizálóra), akkor pedig miért ne végezhetné el az általam írt optimalizációt is maga a fordító?
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
LordX
veterán
válasz jattila48 #2965 üzenetére
Nem érted. A fordító azt fordítja bele, amit írtál. Nem tehet mást. Generál valamilyen köztes kódot (mindegyiknek van, csak egyedül a Clang esetében publikus, az LLVM-IL).
Pre esetben a generált kódra rámozdul az optimalizáló, ami először inline-olja a copy construktort, tehát lesz 1 függvényed, ami másol biteket, azt machinál valamit másik biteken. a következő lépés látja, hogy lemásolsz valami biteket, azt nem használod - fölösleges kód, törölhető.
Post esetben meg nincs copy, nincs mit töröljön.
Az egyik esetben a gép szenvedett egy kicsit érte, de az eredmény ugyanaz, ezért ha nem kritikus kód (ami csak az után derül ki, hogy leprofiloztad!), akkor ne foglalkozz vele, mert nem ér annyit.
Elírtam, fordítva: a WTF a pre-inkrement post-inkrementtel megvalósítva.
-
jattila48
aktív tag
De hát pont arról volt szó, hogy nem változtatja meg ezzel program működését, hiszen nem használja az operátor visszatérő értékét, így nyugodtan használható a pre inkrement verzió. Igen csodálkoznék, ha úgy lenne, ahogy írod, mert akkor más fordítási modulban, ahol szükségszerű a post inkrement verzió ott mit csinál? A kód optimalizálók általában nem globálisan, hanem csak fordítási egységenként működnek. Vagy ha másik modulban post inkrement kell, akkor oda is azt fordít, ahova nem kéne, de azt használják? Ez számomra nagyon nem tűnik logikusnak, és jóval egyszerűbb így megvalósítani, ahogy írtam. Némileg magadnak is ellent mondasz ("annyira nem eszik forrón a kását"), mert ha így lenne ahogy írod, akkor igenis figyelni kellene, hogy tényleg csak a szükséges helyeken használjuk a post inkrement verziót ("Szóval
nemérdemes ebbe energiát befektetni").
BTW elárulnád, hogy mi a baj azzal, ha a post inkrement op-ot pre inkrementtel valósítom meg?„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
LordX
veterán
válasz jattila48 #2963 üzenetére
Az nem épp valid működés, hogy másik operátort fordít, nem változtathatja meg a fordítás a program működését (egyedül copy elision / RVO szabad). Post-increment van itt is, csak elég okos a fordító, hogy kioptimalizálja az extra MOV utasításokat, amik a copy construktorral jöttek létre - módosítsd a példát, hogy legyen valami mellékhatása a copy konstruktornak, máris nem optimizálja ki.
-
jattila48
aktív tag
"Ha nem használod a visszatérési értéket (mint pl. a for ciklusban), akkor erősen valószínű, hogy optimalizálás után pontosan ugyanazt a kódot generálja akkor is, ha saját operátorokat definiálsz"
Úgy tűnik, hogy ilyenkor egyszerűen a pre inkrement verziót fordítja be akkor is, ha post inkrementet használsz. Ettől persze még igaz, hogy maga a post inkrement verzió kb. egy copy ctor-ral költségesebb.
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
jattila48
aktív tag
válasz MasterMark #2955 üzenetére
Nincs ezzel baj. Itt nem lehet a break feltételt betenni a ciklusfeltételbe, mert break esetén kiírsz.
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
jattila48
aktív tag
Elképzelhető, hogy így van. Természetesen mindig a logikának megfelelőt kell használni, de magam részéről ha logikailag mindegy, mindig a pre inkrement verziót használom. Nem POD-ra gondoltam, ezt rosszul írtam, hanem csak az alaptípusokra. Ha nincs optimalizálás, akkor szerintem kb. úgy van, ahogy írtam. Legalábbis én így írtam post inkrement operátort, de valószínűleg nem is lehet ettől nagyon különböző módon.
[ Szerkesztve ]
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
LordX
veterán
válasz MasterMark #2955 üzenetére
if (egy[0].eleje > ketto[0].vege && !nemok) {
auto it = std::find_if( std::rbegin(ketto) //REVERSE begin (gondolom a db2 a 'ketto' konténer mérete)
, std::rend(ketto) //reverse end
, [&](auto&& elem) { return elem.vege < egy[0].eleje; } //keresett feltétel
);
if (it != std::rend(ketto)
kiiras(it->eleje, it->vege);
kiiras(egy[0].eleje, egy[0].vege);
} else { ... } -
LordX
veterán
válasz jattila48 #2928 üzenetére
Annyira nem eszik forrón a kását. Ha nem használod a visszatérési értéket (mint pl. a for ciklusban), akkor erősen valószínű, hogy optimalizálás után pontosan ugyanazt a kódot generálja akkor is, ha saját operátorokat definiálsz:
[link]
(Az std::slist iterátora kb. így működik, mint a példám, csak ott van még a struktúrában a tárolt elem is.)Szóval nem érdemes ebbe energiát befektetni. Ahol a program logikájához pre-inkrement kell, ott azt kell használni, ahol post, ott azt, ahol mindegy, ott meg mindegy. (De mint korábban írtam, azért ha lehet ne szopassuk az optimizálást fölöslegesen, és használjunk inkább pre-t, egy idő után úgy is az lesz a természetes.)
(BTW, a POD-nak semmi köze ehhez, a példámban a két osztály is POD, és nyilvánvalóan nem triviális ez a két OP.)
[ Szerkesztve ]
-
MasterMark
titán
if egy[0].eleje>ketto[0].vege && !nemok){
for (int i=db2-1;i>=0;i--){
if (ketto[i].vege<egy[0].eleje){
kiiras(ketto[i].eleje,ketto[i].vege);
break;
}
}
kiiras(egy[0].eleje,egy[0].vege);
} else {...}Így használtam, illetve hasonlóan máshol is.
Switch Tax
-
jattila48
aktív tag
válasz dobragab #2952 üzenetére
Hát, ez lényegében ugyanúgy egy lineáris keresés, de nekem mindegy! Megkeresed a vége előtt az első nem beolvasható elemet, és közben csinálsz valamit. A lényeg nálam is ez volt: Adott hosszúságú adathalmaz (tömb) elemein sorban haladva egy bizonyos feltétel bekövetkeztéig csinálok valamit. Ha a feltétel bekövetkezik, abbahagyom a feldolgozást (break). Ez a for-break legkézenfekvőbb alkalmazása. Végül is mi volt a baj a lineáris kereséssel?
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
dobragab
addikt
válasz dobragab #2951 üzenetére
Jutott eszembe. Fájlból beolvasás, és error handling. Kicsit bugyuta, de a célnak megteszi.
int i;
for (i = 0; i < n; ++i)
{
if(!(file >> tomb[n]))
break;
// handle data, probably more errors
}
if (i != n)
{
std::cerr << "Error while reading the file!" << std::endl;
throw whatever{};
}Itt a break is a funkcionális dekompozíciót segíti. Elválasztja egymástól a normális futást és a hibakezelést.
[ Szerkesztve ]
Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
-
dobragab
addikt
válasz jattila48 #2950 üzenetére
Én a kérdésre válaszoltam, és nem jutott jobb példa eszembe, mint a lineáris keresés (és őszintén szólva most sem. Mondj egy példát, ahol a for ciklus break kombo helyénvaló, és az nem a lineáris keresés!).
Ha jut eszembe, szólok.
Egy kezdőnek meg azzal sem kell tömni az agyát, hogy mindenáron túl általános sablonos c++ megoldást válasszon, és a hatékonyságot is illik szem előtt tartani. Erről írt Linus is.
Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
-
jattila48
aktív tag
válasz dobragab #2948 üzenetére
Félreértetted (vagy félre akartad érteni). Egyáltalán nem utasítom el funkcionális dekompozíciót, természetesen én is használok fv.-eket. Én a kérdésre válaszoltam, és nem jutott jobb példa eszembe, mint a lineáris keresés (és őszintén szólva most sem. Mondj egy példát, ahol a for ciklus break kombo helyénvaló, és az nem a lineáris keresés!). Magam részéről így csinálnám meg, de lehetőleg break nélkül a ciklusfeltételbe építve. Van azonban olyan eset, amikor nem lehet a ciklusfeltételbe beépíteni, ekkor használható a break (fv. hívás helyett is). Egyébként mint kiderült, a kérdező is a lineáris keresésre gondolt. Egy kezdőnek meg azzal sem kell tömni az agyát, hogy mindenáron túl általános sablonos c++ megoldást válasszon, és a hatékonyságot is illik szem előtt tartani. Erről írt Linus is.
[ Szerkesztve ]
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
dobragab
addikt
válasz jattila48 #2946 üzenetére
de azért kíváncsi lennék, hogy írnál meg egy find and replace-t szövegbufferben amúgy elegánsan, modern C++ stílusban. Milyen konténerben tárolnád a szöveget, milyen standard fv.-eket használnál, és hogy kerülnéd el a for ciklusokat (break-kel együtt)?
A for ciklussal még mindig semmi bajom.
Valahogy így: [link].Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
-
dobragab
addikt
válasz jattila48 #2946 üzenetére
A kérdező azt kérdezte, hogy for ciklusban OK-e a break.
Basszus, ezt elnéztem Ő egy szóval sem említette, hogy lineáris keresésről van szó. Kezdőnek meg illik azt mondani, hogy nem, mert a végén rászokik. Vagy legalább annyit, hogy speciális esetekben igen.
Lehet, hogy neked maga a for ciklus (főleg break-kel) már pattintott C korszak
A for ciklussal semmi baj. A break-kel már annál több. A pattintott C korszak meg a funkcionális dekompozíció elutasítására vonatkozott.
Egyébként biztos ismered Linus Torvalds véleményét a C++ nyelvről.
Persze. És azt tudod, hogy függvényt Linus is használ?
Ja, akkor a linux szerinted pattintott C korszaki, ugye?
A Linux nem. Linus igen.
Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
-
EQMontoya
veterán
válasz dobragab #2945 üzenetére
A funkcionális dekompozició azért is támogatott, mert ha nincs megszokva, akkor ésszerű esetekben sem fogja csinálni az ember.
Múltkor az egyik versenyre írtunk olyan útvonaltervezést (alapvetően dijkstra alapon), amely:
-std::func-ként vette át a súlyfüggvényt, amit használnia kell
-std::func-ként kaphatott predikátumot, ha nem bizonyos pontra, hanem a legközelebbi, adott feltételt teljesítő pontra akarsz tervezniHa ezt nem szedi szét az ember már az elején, akkor a végén orbitális cumi lesz belőle.
Same rules apply!
-
jattila48
aktív tag
válasz dobragab #2945 üzenetére
A kérdező azt kérdezte, hogy for ciklusban OK-e a break.A válasz: igen. Lehet, hogy neked maga a for ciklus (főleg break-kel) már pattintott C korszak, de azért kíváncsi lennék, hogy írnál meg egy find and replace-t szövegbufferben amúgy elegánsan, modern C++ stílusban. Milyen konténerben tárolnád a szöveget, milyen standard fv.-eket használnál, és hogy kerülnéd el a for ciklusokat (break-kel együtt)? Egyébként biztos ismered Linus Torvalds véleményét a C++ nyelvről. Magam részéről ezzel persze jórészt nem értek egyet, de az általa "substandard programmers"-nek nevezett tagokról hasonló a véleményem. Ja, akkor a linux szerinted pattintott C korszaki, ugye?
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
dobragab
addikt
válasz jattila48 #2942 üzenetére
Az itt szócska talán elkerülte a figyelmedet. Én azt írtam, hogy van ahol jó a break (persze nem mindenhol), te meg azt mondod, hogy mindig van jobb megoldás.
Nem kerülte el, szándékosan írtam azt. Ebben az esetben (lineáris keresés) baromi egyszerű a függvény. Erre van a funkcionális dekompozíció, és ez egyáltalán nem C++ vagy OOP. A programot szedjük szét jól elkülöníthető, újra felhasználható részekre. Ez a kifejezés normál esetben a függvény szóval nagyjából egyszerre kerül bevezetésre. C-ben, C++-ban, vagy bármilyen nyelvben, ahol van függvény. Ha figyelted, én is elismertem, hogy van létjogosultsága a break-nek, de itt egyáltalán nincs.
Jelen esetben a fv. hívás maga túlságosan költséges az elvégzett feladathoz képest.
Igazatok volt. Pattintott C korszak.
[ Szerkesztve ]
Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
-
jattila48
aktív tag
válasz dobragab #2941 üzenetére
Egy kicsit vegyél vissza az arcodból! "Szerintem itt a return a ciklus közepéből semmivel sem jobb mint a break (egyik sem struktúrált megoldás)" idézted tőlem. Az itt szócska talán elkerülte a figyelmedet. Én azt írtam, hogy van ahol jó a break (persze nem mindenhol), te meg azt mondod, hogy mindig van jobb megoldás. A példában jobbnak tartom, mint ezt a függvényhívás megoldást. Jelen esetben a fv. hívás maga túlságosan költséges az elvégzett feladathoz képest. Nem kell ide keverni olyan nyilvánvaló eseteket, ahol nincs létjogosultsága a break-nek, mert nem erről volt szó. Kezdünk elkanyarodni az eredeti kérdéstől. Fölösleges lenne most itt RAII-vel meg mélyebb C++ és OOP koncepciókkal dobálódzni. Nem ez volt a kérdés!
[ Szerkesztve ]
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
dobragab
addikt
válasz jattila48 #2937 üzenetére
Szerintem itt a return a ciklus közepéből semmivel sem jobb mint a break (egyik sem struktúrált megoldás)
Ez most a heti vicc rovat, vagy komolyan gondoltad? A break-kel az a gond, hogy nehezen követhető, pontosan hova ugrik, és milyen utasításokat lép át, ami a változók további élettartama szempontjából fontos. Gondolj bele egy switch-ben lévő két egymásba ágyazott ciklusba, és a belső ciklusban egy break. Ha már itt tartunk, azt tudod, hogy hova ugrik?
return-nél messze nincsenek ilyen bajok. A return azt jelenti, hogy a függvény teljesítette azt, ami a feladata. Nyilvánvaló, hol folytatódik a végrehajtás. Nem marad utána semmilyen változó, nem probléma, épp mennyi volt az értéke a visszatéréskor. Az erőforrások felszabadítását most ne keverjük ide, mint otthagyott dinamikus memória. Ha nekem nem hiszel, legalább Stroustrup bácsinak higgy.
És, ha nem kell végigmenni, hanem csak az első két előfordulást kell megtalálni?
Ez elég speciális eset, ilyenkor elfogadhatónak tartom a break-et, de nem hinném, hogy itt ez volt a kérdés. Ja és code smell-t érzek, ha ilyen kell. Persze agyf@sz feladatban lehet ilyen, de production kódban szerintem nem jellemző.
Akárhogy csűrjük, csavarjuk, szerintem van ahol kifejezetten jó megoldás a break for ciklusból.
Van. De egy lineáris keresés tipikusan nem ez az eset.
ráadásul beépítesz egy fölösleges függvény hívást
Wut? Na nehogymá' egyetlen függvényhíváson akarjunk spórolni 2015-ben lineáris keresésnél (ami ugye O(n), tehát lassú)!
Mivan? Ne is írjunk függvényt egy teljesen jól elkülöníthető, egyszerű visszatérési értékű, újra felhasználható (!) kódrészlethez? Funkcionális dekompozíció FTW. Akkor nálad mi üti meg a küszöböt, ami már függvényt ér?
[ Szerkesztve ]
Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
-
jattila48
aktív tag
válasz ToMmY_hun #2938 üzenetére
Ha a pre inkrement művelet kevésbé időigényes mint a copy ctor, akkor akár több mint kétszer is lassabb lehet a post inkrement. Szerintem ez könnyen elképzelhető eset.
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
jattila48
aktív tag
válasz dobragab #2936 üzenetére
Szerintem itt a return a ciklus közepéből semmivel sem jobb mint a break (egyik sem struktúrált megoldás), ráadásul beépítesz egy fölösleges függvény hívást. És, ha nem kell végigmenni, hanem csak az első két előfordulást kell megtalálni? Akárhogy csűrjük, csavarjuk, szerintem van ahol kifejezetten jó megoldás a break for ciklusból. Aztán persze van ahol, van jobb megoldás.
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
dobragab
addikt
válasz jattila48 #2924 üzenetére
Összekeversz két problémát. Ha csak az egyik elemre van szükség, akkor jó a függvény:
int tombben_keres(int tomb[], int meret, int szam)
{
for(int i = 0; i < meret; ++i)
if(tomb[i] == szam)
return i;
return -1;
}Ha viszont mindenképp a teljes tömbön kell végigiterálni (összes nagybetű kiírása, pozitív számok összege, stb), akkor minek break? Simán végigmegy rajta.
for(int i = 0; i < meret; ++i)
if(isupper(str[i]))
std::cout << str[i];Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
-
jattila48
aktív tag
válasz MasterMark #2934 üzenetére
Jó a break for ciklusban. A lineáris keresést csak példaként írtam. Ezek szerint neked az kell. Esetleg, ahogy írtam, a break feltételét (negálva) beépítheted a ciklusfeltételbe, és akkor nincs break.
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
MasterMark
titán
válasz EQMontoya #2930 üzenetére
"pattintott C korszak" Hát ez nagyon nagy.
Én meg csak akkor tudnék igazságot tenni, ha egyáltalán tudnám, hogy miről beszéltek. Ezért nem tudok hozzászólni. Soha nem hallottam se find-ot, se iterátor nem tudom mi, szóval.
jattila48: Breakkel nekem jó az már, bár ez a find érdekesnek tűnik. Igazából mint már írtam, azért kérdeztem, hogy While helyett for + break az jó-e. (Nem tudtam akkor még, hogy ennyi más lehetőség is van. )
Switch Tax
-
jattila48
aktív tag
válasz EQMontoya #2930 üzenetére
Nem azt írtam, hogy lassú, hanem hogy lassabb. Pl. egy szövegszerkesztőnél ez lényeges szempont. Szövegszerkesztőt (marmint a szövegbuffert) nem írnék konténerekkel, iterátorokkal, standard és lambda függvényekkel (pl. szövegben egy sima find and replace az összes előfordulásra, hogy nézne ki nem "pattintott C" stílusban? Belegondolni is rossz). Szerintem szép számmal vannak olyan esetek, ahol a break nemhogy nem felesleges, hanem kifejezetten jobb megoldás, mint az elkerülésére tett C++ bűvészkedés. Ha lehet, én is elkerülöm, pl. a ciklusfeltételbe való beépítéssel.
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
EQMontoya
veterán
válasz jattila48 #2929 üzenetére
Hidd el, az stl cuccok elég jól optimalizáltak, és szerintem a fordítók felé is elég sok hintet tartalmaznak az implementációk. Szóval nem lesz az lassú.
Az meg a pattintott C korszak, hogy mindent megírunk magunknak, főleg a lambda függvények korában. Nyilván lehet fort meg brake-et írni, de a legtöbb esetben felesleges.Same rules apply!
-
jattila48
aktív tag
Na, erre mondom, hogy "túldizájnolás". A tomb maris egy konténer, aminek van iterátora. Az iterátorokat át kell adni a find függvénynek. Mit csinálsz, ha a tomb-ben a következő megfelelő elemet is meg kell találnod (elem=find(++elem, end(tomb), feltetel))? A példát arra írtam, hogy vannak olyan egyszerű esetek, amiket egyszerűen kell megoldani, és akkor nyugodtan használható a break. Ha egy sima karaktertömbben kell elvégezni ezt a feladatot, akkor a konténerek, iterátorok, és standard függvények használata, biztos, hogy lassabb (még inlineolva is) és nagyobb kódot eredményez.
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
jattila48
aktív tag
válasz ToMmY_hun #2926 üzenetére
Itt teljesen mindegy, hogy pre vagy post inkrementálást használsz. Alaptípusoknál (POD) nincs sebességbeli különbség. Általad definiált típusok esetén viszont valóban lassabb a post inkrementálás:
MyClass &operator++(){
//elvegzed a pre inkrementalashoz szukseges muveleteket
return *this; //hivatkozas szerinti visszaadas
}
MyClass operator++(int){
//post inkrementalas. Az int parameter csak ennek a jelzese, nem hasznalt.
MyClass tmp(*this); //temporalis objektumot hozunk letre
operator++(); //ez a pre inkrementalas az aktualis objektumon
return tmp; // a nem inkrementalt temporalist adjuk vissza ertek szerint
}Amint látod, minimum egy copy ctor hívással (és plusz egy fv. hívással) több a post inkrementálás. Hogy ez van-e kétszer annyi idő, vagy nincs, az az inkrementálás műveletigényétől függ.
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
ToMmY_hun
senior tag
válasz jattila48 #2924 üzenetére
Kezdő kérdés: Ugye sima int típusnál csak azért használsz, illetve használnak a gyakorlott C++ programozók pre-increment operátort, mert megszokták az STL-es iterátor inkrementálásnál? Annyit tudok, hogy iterátor típusnál célszerű a pre-increment, mert futásidőben a post akár kétszer olyan lassú is lehet, viszont ez nem igaz sima integer-nél, ugye?
C programmers never die, they are just cast into void.
-
LordX
veterán
válasz jattila48 #2924 üzenetére
Vagy csak simán
auto elem = find(begin(tomb), end(tomb), feltetel);
if (elem != end(tomb)) { /* *elem-et kerested */ }- Rövidebb (1 függvény 3 paraméterrel)
- öndokumentáló (vajon mit csinál ez a ciklus ezzel a bonyolult feltétellel vs vajon mit csinál a find függvény)
- ha lassabb kódot generál, akkor sürgősen cseréld le a fordítód, mert konkrétan ugyanaz a kód, miután inline-oltad
- gyorsabb is lehet, ha ki tudja használni a konténer / elem típusát
- nem random access konténerrel (set, list..) is működik -
jattila48
aktív tag
válasz MasterMark #2911 üzenetére
Nem gáz a break. Egyszerű dolgot nem kell túlbonyolítani. Adott elemszámú tömbben lineáris keresésre tökéletes. Ha pl. az a feladat, hogy egy karaktertömbben sorban keresd ki az A betűket, akkor ez a legjobb megoldás. Ha függvényt használnál, akkor minden következő kereséshez nemcsak a tömböt, hanem a most megtalált indexet is át kell adni. Ez fölösleges bonyolítása a feladatnak. Ha nagyon nem akarsz break-et, akkor elképzelhető, hogy a kiugrási feltétel betehető a ciklusfeltételbe.
int i;
char tomb[100];
int hossz=sizeof(tomb);
for(i=0;i<hossz && tomb[i]!=feltetel;++i);
if(i<hossz){
//megtalaltad a kersett elemet, indexe i.
}for(i=0;i<hossz;++i){
if(tomb[i]==feltetel)break;
}helyett.
C++ programozóknál gyakori hiba, hogy hajlamosak "túldizájnolni" a programot. Egy ilyen egyszerű feladathoz pl. nem biztos, hogy az STL-t kell használni. Nagy, és lassabb lesz tőle a kód.
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
jattila48
aktív tag
válasz dobragab #2922 üzenetére
Ennyi. Ehhez képest nem bonyolította túl. Szerintem a fordító ugyanazt a kódot generálja. Code review-ban én nem tenném szóvá. Ha neki így érthetőbb, akár kommentként is felfogható.
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
dobragab
addikt
Onnan, hogy pár hsz-szel feljebb olyat kérdezett, ami kezdőre vall.
Persze lehet, hogy tévedek. Ha viszont kezdő, akkor az std::begin() meg std::end() és társai nem hiszem, hogy segítenék az algoritmus megértését.
Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
-
ToMmY_hun
senior tag
válasz MasterMark #2917 üzenetére
Nem általános igazság, de egészen jól működik a következő. Amennyiben indexelned kell, akkor használj for ciklust, mert megoldja egy sorban az inkrementálást is. Akkor, ha egy feltétel teljesülésére vársz, akkor használj while-t. Egyébként ebből ne csinálj olyan nagy ügyet, használd azt amelyik az adott feladat ellátásra jobban átlátható, ésszerűbb.
C programmers never die, they are just cast into void.
-
dobragab
addikt
Gondolom, az a feladat, hogy tessék megírni, így STL nem játszik. Legalábbis amíg tanul, jobb, ha megírja maga. Aztán ha az algoritmusokat már ismeri, és komolyabb dolgokat gyakorol, persze inkább azt használja, ami az STL-ben van.
[ Szerkesztve ]
Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
-
félisten
válasz MasterMark #2911 üzenetére
Nincs ilyen szabaly, hasznald azt a megoldast, ami az adott helyzetben leginkabb atlathato es legkonnyebben ertelmezheto.
while (!sleep) sheep++;
-
sztanozs
veterán
válasz MasterMark #2911 üzenetére
tömbben keresésnél kifejezetten ildomos (felesleges tovább iterálni).
JOGI NYILATKOZAT: A bejegyzéseim és hozzászólásaim a személyes véleményemet tükrözik; ezek nem tekinthetők a munkáltatóm hivatalos állásfoglalásának...
-
MasterMark
titán
Mennyire (nem) elegáns for ciklusban break-et használni?
Switch Tax
-
félisten
válasz EQMontoya #2907 üzenetére
Ezt most talaltam nalunk (nem C++, de a lenyeg atjon):
/**
* A utility class to create the objects
*/
public class ObjectUtil {
private ObjectUtil() {
}
public static Activity getActivity(Person author,Person target) {
Activity activity = new Activity();
activity.setAuthor(author);
activity.setTarget(target);
return activity;
}
}Looks like a fckin' constructor to me
while (!sleep) sheep++;
-
dobragab
addikt
válasz EQMontoya #2905 üzenetére
Rosszabb. ZH-ban láttam.
int emelet(int szobaszam)
{
switch(szobaszam / 100)
{
case 0: return 0; break;
case 1: return 1; break;
case 2: return 2; break;
case 3: return 3; break;
case 4: return 4; break;
case 5: return 5; break;
case 6: return 6; break;
case 7: return 7; break;
}
return -1;
}Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
-
EQMontoya
veterán
Heti golden code:
bool a = (b == c) ? true: false;
Same rules apply!
-
MasterMark
titán
válasz MasterMark #2903 üzenetére
Storno, megvan, csak késő van, szóval helyesen:
eredmeny[i] = tomb[i+1] - tomb[i];
Switch Tax
-
MasterMark
titán
Üdv
tomb[i+1] - tomb[i] = eredmeny[i];
Így miért nem tudok számolni?
error: lvalue required as left operand of assignment|
Ezzel a hibával le se fordul.
Switch Tax
-
dobragab
addikt
válasz EQMontoya #2901 üzenetére
Pontosan ugyanebbe futottam bele Linux Mint-en, 4.8-as GCC. Arch-on 5.2-es GCC mellett írtunk egy makefile-t, ami gond nélkül megette. Utána Minten próbáltam fordítani, a linker undefined reference miatt halt el szinte minden linkelendő függvénynél. Szerencsére hallottam már a problémáról, röpke 10 perc alatt rájöttem.
Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
Új hozzászólás Aktív témák
● ha kódot szúrsz be, használd a PROGRAMKÓD formázási funkciót!
- NVIDIA GeForce RTX 4080 /4080S / 4090 (AD103 / 102)
- Drive! - Az utolsó gurulás idén a Quadrifoglio-val
- PlayStation 5
- DUNE médialejátszók topicja
- Azonnali VGA-s kérdések órája
- AMD Navi Radeon™ RX 7xxx sorozat
- Házimozi projektorok, kiegészítőik és kialakítások haladóknak
- Futás, futópályák
- Motoros topic
- Nők, nőügyek (18+)
- További aktív témák...
Állásajánlatok
Cég: PCMENTOR SZERVIZ KFT.
Város: Budapest