- Samsung Galaxy S25 Ultra - titán keret, acélos teljesítmény
- Milyen okostelefont vegyek?
- Samsung Galaxy Z Fold7 - ezt vártuk, de…
- Honor 200 Pro - mobilportré
- T Phone 2 Pro - majdnem mindenben jobb
- Redmi Watch 5 - formás, de egyszerű
- 8000-es akksi került az IQOO Z10 Turbo+-ba
- Xiaomi 12 - az izmos 12
- Egy óra, két rendszer
- Samsung Galaxy Watch7 - kötelező kör
Hirdetés
Új hozzászólás Aktív témák
-
dobragab
addikt
iss >> hex csak egyszer kell, az elején, az az istream állapotaként megmarad.
Amit te keresel, az az std::getline.
std::getline(iss, temp, ':');
Hogy lehetne még javítani rajta, hogy későbbi IP cím operációkat lehessen végezni rajta?
A legmegfelelőbb adatszerkezetben tárolni. A beolvasás / kiírás szempontjából az uint16_t tömb tűnik legegyszerűbbnek, Linux API uint8_t tömböt használ.
-
dobragab
addikt
válasz
jattila48 #3470 üzenetére
Légy szíves írj már rá egy jó kódot, ha már az enyém annyira szar! De legyen aztán boost, regexp, STL, meg minden nyalánkság, ami egy igazán szép C++ kódba kell!
unsigned long long getFibonacciNumber(unsigned i)
{
static std::vector<unsigned long long> cache = {0, 1};
if(cache.size() > i)
return cache[i];
unsigned long long new_val = getFibonacciNumber(i-1) + getFibonacciNumber(i-2);
cache.push_back(new_val);
return new_val;
} -
dobragab
addikt
válasz
jattila48 #3456 üzenetére
Tessék! 9GAG-en sokadszor botlottam bele ebbe a stílusgyakorlatba reggel.
Annyit módosítottam a fejlécen, hogy
unsigned long long getFibonacciNumber(unsigned i)És írtam hozzá egy tesztprogramot:
int main()
{
unsigned long long result[1000];
clock_t start = clock();
for(int i = 0; i < 1000; ++i)
result[i] = getFibonacciNumber(1370 * i);
clock_t finish = clock();
for(auto n : result)
std::cout << n << ' ';
std::cout << ((finish - start) / double(CLOCKS_PER_SEC)) * 1000 << " ms" << std::endl;
return 0;
}Az én megoldásom a nemigazán bivalyerős laptopomon (i5-4200U) átlagosan 80 ms körül végez, és szépen tagolva 11 sor. Egyelőre nem lövöm le a kódot, hátha szeretnél és tudsz jobbat írni STL nélkül. Beégetett méretű tömb lehetőleg ne legyen benne, de amúgy bármi (szálkezelés is).
Összehasonlítási alap: egy egyszerű iteratív megoldás nálam 3800 ms körül teljesít.
-
dobragab
addikt
válasz
bandi0000 #3463 üzenetére
Amit te tanultál, az nem C++, hanem C. C++-ra hirtelen nem is tudok jót mutatni, de C-re igen.
Innen kezdd, és az előadások anyagait nézd elsősorban. Laborok anyagai kisebb-nagyobb gyakorlófeladatok az előadás anyagához, a gyakorlatok anyagában pedig "komolyabb" feladatokat találsz.
Soknak és gyorsnak tűnhet, de neked elég az első 6. előadás anyaga + némi hozzá tartozó gyakorlás.
-
dobragab
addikt
válasz
bandi0000 #3460 üzenetére
A 3-6-os feladatok mindegyike megoldható úgy, hogy nem tárolod el mind a memóriában. Pl:
int utolso_dobas;
while(fscanf(fp, "%d", &utolso_dobas) == 1)
{
// legutóbbi dobás kezelése
}Direkt nem írtam többet, ez pl. 2 sorral kiegészítve megoldja a 3-as feladatot.
És azért C, mert a kolléga eddig C-ben gyakorolt. Ugyanez C++-ban:
int utolso_dobas;
while(std::cin >> utolso_dobas)
{
// legutóbbi dobás kezelése
} -
dobragab
addikt
válasz
bandi0000 #3451 üzenetére
A memóriában minden karakter számként van tárolva, hogy melyik karakterhez milyen érték tartozik, azt itt meg tudod nézni, ez a leggyakrabban használt karakterek kódja. A többi karakternek a számértéke nem egységes, és elég macerás, arról nem kell tudnod.
A '0' karakterhez a decimális 48 tartozik, és azt követően minden számjegyhez eggyel nagyobb. Amikor string-ként olvasol be, akkor valójában sok karaktert kapsz, ezért kell kivonnod belőle '0'-t, hogy a karakter konkrét számértékét kapd.
-
dobragab
addikt
válasz
dabadab #3450 üzenetére
#define in :
(#3452) jattila48
Nem azért kötünk bele minden szirszarba, mert ez nekünk jól esik, pont fordítva. Mert rossz nézni azokat a kódokat, amiket tanítási céllal írsz be. Az a kolléga, aki tanulni jön ide, nem biztos, hogy észreveszi, hogy szar, több sebből vérzik, esetleg gyanútlanul be is másolja a kódot, vagy úgy gondolja, így kell kódot írni.
A legutóbbi kérdés ráadásul annyival bonyolultabb ügy, hogy a kolléga útmutatást kért, hogyan csinálja meg, nem algoritmust, vagy konkrét kódot. Ha szigorú lennék, azt mondanám, elvetted a felfedezés élményét is, de ez bőven megbocsátható. Szemben azzal, hogy útmutatásként szar kódot kapott.
Jó, sarkítottam, én is tudom, de a lényeg talán átmegy.
-
dobragab
addikt
válasz
jattila48 #3435 üzenetére
Csak az algoritmust akartam bemutatni, hogy mennyire egyszerű, és nem kellett hozzá sem boost, sem regexp, sem vector<string>, amiknél feltehetőleg jóval hatékonyabb így (futásidőben, és memória használatban is (főleg ha helyben történik a feldolgozás)).
Van még egy dolog, amit nem vettél számításba, vagy csak tojtál rá. A kolléga, aki segítséget kért, tanul. Ez fontos következményekkel jár.
1. Nem kéne mindent a hatékonyságra fogni. Az lenne a lényeg, hogy egyszerű, világos megoldást mutass neki, amit könnyen felfog, megért, és reprodukálni is tudna.
2. Neked sok-sok év tapasztalatod van abban, hogy hogyan hatékonyabb, és mindent ennek alávetve írsz meg. Ő most ismerkedik a nyelv lehetőségeivel, és pont lesz*rja, mennyire hatékony, ha érti. Gőze sincs arról, hogy hogyan kéne hatékony kódot írni, és ne is próbáld erre nevelni, mert ahhoz tárgyi ismeretek hiányoznak. Ráadásul ha megpróbálja, annál rosszabb. Nem fog neki menni, de legalább érthetetlen kódot ír.
3. A kolléga tanul, és te példakóddal segítesz. Ilyenkor te - akarva, akaratlanul - oktatóként lépsz fel. Mivel hozzánk képest meglehetősen kevés kódot látott, zömmel a sajátját, baromi nagy hatással van rá, milyen kódot lát követendő mintaként. Olyan kódot, ami saját bevallásod szerint is több ponton rossz, nem nagyon kéne neki mutatni.
4. A kolléga további életében valószínűleg az ilyen szintű optimalizálás soha nem lesz fontos. Manapság sem illik C kódot írni az STL használata helyett, mert feleslegesen bonyolítja a kódot. Optimalizálni ráadásul csak akkor kéne, ha lassú a kód (a nyilvánvaló f*szságokat kivéve). Inkább arra kéne nevelni, hogy használjon STL tárolókat, azért vannak.
Így elsőre ennyi, ami az érdemi segítséget illeti.
-
dobragab
addikt
válasz
jattila48 #3441 üzenetére
Feltéve, hogy függvénybe rakod, csak akkor, ha így deklarálod:
restrict const char *ipv6_addr
És azt sem egyszerű megoldani, hogy juttatod ki az eredmény-tömböt a függvényből. Out paraméterrel persze lehet, de valahogy szebbnek tűnik rendes visszatérési értékként, std::string-ben.
-
dobragab
addikt
válasz
EQMontoya #3431 üzenetére
+1. A megoldás ránézésre jó, én csiszolnék rajta.
1. a trim nagyon enum-szagú
2. char* a 21. században?
3. Igen, szerintem helyben kéne végezni, egy std::string-en. Aztán betenni egy függvénybe, ami std::string&-et vár.Vagy std::ostringstream-be pusholni a karaktereket.
(#3432) jattila48
Szabványos C99. Sőt, egyetlen nem-C89 elemet használ, a for(int...
Szebb megoldás: írsz IPv6 osztályt, ahol uint16_t-tömböt tárolsz belül. Megírod a beolvasást, ami tetszőleges formátumú IPv6 címet be tud olvasni, és a kanonikus alakba visszaírást, és mindjárt egyszerre több feladatot oldottál meg.
Ha tényleg "csak" a rövidítés a feladat, ahhoz tényleg OP egy ilyen osztály, de ha használni kell az IPv6 címeket, nem igazán illik sztringben tárolni.
-
dobragab
addikt
válasz
ToMmY_hun #3424 üzenetére
A feladat első ránézésre nem tűnik elvetemültnek, de valahogy nem értem minden részletét.
Mátrixban kellene tárolnom trigonometrikus függvényeket, úgy, hogy ezek a függvényeket tartalmazó mátrixok egymással szorozhatóak legyenek.
Mit értesz két ilyen mátrix szorzatán? Ugyanúgy számolnád, ahogy rendes számokkal? Akkor mit jelent két ilyen függvény összege ill szorzata?
A függvények a következő alakot ölthetik: x * sin(y)
Itt x és y változók, vagy paraméterek?
-
dobragab
addikt
válasz
dabadab #3419 üzenetére
Jogos, ott a pont.
Én a dinamikusan típusos nyelvekre gondoltam, tényleg rosszul fogalmaztam
if a > 5:
b = "hello"
else:
b = False
print(b)Szóval a változódeklaráció hiánya, egy változó típusának mágikus megváltozása, a változók élettartamának ilyen értelmezésével... leginkább káosz
(#3420) ToMmY_hun
Igen, ismerem a viccet, szerintem is zseniális
Na mindegy, befejezem a Python hate factory-t, túlzottan off.
-
dobragab
addikt
válasz
Ereshkigal #3405 üzenetére
A C++98 mára egy elég jól dokumentált és fefedezett nyelv, azt szerintem tényleg 9/10-re ismeri.
Viszont folyamatosan kerülnek bele új feature-ök. C++11 még egészen jól követhető. C++14 nem hozott annyi gyökeres újdonságot, mint a C++11, de azért volt bőven. A C++17 tervezete és az eddig elfogadott módosítások alapján már most elég vad (operator. például), ezt érdemes végigcsemegézni. Fogadni mernék, hogy ebben is találnak majd olyan hidden feature-öket, mint anno a template metaprogramming volt.
Úgyhogy szerintem nem ismeri jobban a C++-t, mint 7/10, max. 5/7
-
dobragab
addikt
válasz
EQMontoya #3358 üzenetére
Szerintem nem annak kéne hívódnia.
int operator,(std::ostream&, int) <- ezt a fordító generálta
int operator,(proxy, int) <- ezt én írtamEzek közül szerintem annak kéne hívódnia, amihez nem kell típuskonverzió, jelen esetben az elsőnek. Ha azt akarnám, hogy itt is az enyém hívódjon, akkor felüldefiniálnám ezt:
int operator,(std::ostream&, int) <- már ezt is én írtam
Szóval felül tudom csapni.
-
dobragab
addikt
Napi mitírki ultimate edition. EZT a kódot nézegetve mondta valaki, hogy még lehetne rajta csavarni egyet. Nekiálltam, és olyan jól sikerült, hogy saját magam is meglepődtem az eredményen. Ha bárki megmondja futtatás nélkül az eredményét, vendégem egy sörre, és ezt nyugodtan vehetik fenyegetésnek.
Vigyázat, C++11 intensifies.
#include <iostream>
class printable {};
struct proxy {
std::ostream& os;
proxy(std::ostream& os) :
os(os) {
}
};
proxy operator<<(std::ostream& os, printable p) {
os << "hello";
return proxy(os);
}
int operator,(proxy p, int n) {
p.os << "world" << std::endl;
return n;
}
template <typename... ARGS>
void print(ARGS const &... args)
{
using swallow = int[];
(void) swallow {0, ( (std::cout << args), 0)...};
}
int main()
{
print(printable());
print(1);
return 0;
} -
dobragab
addikt
Ilyen esetben nem gáz struktúrát használni, sőt, azt kellene. Ez így elég ronda. Valahogy így érdemes:
class Merkozes
{
public:
int fordulo;
int hazaigol;
int idegengol;
int hazaifelidogol;
int idegenfelidogol;
string hazaicsapat;
string vendegcsapat;
};
std::istream& operator>>(std::istream& be, Merkozes& M)
{
Merkozes result;
be >> result.fordulo;
be >> result.hazaigol;
be >> result.idegengol;
be >> result.hazaifelidogol;
be >> result.idegenfelidogol;
// nem biztos, hogy kell, de
// int után string-et beolvasni nem mindig egyszerű
be >> std::ws;
be >> result.hazaicsapat;
be >> result.vendegcsapat;
}
class Merkozesek {
private:
std::vector<Merkozes> adatok;
public:
Merkozesek();
~Merkozesek();
void Kiir();
void Gyoztes();
void Nev();
void Statisztika();
};
Merkozesek::Merkozesek(){
ifstream be("eredmenyek.txt");
if (be.fail()) {
cerr << "hiba";
system("pause"); // jáj, mér?
exit(1);
}
Merkozes M;
while (be >> M)
adatok.push_back(M);
}Így már nem szivárog (ömlik) a memória.
-
dobragab
addikt
válasz
jattila48 #3325 üzenetére
Vagyis nem feltétlenül a taginicializáló listában írt sorrendben (néhány fordító warning-ot generál, ha a taginicializáló lista sorrendje eltér a deklaráció sorrendjétől). Ezek után hajtódik végre a szóban forgó objektum ctorának törzse.
Pontosan. Mivel az inicializáló listát már ismeri, feltételeztem, ezzel is tisztában van.
Normális fordítóktól kapsz ilyenkor warning-ot, különben _nagyon_ könnyű hibás kódot írni.
class String
{
char * data;
size_t size;
public:
String(char* d, size_t s) :
size(s),
data(new char[size+1])
{
// ...
}
// ...
};Első ránézésre nem is látszik, miért hibás a kód, ha a fordítótól nem kapsz warningot, órákig keresheted.
Ha egyáltalán generálható implicit move operáció, akkor az kb. ugyanaz mint a copy operáció, ezért fölösleges a move.
Háát... nem. Ha az Example osztálynak adattagja egy std::vector, marhára nem mindegy, hogy az Example-nek generál-e move ctort, vagy nem. Ha generál, a vector is move-olódni fog, míg ha nem, másolódik (ahol beleszólhat a copy elision, de ezt most hagyjuk).
-
dobragab
addikt
válasz
EQMontoya #3321 üzenetére
Konkrétan C++98-ban:
- default ctor: végighívja az ősosztályok és adattagok default ctor-át, sorrendben. Ha írsz bármilyen ctort, ami nem copy ctor, bukod a default ctort, kézzel kell írnod, ha akarsz. (vagy = default, C++11-ben)
- copy ctor: végighívja az ősosztályok és adattagok copy ctor-át, sorrendben.
- operator=: végighívja az ősosztályok és adattagok operator=-jét, sorrendben.
- dtor: végighívja az adattagok és ősosztályok dtor-át, ebben a sorrendben- címképző operátor (&)
- vessző operátor (,)Ehhez hozzá jön a C++11-es move ctor és move assignment operator, ami ha kínai, nézz utána alaposan a jobbérték referenciáknak.
- move ctor: a move ctor-okat hívja végig, ha van, egyébként a copy ctort
- move op=: a move op=-ket hívja végig, ha van, egyébként a sima op=-tEz a kettő csak akkor van, ha
- nincs a felhasználó által írt copy ctor vagy dtor,
- nincs a felhasználó által írt másoló vagy move operator=,
- nincsen valami miatt implicit törölve (például mert az egyik adattagé törölve van).Mindennek az a célja, hogy az erőforráskezelést el tudd rejteni egy-egy erre specializált osztály belsejébe, pl. string vagy vector. Ezeket aztán máshol úgy tudod használni, mint egy sima int-et, mert a fordító mindig tudja, mikor mit kell meghívni. A felsőbb szintű (nem erőforráskezelő) osztályoknak nem kell foglalkoznia a fent említett tagfüggvényekkel, a default is úgy fog működni, ahogy elvárjuk.
Nyilván ez nagyon le van egyszerűsítve, de nagyságrendileg stimmel.
Jávához képest: van destruktor, mégpedig arra, hogy bármilyen erőforrást (memória, fájl, mutex, grafikus memória, stb.) becsukjon. Ha jól tervezed meg az osztályaidat, ezek mind automatikusan történnek. A GC ennél butább, mert csak memóriát szabad / lehet rábízni.
Jó, igen a finalize-ra elvileg rá lehet bízni pl. egy fájl bezárását, de az ki tudja, mikor fut le... Nagyon nem vicces nyitva hagyni egy fájlt random ideig, amíg a GC össze nem szedi a memóriában lévő objektumot. Ezért van jávában minden fájlkezelős történet try - catch - finally blokkban, hogy akármi történik, kézzel be tudd csukni a fájlt. C++-ban a compiler biztosan becsukja a fájlt a blokk végén (fstream).
Kicsit elkanyarodtam a kérdéstől. Remélem, azért mondtam újat, rosszat meg nem
-
dobragab
addikt
válasz
jattila48 #3307 üzenetére
Kezdőknek pedig nem OOP szemléletet és STL-t kell tanítani, hanem írja meg C-ben az alap algoritmusokat (keresés, rendezés, stb), értse meg a paraméterátadás rejtelmeit (érték, cím,...), írjon rekurzív fv. hívást, stb. Ez később mind hasznára fog válni, amikor már a C++ esetleg magasabb szintű absztrakcióit használja. Pontosabban enélkül, soha nem lesz belőle jó C++ programozó.
Tökéletesen egyetértek.
Igazából lényegtelen, hogy C vagy C++ a nyelv, de C++-ban egy csomó olyan dolog van, aminek dependency-je, hogy értse, hogyan van C-ben.
Például amíg nem tudja _tökéletesen_, mi az a pointer, nem kéne sem referenciát, sem okos pointert tanulni. Sőt, okos pointereket csak azután kéne, hogy megvolt az OOP, a RAII, a template és esetleg a jobbérték referencia.
Amíg nem érti tökéletesen, mi az a tömb, hogy a méretét nem tudja lekérdezni függvényből, hogy mi köze a pointerhez, stb. addig nem szabad neki std::vectort tanítani, mert utána már sosem tanulja meg, mi is az a tömb.
std::string-et is csak azután kéne tanítani, hogy érti a tömböket, használta a karaktertömböket, stb.
Fvptr -> öröklés ugyanez.
Szóval sorolhatnám még a dependency-ket, de nem sok értelme van. Az a lényeg, hogy ezeket be kell tartani, és bizony C-ben nem lehet ezt a szabályt megszegni, mert nincsenek ilyen cuccok. C++-ban sokkal könnyebb "rossz útra tévedni", míg C-ben nem lehet. Ha betartja ezeket a játékszabályokat, akkor a C++ jobb lehet, mert egy csomó f*szságot meg tud úszni a scanf-től a qsort-ig, de jóval nehezebb ezeket betartani.
-
dobragab
addikt
válasz
ToMmY_hun #3265 üzenetére
Mingw-gcc frankón bánik a threadekkel, hiszen betartja a szabványt: és a C++11 szabványban minden van, ami a multithreading-hez kell.
(#3263) jattila48
VS2015 mint IDE zseniális, ha lehetne mingw-vel használni, tökéletes lenne, de tök más a fordító paraméterezése, max. Intel compilerre tudnám cserélni. Az MSVC meg kritikán aluli.
C++ fordítója is a legjobbak között lehet, bár nem mindig tartja be a szabványt.
Remek, ezzel a legfontosabb kritériumot bukta. Azóta nem voltam hajlandó használni, amikor egyszer C-ben egy három paraméterrel előre deklarált függvényt egyetlen paraméterrel hívtam, és lefordult
Adott warningot, de akkor is, ez mi?
-
dobragab
addikt
válasz
jattila48 #3259 üzenetére
Ez nem a C++ libek telepítési nehézsége, hanem az összes Windows szegénységi bizonyítványa. Jól működő operációs rendszeren ennél kicsit egyszerűbb a dolog.
sudo apt-get install libboost-all-dev
A futtatáshoz szükséges binárisokat meg könnyebb beszerezni, akár Win, akár Linux, a Windows-ra fordításhoz ott a mingw-gcc cross.
-
dobragab
addikt
válasz
dabadab #3238 üzenetére
Szerintem a multimap miatt van így. multimap-nél van értelme a count-nak, mindenképp meg kell írni a count-ot. Mást jelent a contains, felesleges lett volna megírni, mert használhatod helyette a count-ot is minden értelmes kontextusban.
bool asd = mmap.count("idk");
if(mmap.count("idk"))
...Megírhatták volna a contains-t is, de minek? Egyetlen int->bool típuskonverzió miatt? Ha nem akarsz a visszatérési értékkel pl. template osztályt példányosítani, semmi baj vele.
bool contains(Key key)
{
return count(key);
} -
dobragab
addikt
válasz
ToMmY_hun #3235 üzenetére
Az enyémben ugye ellenőrizni kell, hogy rendelkezésre áll-e az ID, és ez a lista egy sima vector-ban van tárolva, amiben iterálva keresek.
Gyorsabb lenne a különálló map-ekben keresni, mint egy vector-t lineárisan végignyalni. Ha már mindenáron önálló nyilvántartást vezetsz róluk, arra az std::set való.
Trükkös a map és a set, contains függvényük nincs, illetve van, de count-nak hívják.
-
dobragab
addikt
válasz
jattila48 #3226 üzenetére
Valóban.
template<typename T>
void print(std::vector<T> const& vec)
{
for(int i = 0; i < vec.size(); ++i)
std::cout << vec[i] << ' ';
}És igen, minden saját osztályra, amit ki szeretnél írni, érdemes overload-olni az operator<<-t.
std::ostream& operator<<(std::ostream& os, Ratio r) // tört osztályra
{
os << r.get_num() << '/' << r.get_den();
return os;
} -
dobragab
addikt
válasz
ToMmY_hun #3223 üzenetére
Jó irányba tapogatózol, a template a megoldás. Amit te keresel, az az std::vector. Mindent tud, ami neked valaha kelleni fog dinamikus tömb szintjén. Egyrészt tud automatikusan megnyúlni (push_back), viszont előre is le tudja foglalni a memóriát, és nem kell nyújtózkodnia, ha konstruktorparaméterként adod neki a darabszámot, vagy reserve-ölsz. Természetesen ezután is tud megnyúlni.
Túl jávásan gondolkozol. Egyrészt teljesen felesleges nekik ősosztály, anélkül is lehet különböző típusokat megetetni egy generikus algoritmussal: erre való a template. Másrészt a get helyett C++-ban illik indexelő operátort használni.
std::vector<int> vec(100); // 100 darab helyet lefoglal előre,
// de nem tölti fel, egy darab int sem kerül bele
vec.push_back(1); // belekerült az első elem
for(int i = 0; i < vec.size(); ++i)
std::cout << vec[i];Egy generikus algoritmus lényege a duck typing: minden, ami úszik, és hápog, az kacsa. Másképp: az alábbi algoritmus bármilyen típust tartalmazó vector-ral működni tud, aminek van rendes (std::ostream-et visszaadó) << operátora. Ha te ezt meghívod std::vector<int>-ekre, akkor a fordító fordítási időben legenerálja neked a print<int>-et, mert az int úszik és hápog (van << operátora).
template<typename T>
void print(std::vector<T> const& vec)
{
std::cout << vec(i) << ' ';
} -
dobragab
addikt
válasz
ToMmY_hun #3210 üzenetére
Van mód arra, hogy ne a default-ot hívja meg a leszármazott, mégpedig inicializáló listán. A "setter" ctort akár protected-be is teheted.
class Parent
{
int id;
protected:
Parent(int id) :
id(id)
{ }
public:
Parent() {}
};
class Child : public Parent
{
public:
Child() :
Parent(0)
{ }
}; -
dobragab
addikt
válasz
jattila48 #3208 üzenetére
Fordítsd normális fordítóval, ami támogatja a C++11-et, a zárójelek is rendben vannak. Pl. MinGW-GCC 4.8+
Létrehoz egy int-ekből álló tömböt, amit nullákkal tölt fel, és feltöltés közben egyesével kiírja az argumentumokat. Majd ezt a tömböt eldobja, mert nekünk csak a kiírás kellett, a (void) a compiler warning miatt kell.
Tudtommal ez a legegyszerűbb implementációja a variadic template-es mindent kiíró függvénynek, általában két függvény kell hozzá.
-
dobragab
addikt
Heti fun. Nem én írtam, úgy küldték még régebben, szerintem zseniális.
template <typename... ARGS>
void print_stuff (ARGS const &... args)
{
using swallow = int[];
(void) swallow {0, ( (std::cout << args), 0)...};
} -
dobragab
addikt
Szerintem egy nagy példán belül az összes tárolót nem tudod bemutatni. Ha találsz is egy példát, az vagy túl nagy lenne, vagy erőltetett. Jól van az, hogy mindenre találsz külön-külön példát.
-
dobragab
addikt
Persze. C++-ban az eredeti is valid, csak nem sok értelme van.
Mondtam a csávónak: sel = !sel;
Válasz: Mindegy, megoldottam iffel.Időnként olyan érzésem van, hogy a javac dönti el, mit tud a nyelv, és mit nem. A szabvány luxus lenne. A mai napig nem tudom, miért nem fordult le.
-
dobragab
addikt
Napi golden code. Régebben küldték, most eszembe jutott, és előtúrtam nektek
sel?(sel=false):(sel=true);
Slusszpoén: azért küldték, mert nem fordult le... jávában... És jávában ez tényleg invalid.
-
-
dobragab
addikt
válasz
EQMontoya #3112 üzenetére
Erős egyszerűsítés, szándékosan. Az eredmény végül is az, hogy a globális op new hívódik, és nem malloc. Tudod ellenőrizni, ha felüldefiniálod az op new-t.
#include <memory>
#include <vector>
#include <iostream>
#include <cstdlib>
void * operator new(size_t size)
{
std::cout << "op new!" << std::endl;
void * ptr = malloc(size);
if (ptr == nullptr)
throw std::bad_alloc();
return ptr;
}
int main()
{
std::vector<int> vec;
vec.push_back(1);
return 0;
}És ez a nullptr kivételével szabványos C++98.
-
dobragab
addikt
válasz
EQMontoya #3110 üzenetére
Akár egy struct-ot is lehet malloc-kal foglalni, és utána adattagonként inicializálni, bár jobb helyeken kétszeri lefejezés jár érte.
std::vector tudomásom szerint nem malloc-ot hív, hanem ::operator new-t. Ez a tény mondjuk C++ alapjai vizsgán erős.
Szóval kezdőknek: a fő különbség, hogy a new hívhat ctort a lefoglalt memóriaterületre, míg a malloc nem. Ha nem kell ctort hívni, simán helyettesítheti, de ez általában csak alaptípusnál fordul elő. Az részletkérdés, hogy kicsit máshogy kell használni, és más a hibajelzés módja.
-
dobragab
addikt
Boldog karácsonyt mindenkinek!
On the first day of Christmas my true love gave to me
a partridge in a pear tree.
On the second day of Christmas my true love gave to me
two turtle doves
and a partridge in a pear tree.
On the third day of Christmas my true love gave to me
three french hens, two turtle doves
and a partridge in a pear tree.
On the fourth day of Christmas my true love gave to me
four calling birds, three french hens, two turtle doves
and a partridge in a pear tree.
On the fifth day of Christmas my true love gave to me
five gold rings;
four calling birds, three french hens, two turtle doves
and a partridge in a pear tree.
On the sixth day of Christmas my true love gave to me
six geese a-laying, five gold rings;
four calling birds, three french hens, two turtle doves
and a partridge in a pear tree.
On the seventh day of Christmas my true love gave to me
seven swans a-swimming,
six geese a-laying, five gold rings;
four calling birds, three french hens, two turtle doves
and a partridge in a pear tree.
On the eigth day of Christmas my true love gave to me
eight maids a-milking, seven swans a-swimming,
six geese a-laying, five gold rings;
four calling birds, three french hens, two turtle doves
and a partridge in a pear tree.
On the ninth day of Christmas my true love gave to me
nine ladies dancing, eight maids a-milking, seven swans a-swimming,
six geese a-laying, five gold rings;
four calling birds, three french hens, two turtle doves
and a partridge in a pear tree.
On the tenth day of Christmas my true love gave to me
ten lords a-leaping,
nine ladies dancing, eight maids a-milking, seven swans a-swimming,
six geese a-laying, five gold rings;
four calling birds, three french hens, two turtle doves
and a partridge in a pear tree.
On the eleventh day of Christmas my true love gave to me
eleven pipers piping, ten lords a-leaping,
nine ladies dancing, eight maids a-milking, seven swans a-swimming,
six geese a-laying, five gold rings;
four calling birds, three french hens, two turtle doves
and a partridge in a pear tree.
On the twelfth day of Christmas my true love gave to me
twelve drummers drumming, eleven pipers piping, ten lords a-leaping,
nine ladies dancing, eight maids a-milking, seven swans a-swimming,
six geese a-laying, five gold rings;
four calling birds, three french hens, two turtle doves
and a partridge in a pear tree. -
dobragab
addikt
válasz
jattila48 #3068 üzenetére
Remek, tényleg félreértettem. Azt eddig nem mondtad, hogy a blob formátuma egységes. Azt hittem, hogy a init az adattagokat kapja paraméternek. Így kicsit félrevezető, én nem init-nek nevezném, hanem read-nek, és tkp. ő végzi a deszerializációt.
Legközelebb inkább példakódot írj, azt hamarabb megértjük, mint fél oldal szöveget
Ebben az esetben viszont rendben van így is. Egyetértek veled, jobb ez a megoldás. Én nem kettős inicializálásnak hívnám, hanem a szerializálást kiraktad a D osztályba a RAII miatt.
-
dobragab
addikt
válasz
jattila48 #3064 üzenetére
Az std::string filename RAII-ra átalakításánál úgy gondoltam, a kissé kreatívabban oldod meg. Pl. kap még egy paramétert a privát ctor, ami átveszi az erőforrást, és felszabadítja. Így effektíven a D-nek a read_from_file a konstruktora. A hármas szabállyal most nem tököltem.
class D : public B
{
std::string filename;
FILE * fp = nullptr;
D(FILE * fp,
std::string const& filename,
std::vector<std::string> const& param1,
std::map<int, int> const& param2) :
B{param1, param2},
filename{filename},
fp{fp}
{ }
public:
static D read_from_file(std::string const& filename)
{
fp = fopen(filename.c_str(), "r+b");
std::vector<std::string> myvec;
std::map<int, int> mymap;
// load data from file to my___
return D{fp, filename, myvec, mymap};
}
virtual void pure_virtual_func() override
{ }
virtual ~D()
{
fclose(fp);
}
};Tehát a fájl megnyitás, és a memória terület foglalás nem a D ctor-ában történik, viszont az erőforrás felszabadítást (legalábbis a fájl lezárást) a dtor-ban akarod megoldani.
Nem ott van, szándékosan. Ha jól értem, B leszármazottai abban különböznek egymástól, hogy más külső reprezentációja. B-nek az a dolga, hogy ezeken felülemelkedjen, nélkülük legyen teljes értékű. Épp ezért B-nek nem szabad függnie tőle, azt oldják meg a leszármazottak.
Tényleg jobb lenne D konstruktorába pakolni az allokációt, de ebben a formában nem lehet megoldani. Az ős-ctor hívása mindenképp előbb van, mint a ctor törzse, úgyhogy arra nincs esélyed normálisan megoldani.
Ez egy felemás RAII lenne, ami szerintem koncepcionálisan hibás.
std::shared_ptr és make_shared? Szerintem ez a megoldás pont arra hasonlít. Mindenesetre a kötelezően hívandó init() szerintem ennél sokkal büdösebb: el lehet felejteni a hívását, és B többet tud, mint a feladata. Alapesetben nem kéne, hogy egy osztálynak legyen ctor-ként működő init-je.
Kicsit más jellegű lenne az a megoldás, ha B kap tisztán virtuális read() és write() függvényeket, és azokat override-olja D. Viszont read()-et nem hívhatod ctorból, úgyhogy ez nem működik.
-
dobragab
addikt
válasz
jattila48 #3061 üzenetére
Mutatok példát egyszerű osztályokkal. Én erre gondoltam, de a te eseted ezek szerint nem pont ilyen.
Kicsit elnéztem én is, ugyanis B-t (absztrakt osztályt) nem adhat vissza érték semmilyen a függvény...
class B
{
std::vector<std::string> member1;
std::map<int, int> member2;
public:
B() = delete;
B(const B& other) = default;
B& operator=(const B& other) = default;
B(B&& old) = default;
B& operator=(B&& old) = default;
B(std::vector<std::string> const& param1,
std::map<int, int> const& param2) :
member1{param1},
member2{param2}
{ }
virtual void pure_virtual_func() = 0;
virtual ~B() { }
};
class D : public B
{
std::string filename;
public:
D(std::string const& filename,
std::vector<std::string> const& param1,
std::map<int, int> const& param2) :
B{param1, param2},
filename{filename}
{ }
static D read_from_file(std::string const& filename)
{
std::ifstream file(filename);
std::vector<std::string> myvec;
std::map<int, int> mymap;
// load data from file to my___
return D{filename, myvec, mymap};
}
virtual void pure_virtual_func() override
{ }
};Ha valamit félreértettem a feladattal kapcsolatban, szólj
Kódból jobban értek -
dobragab
addikt
válasz
jattila48 #3058 üzenetére
Most már nekem is kicsit koncepcióhiba-szagú, persze simán lehet, hogy indokolt.
B ellátja a funkcióját, valamilyen adatokon dolgozik. Adsz neki egy ctort, ami az adattagjait darabonként inicializálja, és nem bűvészkedik a bináris adatokkal.
A bináris memóriaterületből olvasás, feldolgozhatóvá alakítás ilyen formában (pointer + méret) nem egy osztály dolga, hanem egy függvényé. Tipikusan egy statikus függvényé, ami megkapja fájlnevet, akármit, és visszaad érték szerint egy B-t. Én ebből csinálnék többet, attól függően, hogy fájl / registry / memória a forrás. Ezek hívják majd B adattagonként inicializáló konstruktorát. A statikus függvények meg lehetnek protected-ek, hogy a RAII-t ne lehessen kívülről zavarni, és hívhasd B / D ctorából. Írj B-nek move ctort, akár default is jó lehet.
Ezzel különválasztottad a program egyáltalán nem összetartozó részeit. B innentől önállóan is működőképes osztály, és hogy a te programodban mindig fájlból érkezik, az mellékes.
Ezután D konstruktora valahogy így nézhet ki:
D::D(std::string filename, T data) :
B{std::move(D::ReadFrom(filename))},
data{data}
{ }Ha B önmagában nem olvasható be, vagy D-vel együtt kellene, mert B beolvasása után kellenek még az adatok, D-t is adhat vissza a beolvasó függvény.
-
dobragab
addikt
válasz
jattila48 #3055 üzenetére
Írj B-nek konstruktort init helyett. Absztrakt osztálynak simán lehet konstruktora, pont az ilyen esetekre, és default ctor-t tiltsd le. D ctor-ban pedig B{args} az inicializáló listában.
A számításokat pedig szerintem el lehet végezni az inicializáló listában is, az ős-ctor hívása előtt, a paraméterekben, ha máshogy nem, vessző operátor segítségével
Szerk: ha bonyolultabbak a számítások, a statikus függvény jó ötlet
Factory? -
dobragab
addikt
Ez klasszikus
-
dobragab
addikt
Napi mitírki. Az első C, a második C++. Feltéve, hogy a char 1, az int 4 bájtos.
1.
printf("%d", sizeof('a'));
printf("%d", sizeof(+'a'));2.
std::cout << sizeof('a');
std::cout << sizeof(+'a'); -
dobragab
addikt
Nyissunk nektek Optimalizálás topikot?
-
dobragab
addikt
válasz
jattila48 #3012 üzenetére
Ha észrevetted, kapott már olyan választ, amilyet te elvársz. EQ megmutatta, hogy ezt igazán C++-osan hogyan illik. Pl. tőlem mindenképpen kapott volna egyszerű választ.
Ajánlom figyelmedbe Stroustrup intelmeit az Újszövetségből. (The C++ Programming Language 4th Edition)
[8] Minimize the use of arrays and C-style strings. C++ standard-library strings (§4.2), arrays (§8.2.4), and vectors (§4.4.1) can often be used to write simpler and more maintainable code compared to the traditional C style. In general, try not to build yourself what has already been provided by the standard library.
[10] Do not assume that something laboriously written in C style (avoiding C++ features such as classes, templates, and exceptions) is more efficient than a shorter alternative (e.g., using standard-library facilities). Often (but of course not always), the opposite is true.
-
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.
-
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.
-
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.
-
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]. -
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.
-
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.
-
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?
-
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];
Ú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!
- Kerékpárosok, bringások ide!
- Mibe tegyem a megtakarításaimat?
- gban: Ingyen kellene, de tegnapra
- AMD GPU-k jövője - amit tudni vélünk
- Opel topik
- CURVE - "All your cards in one." Minden bankkártyád egyben.
- Samsung Galaxy S25 Ultra - titán keret, acélos teljesítmény
- TCL LCD és LED TV-k
- Luck Dragon: Asszociációs játék. :)
- A lemondást javasolja az Intel vezetőjének Donald Trump
- További aktív témák...
- Lenovo Thinkpad Universal és Hybrid USB-C dokkoló, töltővel + USB-C kábellel!
- AKCIÓS áron eladó HP ZBOOK STUDIO G8 WORKSTATION! i7-11850H/32GB/RTX A2000/15,6"FHD/IPS/GARANCIA
- Asus TUF Dash F15 Gamer Laptop szép állapotban (RTX 3070, i7)
- Pioneer VSX-521-K + Jamo Sub 210
- YAMAHA RX-V6A 7.2 házimozi erősítő eladó
- iKing.Hu - Motorola Razr 40 Ultra Glacier Blue 8 GB RAM / 256 GB tárhely Használt, karcmentes
- LG 55C4 - 48" OLED evo - 4K 144Hz - 0.1ms - NVIDIA G-Sync - FreeSync - HDMI 2.1 - A9 Gen7 CPU
- Be Quiet! Pure Rock Pro 3 univerzális CPU hűtő (3év gari van rá 1x volt ki probálva )
- Azonnali A320 B350 X370 B450 X470 A520 B550 X570 chipset alaplap felvásárlás személyes/csomagküldés
- Eladó szinte karcmentes Samsung S21FE 5G 6/128GB / 12 hó jótállás
Állásajánlatok
Cég: FOTC
Város: Budapest