المسارات
/
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

ملاحظة: لا تحتاج إلى معرفة الآلية الدقيقة وراء مفهوم القوالب بعد، فسيكون له مفهومه الخاص في موضع أبعد في شجرة المنهج.

الوصول إلى العناصر

تشترك المتجهات والمصفوفات في الدوال نفسها للوصول إلى عناصرها. يمكنك استخدام الدالتين العضويتين 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 تمرين، وإرشاد بشري حقيقي، وكل ذلك مجانًا.