評分

評分

學習練習

簡介

陣列與向量

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(),它接收一個student_scores的vector。 學校要求的捨入方式是無條件捨去。 幸好 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(),它接收一個student_scores的vector。 這個函式應該數出沒有拿到及格分數的學生人數,並以整數回傳這個數量。 學生需要拿到高於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。 把 student_names vector 中的每個學生姓名,與 student_scores vector 中對應的分數配對起來。 你可以假設每個引數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考試拿到 100 分的那位學生的_第一個_<name>(以字串表示)。

如果找不到任何 100 分,應該回傳空字串""。

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

perfect_score({"Nur", "Tony"}, {90, 80});
// => ""
透過 GitHub 編輯 連結會在新視窗或分頁中開啟
C++ Exercism

準備好開始 評分 了嗎?

註冊 Exercism,透過 19 個概念100 個練習 和真人引導來學習並精通 C++,全部免費。