ट्रैक
/
C++
C++
/
अभ्यास
/
लसाग्ना मास्टर
लसाग्ना मास्टर

लसाग्ना मास्टर

सीखने का अभ्यास

परिचय

शब्दावली

आप पहले ही कुछ कॉन्सेप्ट में C++ के फंक्शन इस्तेमाल कर चुके हैं और लिख चुके हैं। अब तकनीकी बारीकियों में उतरने का समय है। नीचे दिया गया कोड स्निपेट आसान संदर्भ के लिए सबसे आम शब्द दिखाता है। चूँकि C++ व्हाइटस्पेस को अनदेखा करता है, फॉर्मैटिंग इस तरह बदली गई है कि हर एलिमेंट एक ही लाइन पर आ जाए।

// 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

घोषणा कंपाइलर के लिए एक नोट की तरह काम करती है, जो बताती है कि इस नाम, रिटर्न टाइप और पैरामीटर लिस्ट वाला एक फंक्शन मौजूद है। अगर परिभाषा मौजूद न हो, तो कोड काम नहीं करेगा। घोषणाएँ ज़रूरी नहीं हैं, लेकिन अगर आप फंक्शन को उसकी परिभाषा से पहले इस्तेमाल करते हैं तो इनकी ज़रूरत पड़ती है। घोषणाएँ साइक्लिक रेफरेंस जैसी समस्याएँ हल कर सकती हैं और इन्हें इंटरफ़ेस को इम्प्लीमेंटेशन से अलग करने के लिए भी इस्तेमाल किया जा सकता है।

const क्वालिफायर

कभी-कभी आप यह पक्का करना चाहते हैं कि वैल्यू इनिशियलाइज़ होने के बाद बदली न जा सके। C++ कॉन्स्टेंट के लिए क्वालिफायर के रूप में const कीवर्ड इस्तेमाल करता है।

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

आप अक्सर कॉन्स्टेंट को UPPER_SNAKE_CASE में लिखा हुआ देखेंगे। अगर कोई और कन्वेंशन न हो, तो इस केसिंग को मैक्रो के लिए आरक्षित रखने की सलाह दी जाती है।

किसी कॉन्स्टेंट वेरिएबल को सेट होने के बाद बदलने की कोशिश करने पर आपका कोड कंपाइल नहीं होगा। इससे अनजाने में हुए बदलावों से बचने में मदद मिलती है और कंपाइलर के लिए ऑप्टिमाइज़ेशन की संभावनाएँ भी खुलती हैं। एक इंसान के तौर पर भी, अगर आप जानते हैं कि कोड के कुछ हिस्से प्रभावित नहीं होंगे, तो कोड के बारे में सोचना आसान हो जाता है।

आप const को फंक्शन के पैरामीटर के लिए क्वालिफायर के रूप में भी इस्तेमाल कर सकते हैं।

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

जब आप फंक्शन को कोई const रेफरेंस पास करते हैं, तो आप निश्चिंत रह सकते हैं कि वह बदला नहीं जाएगा। जिन ऑब्जेक्ट को कॉपी करना महँगा पड़ सकता है, जैसे लंबी स्ट्रिंग, उनके लिए आप अक्सर const रेफरेंस देखेंगे। const क्वालिफायर का तीसरा उपयोग ऐसे मेंबर फंक्शन हैं जो क्लास के इंस्टेंस को नहीं बदलते।

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

Stubborn का मेंबर फंक्शन answer पैरामीटर के रूप में const string& रेफरेंस इस्तेमाल करता है। इससे उस मूल ऑब्जेक्ट की कॉपी बनाने की ज़रूरत नहीं पड़ती जो फंक्शन को पास किया गया था।

फंक्शन ओवरलोडिंग

अगर पैरामीटर लिस्ट अलग हो, तो कई फंक्शन का नाम एक ही हो सकता है। इसे फंक्शन ओवरलोडिंग कहते हैं और आमतौर पर यह तब किया जाता है जब ये फंक्शन बहुत मिलते-जुलते काम करते हों।

रिटर्न टाइप के बिना फंक्शन का हेडर उस फंक्शन का टाइप सिग्नेचर होता है। टाइप सिग्नेचर में बदलाव होने पर एक नया फंक्शन बनता है।

play_sound उदाहरण में अलग-अलग परिस्थितियों के लिए छह अलग-अलग ओवरलोड हैं:

// 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

टाइप सिग्नेचर फंक्शन के नाम, पैरामीटर की संख्या, उनके टाइप और उनके क्वालिफायर से तय होता है (लेकिन उनके नाम से नहीं)। रिटर्न टाइप जानबूझकर टाइप सिग्नेचर का हिस्सा नहीं है, और अगर आपके पास दो ऐसे फंक्शन हों जो सिर्फ रिटर्न टाइप में अलग हों, तो आपको कंपाइलेशन एरर मिलेंगी। कंपाइलर शिकायत करेगा, क्योंकि यह साफ़ नहीं होता कि इन दोनों में से किसे इस्तेमाल करना चाहिए।

डिफ़ॉल्ट आर्गुमेंट

कुछ फंक्शन बहुत लंबे हो सकते हैं, और उन्हें कॉल करते समय अक्सर ज़्यादातर पैरामीटर के लिए एक ही वैल्यू इस्तेमाल होती है। उन कॉल में होने वाले दोहराव को डिफ़ॉल्ट आर्गुमेंट से बचाया जा सकता है।

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"

चूँकि फंक्शन की घोषणा अक्सर परिभाषा से पहले पढ़ी जाती है, डिफ़ॉल्ट आर्गुमेंट सेट करने के लिए यही बेहतर जगह है। अगर किसी एक पैरामीटर की डिफ़ॉल्ट घोषणा है, तो उसके दाईं ओर के सभी पैरामीटर के लिए भी डिफ़ॉल्ट घोषणा ज़रूरी है। कभी-कभी मेंटेनेबिलिटी बेहतर करने के लिए जटिल फंक्शन ओवरलोड को रिफैक्टर करके डिफ़ॉल्ट आर्गुमेंट वाले कम फंक्शन बनाए जा सकते हैं।

निर्देश

इस अभ्यास में आप अपनी पसंदीदा रेसिपी की किताब से अपनी शानदार लसानिया तैयार करने और पकाने से जुड़ा कुछ और कोड लिखेंगे।

इसमें पाँच काम हैं। पहला काम पकाने से जुड़ा है, और बाकी चार बेहतरीन तैयारी से।

1. तैयारी के समय का अनुमान लगाइए

आगे जो लसानिया आप बनाएँगे, उसके लिए आप पर्याप्त समय बचाकर रखना चाहते हैं ताकि पकाने का आनंद ले सकें। आपने पहले ही तय कर लिया है कि आपके लसानिया में कौन-कौन सी लेयर होंगी। अब आप उसी के आधार पर अनुमान लगाना चाहते हैं कि तैयारी में कितना समय लगेगा।

एक फंक्शन preparationTime बनाइए जो लेयर के एक वेक्टर को string के रूप में और हर लेयर के लिए औसत तैयारी समय को मिनटों में int के रूप में लेता है। यह फंक्शन लेयर की संख्या के आधार पर कुल तैयारी समय का अनुमान int के रूप में लौटाना चाहिए। अगर औसत तैयारी समय नहीं दिया गया हो, तो डिफॉल्ट वैल्यू 2 इस्तेमाल की जानी चाहिए।

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

2. नूडल और सॉस की ज़रूरी मात्रा निकालिए

समय बचाने के अलावा, आप यह भी सुनिश्चित करना चाहते हैं कि अपने सपनों का लसानिया पकाने के लिए आपके पास पर्याप्त सॉस और नूडल हों। आपके लसानिया में नूडल की हर लेयर के लिए 50 ग्राम नूडल चाहिए। सॉस की हर लेयर के लिए 0.2 लीटर सॉस चाहिए।

फंक्शन quantities बनाइए, जो लेयर के एक वेक्टर को string पैरामीटर के रूप में लेता है। इसके बाद यह फंक्शन तय करेगा कि आपका खाना बनाने के लिए कितने नूडल और सॉस चाहिए। नतीजा एक amount स्ट्रक्चर के रूप में लौटाया जाना चाहिए, जो आपके लिए पहले से बना हुआ है। amount में दो मेंबर वेरिएबलो हैं, एक noodles के वज़न के लिए int के रूप में और दूसरा sauce के आयतन के लिए double के रूप में।

struct amount { int noodles; double sauce; };

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

3. गुप्त सामग्री जोड़िए

कुछ समय पहले आप एक दोस्त के घर गए थे और वहाँ लसानिया खाया था। वह बहुत शानदार था और उसमें कुछ खास था। उस दोस्त ने आपको सामग्री की सूची भेजी और बताया कि सूची की अंतिम चीज़ वह "गुप्त सामग्री" है जिसने खाने को इतना खास बनाया। अब आप उस गुप्त सामग्री को अपनी रेसिपी में भी जोड़ना चाहते हैं।

एक फंक्शन addSecretIngredient लिखिए जो दो vector of strings को पैरामीटर के रूप में लेता है। पहला पैरामीटर आपकी अपनी रेसिपी की सामग्री का एक रेफरेंस है, और दूसरा स्ट्रिंग का वेक्टर वह सामग्री रखता है जो आपके दोस्त ने भेजी। आपकी सामग्री सूची का अंतिम एलिमेंट हमेशा "?" होता है। यह फंक्शन उसे आपके दोस्त की सूची की अंतिम चीज़ से बदल देना चाहिए। ध्यान दें: addSecretIngredient कुछ नहीं लौटाता। आपको अपनी सामग्री की सूची को सीधे बदलना चाहिए। आपके दोस्त की सामग्री वाली सूची भी एक रेफरेंस हो सकती है (परफॉर्मेंस सुधारने के लिए), लेकिन उसे नहीं बदला जाना चाहिए। ध्यान रखिए कि वह सूची const रेफरेंस से बदली न जाए।

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. रेसिपी को स्केल कीजिए

आपकी रेसिपी की किताब में दी गई मात्राओं से सिर्फ दो हिस्सों के लिए पर्याप्त लसानिया बनता है। चूँकि अगली बार आपको ज़्यादा लोगों के लिए पकाना है, इसलिए आप अलग-अलग हिस्सों की संख्या के लिए मात्राएँ निकालना चाहते हैं।

एक फंक्शन scaleRecipe बनाइए जो दो पैरामीटर लेता है।

  • 2 हिस्सों के लिए ज़रूरी double मात्राओं का एक वेक्टर।
  • उन हिस्सों की संख्या जितने आप पकाना चाहते हैं।

यह फंक्शन चाहे गए हिस्सों की संख्या के लिए ज़रूरी मात्राओं का एक नया वेक्टर लौटाना चाहिए। लेकिन आप मूल रेसिपी को बनाए रखना चाहते हैं। इसका मतलब है कि इस फंक्शन में quantities आर्गुमेंट को नहीं बदला जाना चाहिए।

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

5. पारिवारिक गुप्त रहस्य खोलिए

आपको बचपन की वे कहानियाँ याद हैं, जो आपकी परदादी की बहन के बारे में थीं, परिवार के सबसे गहरे पाक रहस्यों की संरक्षक। कहा जाता है कि उनके पास कल्पना से परे स्वाद खोलने की चाबी है, लेकिन उनके तरीके अपरंपरागत हैं। वह सूचियों या मापों से काम नहीं करतीं; वह धीमी आवाज़ में बोलती हैं और एक बार में सिर्फ एक ही सामग्री बताती हैं।

उत्साह और घबराहट के बीच आप अपनी परदादी की बहन से संपर्क करने का फैसला करते हैं। जैसा अपेक्षित था, वह अपने रहस्यमय अंदाज़ में जवाब देती हैं और रहस्य में लिपटी एक ही गुप्त सामग्री देती हैं।

आपकी परदादी की बहन का योगदान एक और जटिलता जोड़ता है, जिसे आप अपनी रेसिपी में इस्तेमाल करना चाहते हैं। addSecretIngredient फंक्शन का एक और रूप बनाइए, जो दो आर्गुमेंट लेता है: आपकी सामग्री की सूची दर्शाने वाले एक वेक्टर का रेफरेंस, और आपकी परदादी की बहन से मिली रहस्यमय चीज़ को दर्शाने वाली एक स्ट्रिंग।

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

शुभकामनाएँ, बहादुर रसोइए!

GitHub के ज़रिए संपादित करें यह लिंक एक नई विंडो या टैब में खुलता है
C++ Exercism

लसाग्ना मास्टर शुरू करने के लिए तैयार हैं?

Exercism पर साइन अप कीजिए और C++ को 19 कॉन्सेप्ट100 अभ्यास तथा असली इंसानों से मिलने वाली मेंटरिंग के साथ सीखिए और उसमें महारत हासिल कीजिए, वह भी बिल्कुल मुफ्त।