cpp:lamdas
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| cpp:lamdas [2026/05/21 21:28] – gthanos | cpp:lamdas [2026/05/22 08:13] (current) – [Παράδειγμα 1ο - Φιλτράρισμα και εξαγωγή μέσου όρου] gthanos | ||
|---|---|---|---|
| Line 25: | Line 25: | ||
| | [& | | [& | ||
| - | ==== Παραδείγματα Lamda ==== | + | ===== Παραδείγματα Lamda Expressions |
| + | |||
| + | ==== Παράδειγμα 1ο - Φιλτράρισμα και εξαγωγή μέσου όρου ==== | ||
| + | |||
| + | Στο παρακάτω παράδειγμα οι βαθμοί ενός φοιτητής, | ||
| <code cpp filter_and_average.cpp> | <code cpp filter_and_average.cpp> | ||
| Line 53: | Line 57: | ||
| } | } | ||
| </ | </ | ||
| + | |||
| + | <WRAP center round tip 80%> | ||
| + | Παρατηρούμε ότι το //Capture Clause// λαμβάνει τις μεταβλητές sum, count, threshold. Οι δύο πρώτες καλούνται με αναφορά και την ενημερώνουην μετά την έξοδο από τη lamda, ενώ η threshold καλείται με τιμή. | ||
| + | </ | ||
| + | |||
| + | === Πως διαχειρίζεται ο compiler το lambda expression; === | ||
| + | |||
| + | Ο compiler μετατρέπει τη λάμδα σε μια ανώνυμη κλάση (anonymous functor). Για την παραπάνω έκφραση //lamda// ο compiler δημιουργεί την παρακάτω ανώνυμη κλάση. | ||
| + | |||
| + | <code cpp lamda2functor.cpp> | ||
| + | class __lambda_unique_name { | ||
| + | private: | ||
| + | int& sum; // Capture by reference | ||
| + | int& count; | ||
| + | const int threshold; // Capture by value | ||
| + | |||
| + | public: | ||
| + | // Constructor για την αρχικοποίηση των captures | ||
| + | __lambda_unique_name(int& | ||
| + | : sum(_sum), count(_count), | ||
| + | |||
| + | // Ο τελεστής κλήσης (το σώμα της lambda) | ||
| + | // Είναι const εξ ορισμού, | ||
| + | void operator()(int g) const { | ||
| + | if (g >= threshold) { | ||
| + | sum += g; | ||
| + | count++; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // Ο compiler διαγράφει τον default constructor | ||
| + | __lambda_unique_name() = delete; | ||
| + | }; | ||
| + | </ | ||
| + | |||
| + | Παρατηρούμε ότι η μεταβλητή // | ||
| + | |||
| + | ==== Παράδειγμα 2ο - Αθροιστής ==== | ||
| + | |||
| + | Ας δούμε το παρακάτω παράδειγμα που απεικόνίζει έναν αθροιστή και μεταβάλει μία μεταβλητή που έχει περαστεί με τιμή στο //Clause//. | ||
| + | |||
| + | <code cpp sample_accumulator.cpp> | ||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | int main() { | ||
| + | // Το [total = 0] δημιουργεί μια εσωτερική μεταβλητή (capture by value). | ||
| + | auto add_to_total = [total = 0](int amount) mutable { | ||
| + | total += amount; // Η τροποποίηση επιτρέπεται μόνο λόγω του ' | ||
| + | return total; | ||
| + | }; | ||
| + | |||
| + | std:: | ||
| + | |||
| + | std::cout << " | ||
| + | | ||
| + | for (int bill : expenses) { | ||
| + | std::cout << " | ||
| + | << " | Current Total: " << add_to_total(bill) | ||
| + | << std::endl; | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Στο παράδειγμα, | ||
| + | |||
| + | <code cpp lamda2functor2.cpp> | ||
| + | class __lambda_accumulator_unique { | ||
| + | private: | ||
| + | int total; // Το εσωτερικό state (capture by value) | ||
| + | |||
| + | public: | ||
| + | // Constructor που αρχικοποιεί το total (στην περίπτωσή μας με 0) | ||
| + | __lambda_accumulator_unique(int initial_val) : total(initial_val) {} | ||
| + | |||
| + | /** | ||
| + | * Ο operator() ΔΕΝ είναι const. | ||
| + | * Αυτό συμβαίνει επειδή χρησιμοποιήσαμε τη λέξη ' | ||
| + | * Αν έλειπε το ' | ||
| + | * int operator()(int amount) const { ... } | ||
| + | * και η γραμμή total += amount θα έβγαζε error στη μεταγλώττιση. | ||
| + | */ | ||
| + | int operator()(int amount) { | ||
| + | total += amount; // Τροποποιούμε το data member της κλάσης | ||
| + | return total; | ||
| + | } | ||
| + | }; | ||
| + | </ | ||
| + | |||
| + | ==== Παράδειγμα 3ο - Password Cheker ==== | ||
| + | |||
| + | Παρακάτω δίνεται ένα πρόγραμμα που διαβάζει από ένα std::vector ένα σύνολο από passwords, εφαρμόζει κάποια κριτήρια για τον αν τα passwords είναι valid ή όχι και εκτυπώνει για κάθε passowrd τη θέση του στη λίστα και τόσα αστεράκια όσα είναι το μέγεθος του. Τα κριτήρια για το αν ένα passowrd είναι valid είναι α) μέγεθος τουλάχιστον 8 χαρκτήρες, | ||
| + | |||
| + | <code cpp password_checker.cpp> | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | //using namespace std; | ||
| + | |||
| + | int main() { | ||
| + | // Λίστα με passwords για έλεγχο | ||
| + | std:: | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | }; | ||
| + | |||
| + | // Λάμδα για τον έλεγχο εγκυρότητας | ||
| + | auto isValid = [specialChars = std:: | ||
| + | if (p.length() < 8) return false; | ||
| + | |||
| + | bool hasUpper = false, hasLower = false, hasDigit = false, hasSpecial = false; | ||
| + | |||
| + | for (char c : p) { | ||
| + | if (std:: | ||
| + | else if (std:: | ||
| + | else if (std:: | ||
| + | else if (specialChars.find(c) != std:: | ||
| + | } | ||
| + | |||
| + | return hasUpper && hasLower && hasDigit && hasSpecial; | ||
| + | }; | ||
| + | |||
| + | std::cout << " | ||
| + | std::cout << " | ||
| + | std::cout << " | ||
| + | |||
| + | for (size_t i = 0; i < passwords.size(); | ||
| + | bool valid = isValid(passwords[i]); | ||
| + | | ||
| + | // Εκτύπωση θέσης (i + 1) | ||
| + | std::cout << " | ||
| + | |||
| + | // Εκτύπωση αστερίσκων αντί για το password | ||
| + | std::string masked(passwords[i].length(), | ||
| + | std::cout << masked; | ||
| + | |||
| + | // Ευθυγράμμιση εξόδου (padding) | ||
| + | int padding = 15 - (int)passwords[i].length(); | ||
| + | for(int j=0; j < (padding > 0 ? padding : 1); ++j) std::cout << " "; | ||
| + | |||
| + | std::cout << "| " << (valid ? " | ||
| + | } | ||
| + | |||
| + | return 0; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ==== Παράδειγμα 4ο - Μετασχηματισμός ==== | ||
| + | |||
| + | Ας υποθέσουμε ότι έχουμε ένα // | ||
| + | |||
| + | <code cpp Student.hpp> | ||
| + | #ifndef _STUDENT_HPP_ | ||
| + | #define _STUDENT_HPP_ | ||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | class Student { | ||
| + | private: | ||
| + | char *name; | ||
| + | int aem; | ||
| + | public: | ||
| + | Student(); | ||
| + | Student(const char *name, int aem); | ||
| + | Student(const Student& | ||
| + | ~Student(); | ||
| + | | ||
| + | char* getName() const; | ||
| + | int getAEM() const; | ||
| + | void setName(char*); | ||
| + | void setAEM(int); | ||
| + | | ||
| + | friend std:: | ||
| + | bool operator> | ||
| + | bool operator< | ||
| + | Student& | ||
| + | }; | ||
| + | |||
| + | Student:: | ||
| + | this-> | ||
| + | strcpy(this-> | ||
| + | this-> | ||
| + | std::cerr << "Argu Construct : " << *this << std::endl; | ||
| + | } | ||
| + | |||
| + | Student:: | ||
| + | name = new char [strlen(st.name) + 1]; | ||
| + | strcpy(name, | ||
| + | aem = st.aem; | ||
| + | std::cerr << "Copy Construct : " << *this << std::endl; | ||
| + | } | ||
| + | |||
| + | Student:: | ||
| + | this-> | ||
| + | this-> | ||
| + | } | ||
| + | |||
| + | Student:: | ||
| + | if(name != nullptr) { | ||
| + | std::cerr << " | ||
| + | delete []name; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | char* Student:: | ||
| + | return name; | ||
| + | } | ||
| + | |||
| + | int Student:: | ||
| + | return aem; | ||
| + | } | ||
| + | |||
| + | void Student:: | ||
| + | this-> | ||
| + | delete this-> | ||
| + | this-> | ||
| + | strcpy(this-> | ||
| + | } | ||
| + | |||
| + | void Student:: | ||
| + | this-> | ||
| + | } | ||
| + | |||
| + | Student& | ||
| + | if(name != nullptr) | ||
| + | delete name; | ||
| + | name = new char [strlen(st.name) + 1]; | ||
| + | strcpy(name, | ||
| + | aem = st.aem; | ||
| + | std::cerr << "Copy : " << *this << std::endl; | ||
| + | return *this; | ||
| + | } | ||
| + | |||
| + | std:: | ||
| + | if(st.name != nullptr) | ||
| + | out << st.name << " " << st.aem; | ||
| + | return out; | ||
| + | } | ||
| + | |||
| + | bool Student:: | ||
| + | if(aem > st.aem) | ||
| + | return true; | ||
| + | return false; | ||
| + | } | ||
| + | |||
| + | bool Student:: | ||
| + | if(aem < st.aem) | ||
| + | return true; | ||
| + | return false; | ||
| + | } | ||
| + | #endif | ||
| + | </ | ||
| + | |||
| + | <code cpp trasfrorm_vector2vector.cpp> | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include " | ||
| + | |||
| + | int main() { | ||
| + | // 1. Αρχικό vector με 5 αντικείμενα Student | ||
| + | std:: | ||
| + | students.push_back(Student(" | ||
| + | students.push_back(Student(" | ||
| + | students.push_back(Student(" | ||
| + | students.push_back(Student(" | ||
| + | students.push_back(Student(" | ||
| + | |||
| + | // 3. Το ΝΕΟ vector όπου θα αποθηκευτούν οι φοιτητές που θα " | ||
| + | std:: | ||
| + | |||
| + | std::cout << "\n--- Φιλτράρισμα με Lambda σε νέο Vector ---\n" << std::endl; | ||
| + | |||
| + | // 2. Φιλτράρισμα και αποθήκευση στο νέο vector | ||
| + | std:: | ||
| + | | ||
| + | | ||
| + | | ||
| + | }); | ||
| + | |||
| + | // Εκτύπωση των αποτελεσμάτων του νέου vector | ||
| + | std::cout << "\n--- Φοιτητές στο Νέο Vector ---" << std::endl; | ||
| + | for (const auto& student : filteredStudents) { | ||
| + | std::cout << student << std::endl; | ||
| + | } | ||
| + | | ||
| + | std::cout << "\n--- Τέλος Προγράμματος ---" << std::endl; | ||
| + | return 0; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | <code cpp trasfrorm_vector2set.cpp> | ||
| + | #include < | ||
| + | #include < | ||
| + | #include <set> | ||
| + | #include < | ||
| + | #include < | ||
| + | #include " | ||
| + | |||
| + | int main() { | ||
| + | // 1. Δημιουργία vector με 5 αντικείμενα Student | ||
| + | std:: | ||
| + | students.push_back(Student(" | ||
| + | students.push_back(Student(" | ||
| + | students.push_back(Student(" | ||
| + | students.push_back(Student(" | ||
| + | students.push_back(Student(" | ||
| + | |||
| + | // 3. Το set όπου θα αποθηκευτούν οι φοιτητές που θα " | ||
| + | std:: | ||
| + | |||
| + | std::cout << "\n--- Φιλτράρισμα με Lambda και std:: | ||
| + | |||
| + | // 2. Φιλτράρισμα και αποθήκευση ταυτόχρονα | ||
| + | std:: | ||
| + | | ||
| + | | ||
| + | | ||
| + | }); | ||
| + | |||
| + | // Εκτύπωση των αποτελεσμάτων | ||
| + | std::cout << "\n--- Φοιτητές στο Set ---" << std::endl; | ||
| + | for (const auto& student : filteredStudents) { | ||
| + | std::cout << student << std::endl; | ||
| + | } | ||
| + | | ||
| + | std::cout << "\n--- Τέλος Προγράμματος ---" << std::endl; | ||
| + | return 0; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
cpp/lamdas.1779398934.txt.gz · Last modified: 2026/05/21 21:28 by gthanos
