Διαδρομές
/
C++
C++
/
Ασκήσεις
/
Βάζοντας βαθμούς
Βάζοντας βαθμούς

Βάζοντας βαθμούς

Άσκηση εκμάθησης

Εισαγωγή

Πίνακες και Διανύσματα

Η C++ προσφέρει διαφορετικούς περιέκτες για να αποθηκεύεις στοιχεία του ίδιου τύπου με συγκεκριμένη σειρά. Υπάρχει το std::array για περιέκτες σταθερού μεγέθους και το std::vector, που έχει δυνατότητες δυναμικής αλλαγής μεγέθους.

Κατασκευή

Όταν δηλώνεις έναν πίνακα ή ένα διάνυσμα, πρέπει να καθορίσεις τον τύπο των στοιχείων που θα περιέχει ο περιέκτης. Οι πίνακες χρειάζονται επίσης ένα μέγεθος. Δες αυτά τα παραδείγματα για να δεις πώς αρχικοποιούνται οι δύο τύποι περιεκτών:

#include <array>
#include <string>

// std::array<element_type, size> variable_name {list of elements}
std::array<std::string, 3> indie_rock {"yeah", "yeah", "yeah"};
// indie_rock contains the elements "yeah" three times

Τα διανύσματα συνήθως χρειάζονται περισσότερο χώρο, καθώς δεσμεύουν μνήμη για περαιτέρω ανάπτυξη. Δε χρειάζεται να καθορίσεις μέγεθος:

#include <vector>

// std::vector<element_type> variable_name {list of elements}
std::vector<int> countdown {3, 2, 1};
// countdown contains the elements 3, 2 and 1

Σημείωση: Δε χρειάζεται να ξέρεις ακόμα τους ακριβείς μηχανισμούς πίσω από την έννοια του template. Θα έχει τη δική του έννοια πιο κάτω στο δέντρο του προγράμματος σπουδών.

Πρόσβαση στα στοιχεία

Τα διανύσματα και οι πίνακες μοιράζονται τις ίδιες συναρτήσεις για πρόσβαση στα στοιχεία τους. Μπορείς να χρησιμοποιήσεις τις συναρτήσεις μέλους front και back για να πάρεις το πρώτο και το τελευταίο στοιχείο του περιέκτη. Υπάρχει επίσης η at και ο τελεστής [] για πρόσβαση σε συγκεκριμένα στοιχεία.

countdown[0];
// => 3
countdown.at(2);
// => 1
countdown[1] = 4;
// countdown now contains 3, 4 and 1
indie_rock.back() = "yeahs";
// indie_rock is now "yeah", "yeah", "yeahs"

Σημείωση: Αν επιλέξεις μια θέση που δεν είναι στο εύρος του περιέκτη σου, ο [] μπορεί να οδηγήσει σε μη ορισμένη συμπεριφορά. Η συνάρτηση at θα πέταγε μια εξαίρεση, κάτι που μπορεί να σου κάνει τη ζωή πιο εύκολη μακροπρόθεσμα.

Τροποποιητές διανυσμάτων

Καθώς το vector δεν έχει σταθερό μέγεθος, είναι δυνατόν να προσθέτεις ή να αφαιρείς στοιχεία. Δύο συνηθισμένες συναρτήσεις γι' αυτόν τον σκοπό είναι οι emplace_back και pop_back.

std::vector<std::string> witches {"Holly", "Alyssa", "Shannen"};
witches.pop_back();
// Shannen is no longer with the witches
witches.emplace_back("Rose");
// Rose has joined the team

Χωρητικότητα

Μπορείς να ελέγξεις αν οι περιέκτες είναι άδειοι με τη συνάρτηση μέλους empty. Αν θέλεις να μάθεις τον αριθμό των στοιχείων, μπορείς να χρησιμοποιήσεις τη size.

Οδηγίες

Είσαι βοηθός διδασκαλίας και διορθώνεις διαγωνίσματα μαθητών. Η χειροκίνητη παρακολούθηση των αποτελεσμάτων γίνεται και κουραστική και επιρρεπής σε λάθη. Αποφασίζεις να κάνεις τα πράγματα λίγο πιο ενδιαφέροντα, φτιάχνοντας μερικές συναρτήσεις που θα μετρούν και θα υπολογίζουν τα αποτελέσματα της τάξης.

1. Στρογγυλοποίηση βαθμολογιών

Ενώ μπορείς να δώσεις "μερικούς βαθμούς" στις ερωτήσεις του διαγωνίσματος, οι τελικοί βαθμοί του διαγωνίσματος πρέπει να είναι int. Έτσι, πριν κάνεις οτιδήποτε άλλο με τους βαθμούς της τάξης, πρέπει να περάσεις από όλες τις βαθμολογίες και να μετατρέψεις κάθε βαθμολογία double σε int.

Δημιούργησε τη συνάρτηση round_down_scores() που παίρνει ένα vector από student_scores. Η στρογγυλοποίηση που ζητούν τα σχολεία είναι αποκοπή. Ευτυχώς για σένα, η C++ μπορεί να μετατρέψει έναν τύπο σε έναν άλλο με το static_cast. Η μετατροπή static_cast από double σε int κόβει κάθε ψηφίο μετά την υποδιαστολή. Αυτή η συνάρτηση πρέπει να παίρνει το vector εισόδου και να return έναν νέο vector με όλες τις βαθμολογίες μετατρεπόμενες σε int.

std::vector<double> student_scores {90.33, 40.5, 55.44, 70.05, 30.55, 25.45, 80.45, 95.3, 38.7, 40.3};
round_down_scores(student_scores)
// => {90, 40, 55, 70, 30, 25, 80, 95, 38, 40}

Υπάρχουν κι άλλοι τρόποι που πετυχαίνουν το ίδιο αποτέλεσμα, αλλά η μετατροπή τύπου είναι κάτι που το βλέπεις συχνά.

int new_PI{static_cast<int>(3.14) + static_cast<int>(0.001592653589)};
// new_PI is 3.

2. Μαθητές που δεν περνούν

Καθώς διόρθωνες το διαγώνισμα, παρατήρησες ότι κάποιοι μαθητές δεν τα πήγαιναν όσο καλά περίμενες. Αλλά αποσπάστηκες και ξέχασες να σημειώσεις πόσοι ακριβώς μαθητές ήταν.

Δημιούργησε τη συνάρτηση count_failed_students() που παίρνει ένα vector από student_scores. Αυτή η συνάρτηση πρέπει να μετράει τον αριθμό των μαθητών που δεν έχουν βαθμολογία επιτυχίας και να επιστρέφει αυτόν τον αριθμό ως ακέραιο. Ένας μαθητής χρειάζεται βαθμολογία μεγαλύτερη από 40 για να περάσει το διαγώνισμα.

count_failed_students({90,40,55,70,30,25,80,95,38,40});
// => 5

3. Υπολογισμός βαθμών με γράμμα

Στον δάσκαλο που βοηθάς αρέσει να βάζει βαθμούς με γράμμα εκτός από αριθμητικές βαθμολογίες. Επειδή οι μαθητές σπάνια γράφουν 100 σε ένα διαγώνισμα, τα κατώτερα όρια του "βαθμού με γράμμα" υπολογίζονται με βάση την υψηλότερη βαθμολογία που επιτεύχθηκε και αυξάνονται ομοιόμορφα ανάμεσα στην υψηλότερη βαθμολογία και το όριο αποτυχίας του <= 40.

Δημιούργησε τη συνάρτηση letter_grades() που παίρνει ως παράμετρο τη βαθμολογία "υψηλότερη" του διαγωνίσματος και επιστρέφει έναν array (όχι vector) με τα κατώτερα όρια βαθμολογίας για κάθε διάστημα βαθμού "αμερικανικού τύπου": ["D", "C", "B", "A"].

/*Where the highest score is 100, and failing is <= 40.
       "F" <= 40
 41 <= "D" <= 55
 56 <= "C" <= 70
 71 <= "B" <= 85
 86 <= "A" <= 100
*/

letter_grades(100);
// => {41, 56, 71, 86}


/*Where the highest score is 88, and failing is <= 40.
       "F" <= 40
 41 <= "D" <= 52
 53 <= "C" <= 64
 65 <= "B" <= 76
 77 <= "A" <= 88
*/

letter_grades(88);
// => {41, 53, 65, 77}

4. Αντιστοίχιση ονομάτων με βαθμολογίες

Έχεις τις βαθμολογίες του διαγωνίσματος σε φθίνουσα σειρά και τα αντίστοιχα ονόματα των μαθητών (ταξινομημένα με τη σειρά των βαθμολογιών τους). Θέλεις να αντιστοιχίσεις το όνομα κάθε μαθητή με τη βαθμολογία του και να εκτυπώσεις μια συνολική κατάταξη της τάξης.

Δημιούργησε τη συνάρτηση student_ranking() με παραμέτρους student_scores και student_names. Αντιστοίχισε κάθε όνομα μαθητή στο vector student_names με τη βαθμολογία του από το vector student_scores. Μπορείς να υποθέσεις ότι κάθε vector ορίσματος είναι ταξινομημένος από τη μεγαλύτερη βαθμολογία προς τη μικρότερη. Η συνάρτηση πρέπει να επιστρέφει ένα vector από συμβολοσειρές με τη μορφή <rank>. <student name>: <student score>.

std::vector<int> student_scores {100, 99, 90, 84, 66, 53, 47};
std::vector<std::string> student_names {"Joci", "Sara","Kora","Jan","Indra","Bern", "Fred"};
student_ranking(student_scores, student_names)
// =>
//  {"1. Joci: 100", "2. Sara: 99", "3. Kora: 90", "4. Jan: 84", "5. Indra: 66", "6. Bern: 53", "7. Fred: 47"}

5. Μια "τέλεια" βαθμολογία

Αν και μια "τέλεια" βαθμολογία 100 είναι σπάνια σε ένα διαγώνισμα, έχει ενδιαφέρον να ξέρεις αν τουλάχιστον ένας μαθητής την έχει πετύχει.

Δημιούργησε τη συνάρτηση perfect_score() με παραμέτρους student_scores και student_names. Οι λίστες είναι οι ίδιες όπως στην εργασία 4. Η συνάρτηση πρέπει να return το πρώτο <name> (ως συμβολοσειρά) του μαθητή που πήρε 100 στο διαγώνισμα.

Αν δεν βρεθεί καμία βαθμολογία 100, πρέπει να επιστραφεί μια κενή συμβολοσειρά "".

perfect_score({"Nur", "Tony", "Fatima"}, {90, 80, 100});
// => "Fatima"

perfect_score({"Nur", "Tony"}, {90, 80});
// => ""
Επεξεργασία μέσω GitHub Ο σύνδεσμος ανοίγει σε νέο παράθυρο ή καρτέλα
C++ Exercism

Έτοιμος να ξεκινήσεις την άσκηση Βάζοντας βαθμούς;

Γράψου στο Exercism για να μάθεις και να κατακτήσεις C++ με 19 έννοιες100 ασκήσεις και πραγματική καθοδήγηση από ανθρώπους, όλα δωρεάν.