Треки
/
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 рядків тексту (англ. string) у форматі <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 вправ та справжнє наставництво від людей, і все це безкоштовно.