Kurzusok
/
C++
C++
/
Feladatok
/
lasagne-mester
lasagne-mester

lasagne-mester

Tanulófeladat

Bevezetés

Terminológia

Már használtál és írtál C++ függvényeket néhány fogalomnál. Itt az ideje, hogy technikailag is belemenjünk. Az alábbi kódrészlet a leggyakoribb kifejezéseket mutatja be, hogy könnyen visszakereshesd őket. Mivel a C++ figyelmen kívül hagyja a whitespace-t, a formázást úgy alakítottuk át, hogy minden elem egy-egy külön sorba kerüljön.

// Function declaration:
bool                                              // Return type
admin_detected(string user, string password)      // Type signature
;                                                 // Don't forget the ';' for the declaration

// Function definition:
bool                                              // Return type
admin_detected                                    // Function name
(string user, string password)                    // Parameter list
{ return user == "admin" && password == "1234"; } // Function body
Advanced

A deklaráció olyan, mint egy üzenet a fordítónak: létezik egy függvény ezzel a névvel, visszatérési típussal és paraméterlistával. A kód nem fog működni, ha hiányzik a definíció. A deklarációk elhagyhatók, akkor van rájuk szükség, ha a függvényt a definíciója előtt használod. A deklarációk megoldhatnak olyan problémákat, mint a körkörös hivatkozások, és arra is használhatók, hogy elválasszák a felületet a megvalósítástól.

A const minősítő

Néha biztos szeretnél lenni benne, hogy az értékek a kezdeti értékadás után nem változtathatók meg. A C++ a const kulcsszót használja a konstansok minősítőjeként.

const int number_of_dragon_balls{7};
number_of_dragon_balls--; // compilation error
Note

A konstansokat gyakran UPPER_SNAKE_CASE írásmóddal látod majd. Ha nincs más konvenció, érdemes ezt az írásmódot a makróknak fenntartani.

Ha egy konstans változót a beállítása után megpróbálsz megváltoztatni, a kódod nem fog lefordulni. Ez segít elkerülni a nem szándékos változtatásokat, emellett optimalizálási lehetőségeket is nyit a fordító számára. Emberként is könnyebb átlátni a kódot, ha tudod, hogy bizonyos részek nem fognak változni.

A const-ot függvényparaméterek minősítőjeként is használhatod.

string guess_number(const int& secret, const int& guess) {
    if (secret < guess) return "lower.";
    if (secret > guess) return "higher.";
    return "exact!";
}

Amikor egy const referenciát adsz át a függvénynek, biztos lehetsz benne, hogy az változatlan marad. Gyakran látsz majd const referenciákat olyan objektumokhoz, amelyeket költséges lenne másolni, például hosszabb stringekhez. A const minősítő harmadik felhasználási esete az olyan tagfüggvények, amelyek nem változtatják meg az osztály egy példányát.

class Stubborn {
    public:
    Stubborn(string reply) {
        response = reply;
    }
    string answer(const string& question) const {
        if (question.length() == 0) { return ""; }
        return response;
    }
    private:
    string response{};
};

A Stubborn answer tagfüggvénye const string& referenciát használ paraméterként. Ez elkerüli a függvénynek átadott eredeti objektum másolását.

Függvénytúlterhelés

Több függvénynek is lehet ugyanaz a neve, ha a paraméterlistájuk különbözik. Ezt függvénytúlterhelésnek nevezzük, és általában akkor alkalmazzuk, ha ezek a függvények nagyon hasonló feladatokat látnak el.

A visszatérési típus nélküli függvényfejléc a függvény típusszignatúrája. A típusszignatúra megváltozása új függvényt eredményez.

A play_sound példának hat különböző túlterhelése van, hogy különböző helyzeteket lefedjen:

// different argument types:
void play_sound(char note);         // C, D, E, ..., B
void play_sound(string solfege);    // do, re, mi, ..., ti
void play_sound(int jianpu);        // 1, 2, 3, ..., 7

// different number of arguments:
void play_sound(string solfege, double duration);

// different qualifiers:
void play_sound(vector<string>& solfege);
void play_sound(const vector<string>& solfege);
Advanced

A típusszignatúrát a függvény neve, a paraméterek száma, típusa és minősítői határozzák meg (a nevük viszont nem). A visszatérési típus kifejezetten nem része a típusszignatúrának, és fordítási hibát kapsz, ha két függvényed csak a visszatérési típusban tér el. A fordító azért fog panaszkodni, mert nem egyértelmű, hogy a kettő közül melyiket kell használni.

Alapértelmezett argumentumok

Némelyik függvény nagyon hosszúra nyúlhat, és a hívásai közül sok ugyanazokat az értékeket használhatja a paraméterek többségéhez. Az ilyen hívásokban fellépő ismétlődést alapértelmezett argumentumokkal kerülheted el.

void record_new_horse_birth(string name, int weight, string color="brown-ish", string dam="Alruccaba", string sire="Poseidon");

record_new_horse_birth("Urban Sea", 130); // color will be brown, dam "Alruccabam", sire "Poseidon"
record_new_horse_birth("Highclere", 175, "off-white", "Fall Aspen");   // sire will be "Poseidon"

Mivel a függvénydeklarációt gyakran a definíció előtt olvassák, jobb hely az alapértelmezett argumentumok beállítására. Ha egy paraméternek van alapértelmezett deklarációja, akkor a tőle jobbra lévő összes paraméternek is szüksége van rá. Néha a bonyolult függvénytúlterhelések kevesebb, alapértelmezett argumentumokkal rendelkező függvényre refaktorálhatók a karbantarthatóság javítása érdekében.

Utasítások

Ebben a feladatban még egy kis kódot írsz, ami a kedvenc szakácskönyvedből származó remek lasagnéd elkészítéséhez és megsütéséhez kapcsolódik.

Öt részfeladat vár rád. Az első magával a sütéssel kapcsolatos, a másik négy a tökéletes előkészületről szól.

1. Becsüld meg az előkészítési időt

A következő lasagnához, amit elkészítesz, szeretnél elegendő időt félretenni, hogy nyugodtan élvezhesd a főzést. Már megtervezted, milyen rétegekből áll majd a lasagnéd. Most ebből szeretnéd megbecsülni, mennyi ideig tart majd az előkészület.

Készíts egy preparationTime függvényt, amely egy rétegekből álló vektort fogad string típusként, valamint a rétegenkénti átlagos előkészítési időt percben, int típusként. A függvény a rétegek száma alapján adja vissza a teljes előkészítési idő becslését int típusként. Ha nem adják meg az átlagos előkészítési időt, akkor a 2 alapértelmezett értéket kell használni.

std::vector<std::string> layers{"sauce", "noodles", "sauce", "meat", "mozzarella", "noodles"};
preparationTime(layers, 3)
// => 18
preparationTime(layers)
// => 12

2. Számítsd ki a szükséges tészta és szósz mennyiségét

Az idő félretétele mellett szeretnél arról is gondoskodni, hogy legyen elég szósz és tészta az álmaid lasagnájához. A lasagnád minden tésztarétegéhez 50 gramm tésztára lesz szükséged. Minden szószréteghez 0,2 liter szószra lesz szükséged.

Definiáld a quantities függvényt, amely paraméterként egy rétegekből álló vektort fogad string típusként. A függvény ezután meghatározza az étel elkészítéséhez szükséges tészta- és szószmennyiséget. Az eredményt amount struct formájában kell visszaadni, amelyet már definiáltunk neked. Az amount két tagváltozóval rendelkezik: az egyik a noodles tömegét tárolja int típusként, a második a sauce térfogatát double típusként.

struct amount { int noodles; double sauce; };

amount needed{quantities({"sauce", "noodles", "sauce", "meat", "mozzarella", "noodles"})};
// needed.noodles => 100
// needed.sauce => 0.4

3. Add hozzá a titkos hozzávalót

Nemrég meglátogattál egy barátodat, és lasagnát ettél nála. Fantasztikus volt, és volt benne valami különleges. A barátod elküldte a hozzávalók listáját, és azt mondta, hogy a lista utolsó eleme a „titkos hozzávaló”, amitől az étel olyan különleges lett. Most te is hozzá szeretnéd adni ezt a titkos hozzávalót a receptedhez.

Írj egy addSecretIngredient függvényt, amely két vector of strings paramétert fogad. Az első paraméter a saját recepted hozzávalóira mutató referencia, a második vektor pedig a barátod által küldött hozzávalókat tartalmazza. A hozzávalólistád utolsó eleme mindig "?". A függvény helyettesítse ezt a barátod listájának utolsó elemévvel. Megjegyzés: az addSecretIngredient nem ad vissza semmit, helyette közvetlenül a saját hozzávalóid listáját kell módosítanod. A barátod hozzávalóit tartalmazó lista szintén lehet referencia (a teljesítmény javítása érdekében), de nem szabad módosítani. Ügyelj rá, hogy a lista const referenciával ne módosuljon.

std::vector<std::string> friendsList{"noodles", "sauce", "mozzarella", "kampot pepper"};
std::vector<std::string> myList{"noodles", "meat", "sauce", "mozzarella", "?"};

addSecretIngredient(myList, friendsList);
// myList => {"noodles", "meat", "sauce", "mozzarella", "kampot pepper"}

4. Méretezd át a receptet

A szakácskönyvedben felsorolt mennyiségek csak két adag lasagnához elegendőek. Mivel legközelebb több emberre szeretnél főzni, szeretnéd kiszámítani a mennyiségeket különböző adagszámokhoz.

Készíts egy scaleRecipe függvényt, amely két paramétert fogad.

  • Egy double értékekből álló vektor a 2 adaghoz szükséges mennyiségekkel.
  • A megfőzni kívánt adagok száma.

A függvény egy új vektort adjon vissza a kívánt adagszámhoz szükséges mennyiségekkel. Az eredeti receptet viszont meg szeretnéd tartani. Ez azt jelenti, hogy a quantities argumentumot ebben a függvényben nem szabad módosítani.

std::vector<double> quantities{1.2, 3.6, 10.5};
scaleRecipe(quantities, 4);
// => { 2.4, 7.2, 21 }

5. Oldd fel a családi titkot

Emlékszel gyerekkori történetekre, mesékre a dédnagynénédről, aki a család legmélyebb kulináris titkainak őrzője. A legenda szerint nála van a kulcs az elképzelhetetlen ízek feloldásához, de a módszerei szokatlanok. Nem foglalkozik listákkal vagy mérésekkel; suttogva beszél, és egyszerre csak egy hozzávalót árul el.

Izgalom és szorongás keverékével úgy döntesz, hogy felveszed a kapcsolatot a dédnagynénéddel. Ahogy vártad, rejtélyes modorában válaszol, és egyetlen titkos hozzávalót kínál, misztériumba burkolva.

A dédnagynénéd hozzájárulása egy újabb réteget ad a bonyolultsághoz, amit szeretnél felhasználni a receptedben. Készítsd el az addSecretIngredient függvény egy másik változatát, amely két argumentumot fogad: egy referenciát a hozzávalóid listáját képviselő vektorra, és egyetlen stringet, amely a dédnagynénéd rejtélyes ajándékát képviseli.

std::vector<std::string> myList{"noodles", "meat", "sauce", "mozzarella", "?"};
std::string secretIngredient{"spice melange"};
addSecretIngredient(myList, secretIngredient);
// myList => {"noodles", "meat", "sauce", "mozzarella", "spice melange"}

Sok szerencsét, bátor séf!

Szerkesztés GitHubon A hivatkozás új ablakban vagy lapon nyílik meg
C++ Exercism

Készen állsz elkezdeni a(z) lasagne-mester feladatot?

Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) C++ nyelvet 19 fogalom100 feladat segítségével, valódi emberi mentorálással, mindez ingyen.