Files, Sorting & Records — The 100-Student Problem

This whole lesson is one problem. Every new thing you learn here shows up because the problem refuses to be solved without it. Cả bài học này chỉ có một bài toán. Mỗi thứ mới bạn học đều xuất hiện vì bài toán không thể giải nếu thiếu nó.

🛠️ Section 0 — Set Up Your Computer

Do this once. Follow the numbered steps in order. Làm một lần. Làm theo các bước đánh số, đúng thứ tự.

0.1 — Install Git Bash

Git Bash is the window where you type commands. Git Bash là cửa sổ để gõ lệnh.

  1. Go to git-scm.com/install/windows and click "Click here to download". Vào git-scm.com/install/windows, bấm "Click here to download".
    The Git download page with Click here to download circled in red
    Click the link in the red box. / Bấm liên kết trong khung đỏ.
  2. Open File ExplorerDownloads → double-click the file. Mở File Explorer → Downloads → bấm đúp vào tệp.
  3. If Windows asks "Do you want to allow this app to make changes?", click Yes. Nếu Windows hỏi, bấm Yes.
  4. Click Next on every screen, then Install, then Finish. Bấm Next ở mọi màn hình, rồi Install, rồi Finish.
  5. To open Git Bash: Start → type Git Bash → click it. Để mở Git Bash: Start → gõ Git Bash → bấm vào.
    An empty Git Bash window waiting for a command
    Git Bash. The $ means it is waiting for you to type. / Dấu $ nghĩa là nó đang chờ bạn gõ. (Image: gitforwindows.org)

0.2 — Install the C++ compiler

The compiler turns your C++ code into a program the computer can run. Trình biên dịch biến code C++ thành chương trình máy tính chạy được.

Part A — Install MSYS2 Phần A — Cài MSYS2

  1. Go to msys2.org and click the link in the red box (it ends with .exe). Vào msys2.org, bấm liên kết trong khung đỏ (kết thúc bằng .exe).
    The MSYS2 website with the installer download link circled in red
    Click the link in the red box. / Bấm liên kết trong khung đỏ.
  2. Open File ExplorerDownloads → double-click the file. Mở File Explorer → Downloads → bấm đúp vào tệp.
  3. If Windows asks "Do you want to allow this app to make changes?", click Yes. Nếu Windows hỏi, bấm Yes.
  4. Click Next on every screen. Do not change the folder C:\msys64. Bấm Next ở mọi màn hình. Không đổi thư mục C:\msys64.
    The MSYS2 installer folder screen with C:\msys64 circled in red
    Leave it as C:\msys64. / Giữ nguyên C:\msys64. (Image: msys2.org)
  5. On the last screen, keep "Run MSYS2 now" ticked and click Finish. Ở màn hình cuối, giữ dấu tích "Run MSYS2 now", bấm Finish.
    The last MSYS2 installer screen with Run MSYS2 now circled in red
    Keep this ticked. / Giữ dấu tích này. (Image: msys2.org)
  6. A black MSYS2 window opens. It is not Git Bash — you use it only now. Một cửa sổ đen MSYS2 hiện ra. Nó KHÔNG phải Git Bash — chỉ dùng lúc này.
    The MSYS2 window that opens after the installer finishes
    The MSYS2 window. / Cửa sổ MSYS2. (Image: msys2.org)
  7. Copy this line. Right-click inside the black window → Paste (Ctrl+V does not work there). Press Enter. Typing it from paper? There are two dashes before needed. Sao chép dòng này. Bấm chuột phải vào cửa sổ đen → Paste (Ctrl+V không dùng được). Nhấn Enter. Gõ từ giấy? Có hai dấu gạch ngang trước needed.
    bash
    pacman -S --needed base-devel mingw-w64-ucrt-x86_64-toolchain
  8. Each time it asks a question, press Enter. Mỗi lần nó hỏi, nhấn Enter.
    The MSYS2 window asking Enter a selection
    A question like this: press Enter. / Câu hỏi như thế này: nhấn Enter. (Image: VS Code documentation)
  9. Wait while text scrolls for a few minutes. When the last line ends with $, close the window. Chờ vài phút khi chữ chạy. Khi dòng cuối kết thúc bằng $, đóng cửa sổ.

Part B — Let Git Bash find the compiler Phần B — Cho Git Bash tìm thấy trình biên dịch

  1. Start → type environment variables → click "Edit environment variables for your account" (not "system"). Start → gõ environment variables → bấm "Edit environment variables for your account" (không phải "system").
  2. In the top list, click PathEdit New. Ở danh sách phía trên, bấm Path → Edit → New.
  3. Type C:\msys64\ucrt64\bin exactly. Click OK on every window. Gõ chính xác C:\msys64\ucrt64\bin. Bấm OK ở mọi cửa sổ.
  4. Open a new Git Bash. Type this and press Enter: Mở Git Bash mới. Gõ dòng này rồi nhấn Enter:
    bash
    g++ --version
  5. The first line should start with g++. If you see command not found, do steps 1–4 again. Dòng đầu phải bắt đầu bằng g++. Nếu thấy command not found, làm lại bước 1–4.

0.3 — Install VS Code

VS Code is where you write your code. VS Code là nơi bạn viết code.

  1. Go to code.visualstudio.com/download and click the Windows button. Vào code.visualstudio.com/download, bấm nút Windows.
    The VS Code download page with the Windows button circled in red
    Click the button in the red box. / Bấm nút trong khung đỏ.
  2. Open File ExplorerDownloads → double-click the file. Mở File Explorer → Downloads → bấm đúp vào tệp.
  3. Click "I accept the agreement", then Next. Bấm "I accept the agreement", rồi Next.
  4. On "Select Additional Tasks", tick both "Add 'Open with Code'" boxes. Ở màn hình "Select Additional Tasks", tích cả hai ô "Add 'Open with Code'".
    The VS Code installer with the two Open with Code boxes circled in red
    Tick both boxes in the red frame — they start empty. / Tích cả hai ô trong khung đỏ — lúc đầu còn trống. (Image: MIT RACECAR course, MIT License)
  5. Click Next, Install, Finish. Bấm Next, Install, Finish.

0.4 — Make a folder and open it in VS Code

  1. Open File ExplorerThis PC → double-click the (D:) disk. (No (D:) disk? Tell your teacher.) Mở File Explorer → This PC → bấm đúp vào ổ (D:). (Không có ổ D:? Báo giáo viên.)
  2. Right-click an empty space → NewFolder. Name it with your name — no spaces, no accents. Example: nguyenvanan. Bấm chuột phải vào chỗ trống → New → Folder. Đặt tên bằng tên của bạn — không dấu cách, không dấu tiếng Việt. Ví dụ: nguyenvanan.
  3. Right-click your folderOpen with Code. (No option? Click "Show more options" first.) Bấm chuột phải vào thư mục của bạn → Open with Code. (Không thấy? Bấm "Show more options" trước.)
  4. VS Code asks if you trust the folder. Click "Yes, I trust the authors". VS Code hỏi bạn có tin thư mục không. Bấm "Yes, I trust the authors".
    The VS Code question Do you trust the authors of the files in this folder
    Click the blue button. / Bấm nút màu xanh. (Image: VS Code documentation)
  5. In the left panel of VS Code, right-click an empty space → New Folder.... Type helloworld and press Enter. All your files for this lesson go in this folder. Ở khung bên trái VS Code, bấm chuột phải vào chỗ trống → New Folder... Gõ helloworld rồi nhấn Enter. Mọi tệp của bài này đều để trong thư mục này.

0.5 — Create your first file

  1. In the left panel of VS Code, click the helloworld folder. Ở khung bên trái VS Code, bấm vào thư mục helloworld.
  2. Click the New File button (a page with +). Bấm nút New File (tờ giấy có dấu +).
    The VS Code Explorer with the New File button highlighted
    The New File button, in the green box. Yours shows your name on top. / Nút New File, trong khung xanh lá. Của bạn ghi tên bạn ở trên cùng. (Image: VS Code documentation)
  3. Type hello.cpp and press Enter. It appears under helloworld. Gõ hello.cpp rồi nhấn Enter. Tệp hiện ra bên dưới helloworld.
  4. Type this into the file: Gõ nội dung này vào tệp:
    cpp
    #include <iostream> using namespace std; int main() { cout << "Hello" << endl; return 0; }
  5. Press Ctrl+S to save. Nhấn Ctrl+S để lưu.

0.6 — Open Git Bash in your folder

  1. Close any Git Bash window that is already open. Đóng mọi cửa sổ Git Bash đang mở.
  2. In File Explorer, open (D:) your folderhelloworld. Trong File Explorer, mở (D:) → thư mục của bạn → helloworld.
  3. Right-click an empty space → Open Git Bash here. (No option? Click "Show more options" first.) Bấm chuột phải vào chỗ trống → Open Git Bash here. (Không thấy? Bấm "Show more options" trước.)
  4. Type ls and press Enter. Gõ ls rồi nhấn Enter.
    bash
    ls
  5. You should see hello.cpp. Bạn sẽ thấy hello.cpp.

0.7 — Compile and run your first file

C++ needs two commands: the first turns hello.cpp into a program (this is called compiling), the second runs it. C++ cần hai lệnh: lệnh đầu biến hello.cpp thành chương trình (gọi là biên dịch), lệnh sau chạy nó.

  1. Type these two lines, pressing Enter after each: Gõ hai dòng này, nhấn Enter sau mỗi dòng:
    bash
    g++ -o hello hello.cpp ./hello
  2. You should see Hello. Your computer is ready. Bạn sẽ thấy Hello. Máy tính đã sẵn sàng.

🎯 Section 1 — The Problem

A class has 100 students. Each one has a score. Your job: print the scores from lowest to highest. Một lớp có 100 học sinh, mỗi bạn có một điểm. Nhiệm vụ: in điểm từ thấp đến cao.

The scores look like this — one number per line, 100 lines in total: Điểm có dạng như sau — mỗi dòng một số, tổng cộng 100 dòng:

87
92
78
95
85
...

You found it: typing 100 numbers every single time you test is impossible. Before we can sort anything, we need the data to come from somewhere else. Bạn đã thấy: gõ 100 số mỗi lần chạy thử là không thể. Trước khi sắp xếp, dữ liệu phải đến từ nơi khác.

📂 Section 2 — Read the Scores From a File

The 100 numbers are already in a text file called scores.txt. Your program can read them from the file, so you never type them again. 100 số đã có sẵn trong tệp văn bản scores.txt. Chương trình của bạn đọc chúng từ tệp, nên bạn không phải gõ lại nữa.

cpp
#include <iostream> #include <fstream> #include <vector> using namespace std; int main() { ifstream fin("scores.txt"); vector<int> scores; int s; while (fin >> s) { scores.push_back(s); } for (int x : scores) { cout << x << endl; } return 0; }

🔢 Section 3 — Sort Them

The scores are in a vector. C++ can put a vector in order with one line. First add #include <algorithm> at the top of your file, next to the other #include lines. Then: Điểm đang nằm trong vector. C++ sắp xếp vector bằng một dòng. Trước tiên, thêm #include <algorithm> ở đầu tệp, cạnh các dòng #include khác. Rồi:

cpp
sort(scores.begin(), scores.end());

What are begin() and end()?

Notice that sort does not take the vector. It takes two markers: one for where to start sorting, and one for where to stop. Để ý: sort không nhận vector. Nó nhận hai cái mốc: một mốc chỗ bắt đầu, một mốc chỗ dừng.

This way an empty vector works too: its start marker and its stop marker are the same, so there is nothing to sort. Nhờ vậy vector rỗng cũng chạy đúng: mốc bắt đầu và mốc dừng trùng nhau, nên không có gì để sắp xếp.

The whole program: Toàn bộ chương trình:

cpp
#include <iostream> #include <fstream> #include <vector> #include <algorithm> using namespace std; int main() { ifstream fin("scores.txt"); vector<int> scores; int s; while (fin >> s) { scores.push_back(s); } sort(scores.begin(), scores.end()); for (int x : scores) { cout << x << endl; } return 0; }

💾 Section 4 — Write the Answer to a File

Printing 100 lines to the screen scrolls away. Write the answer into out.txt instead, so you can open it and check it. When you run this program, it shows nothing on the screen — that is normal. It creates out.txt in your helloworld folder; open it in VS Code to see the answer. In 100 dòng ra màn hình sẽ bị trôi mất. Hãy ghi kết quả vào tệp out.txt để mở ra kiểm tra. Khi chạy, chương trình không hiện gì trên màn hình — như vậy là bình thường. Nó tạo tệp out.txt trong thư mục helloworld; mở tệp đó trong VS Code để xem kết quả.

cpp
#include <iostream> #include <fstream> #include <vector> #include <algorithm> using namespace std; int main() { ifstream fin("scores.txt"); ofstream fout("out.txt"); vector<int> scores; int s; while (fin >> s) { scores.push_back(s); } sort(scores.begin(), scores.end()); for (int x : scores) { fout << x << endl; } return 0; }

ofstream is the writing twin of ifstream — the o is for output. And fout << x works exactly like cout << x, just into the file. ofstream là anh em ghi của ifstream, chữ o là output. Và fout dùng y hệt cout, chỉ khác là ghi vào tệp.

🔄 Section 5 — New Requirement: Best Student at the Top

The teacher changes her mind. She wants the scores from highest to lowest now. Cô giáo đổi ý. Bây giờ cô muốn điểm từ cao xuống thấp.

With only the two markers, sort always puts the smallest first. To get a different order, you put a third thing inside sort's brackets: a function that answers one question — should a come before b? Chỉ với hai mốc, sort luôn xếp nhỏ trước. Muốn thứ tự khác, bạn đặt thêm một thứ thứ ba vào trong ngoặc của sort: một hàm trả lời câu hỏi — a có nên đứng trước b không?

cpp
#include <iostream> #include <fstream> #include <vector> #include <algorithm> using namespace std; bool highestFirst(int a, int b) { return a > b; } int main() { ifstream fin("scores.txt"); ofstream fout("out.txt"); vector<int> scores; int s; while (fin >> s) { scores.push_back(s); } sort(scores.begin(), scores.end(), highestFirst); for (int x : scores) { fout << x << endl; } return 0; }

Compared with Section 4, two things are new: the bool highestFirst function above int main() (not inside it), and the sort line now has highestFirst as a third thing. Write highestFirst with no brackets: you are handing the function to sort, and sort calls it for you. So với Phần 4, có hai chỗ mới: hàm bool highestFirst nằm phía trên int main() (không nằm bên trong), và dòng sort giờ có thêm highestFirst. Viết highestFirst không có dấu ngoặc: bạn đưa hàm cho sort, và sort sẽ tự gọi nó.

Read it like this: sort keeps asking your function about pairs of scores. Your function says "a comes first when a is bigger", so the biggest score ends up at the top. Hiểu thế này: sort liên tục hỏi hàm của bạn về từng cặp điểm. Hàm nói "a đứng trước khi a lớn hơn", nên điểm lớn nhất lên đầu.

🙋 Section 6 — New Requirement: Whose Score Is It?

A list of numbers is not very useful. The teacher wants to know which student got each score. So the data file changes — every line now has a name and a score, for example: Danh sách toàn số thì chưa dùng được. Cô giáo muốn biết điểm đó là của ai. Vì vậy tệp dữ liệu thay đổi — mỗi dòng có tên và điểm, ví dụ:

An 87
Binh 92
Chi 78
Dung 95
Em 85

Reading a line now gives you two things instead of one. You can chain >> to grab them both: Đọc một dòng bây giờ cho bạn hai thứ. Bạn nối >> để lấy cả hai:

cpp
#include <iostream> #include <fstream> #include <string> using namespace std; int main() { ifstream fin("students.txt"); string name; int score; while (fin >> name >> score) { cout << name << " " << score << endl; } return 0; }

🧩 Section 7 — Keep the Name and the Score Together

The last requirement: write the students from the lowest score to the highest, each name still next to its score. Yêu cầu cuối: ghi học sinh từ điểm thấp nhất đến cao nhất, tên vẫn nằm cạnh điểm.

Here is a way that works. It uses what you already know — reading, sorting, writing — with one change. Đây là một cách làm đúng. Nó dùng những gì bạn đã biết — đọc tệp, sắp xếp, ghi tệp — chỉ khác một chỗ.

Instead of putting an int in the vector, put a pair of things in the vector. C++ calls it a pair, and you say what the two parts are: Thay vì bỏ một int vào vector, hãy bỏ vào một cặp. C++ gọi nó là pair, và bạn khai báo hai phần đó là gì:

cpp
vector<pair<int, string>> data; data.push_back({score, name});

The whole program: Toàn bộ chương trình:

cpp
#include <iostream> #include <fstream> #include <vector> #include <string> #include <algorithm> using namespace std; int main() { ifstream fin("students.txt"); ofstream fout("out.txt"); vector<pair<int, string>> data; string name; int score; while (fin >> name >> score) { data.push_back({score, name}); } sort(data.begin(), data.end()); for (auto& p : data) { fout << p.second << " " << p.first << endl; } return 0; }

When C++ sorts pairs, it compares the first part first. The score is the first part, so the vector comes out in score order — and the name is carried along, because the name and the score are one single value. Khi sắp xếp pair, C++ so sánh phần đầu tiên trước. Điểm là phần đầu, nên vector được sắp theo điểm — và tên đi theo cùng, vì tên và điểm là một giá trị duy nhất.

🔍 Section 8 — What Actually Changed

Put the section 4 program and the section 7 program next to each other: Đặt chương trình phần 4 và phần 7 cạnh nhau:

The requirement that looked like it broke everything left the sorting completely alone. That happens when each part of a program does one job: a change usually hits some parts and misses others. Yêu cầu tưởng như phá vỡ mọi thứ lại không đụng gì đến phần sắp xếp. Điều đó xảy ra khi mỗi phần của chương trình chỉ làm một việc: một thay đổi thường chỉ ảnh hưởng vài phần.

✏️ Section 9 — Exercises

Every exercise has its own input file. Click the file name next to the question, drag the file from Downloads into your helloworld folder, and use that file name in your program — for exercise 1, ex1.txt. Exercises 1–4 have one score per line; exercises 5–8 have a name and a score. Mỗi bài tập có tệp dữ liệu riêng. Bấm vào tên tệp cạnh câu hỏi, kéo tệp từ Downloads vào thư mục helloworld, và dùng đúng tên tệp đó trong chương trình — với câu 1 là ex1.txt. Câu 1–4 mỗi dòng một điểm; câu 5–8 mỗi dòng một tên và một điểm.