Bài 1.5: Bài tập thực hành làm quen với C++

Chào mừng quay trở lại với chuỗi bài viết về C++!

Sau khi đã làm quen với cấu trúc cơ bản của một chương trình C++ và cách thực hiện nhập/xuất dữ liệu đơn giản ở các bài trước, hôm nay là lúc chúng ta xắn tay áo lênthực hành! Bài viết này không giới thiệu quá nhiều khái niệm mới toanh, mà tập trung vào việc áp dụng những gì đã học và làm quen thêm một vài "công cụ" cơ bản khác thông qua các ví dụ code cụ thể.

Hãy coi đây là một "sân chơi" để bạn tự tay gõ code, chạy thử, và cảm nhận cách ngôn ngữ C++ hoạt động ở mức độ đơn giản nhất. Thực hành là cách tốt nhất để học!

Chương trình C++ Đầu Tiên (Lại Một Lần Nữa!)

Không có cách nào tốt hơn để bắt đầu ngoài việc lặp lại cấu trúc cơ bản.

#include <iostream> // Bao gom thu vien input/output

int main() { // Ham chinh cua chuong trinh
    cout << "Chao mung toi the gioi C++!" << endl; // In ra man hinh
    return 0; // Ket thuc chuong trinh thanh cong
}
  • #include <iostream>: Dòng này là chỉ thị tiền xử lý. Nó bảo trình biên dịch "nhập" nội dung của thư viện iostream vào chương trình của chúng ta. Thư viện này cung cấp các công cụ để làm việc với dòng nhập (input stream) và dòng xuất (output stream), ví dụ như cout.
  • int main() { ... }: Đây là hàm chính (main function). Mọi chương trình C++ hợp lệ đều phải có một hàm main, và việc thực thi chương trình sẽ bắt đầu từ đây. int là kiểu dữ liệu trả về của hàm main, theo quy ước, trả về 0 thường có nghĩa là chương trình kết thúc mà không gặp lỗi.
  • cout << "..." << endl;: Dòng này sử dụng đối tượng cout (standard output stream) để gửi dữ liệu ("Chao mung toi the gioi C++!") ra thiết bị xuất chuẩn (thường là màn hình). Toán tử << được gọi là toán tử chèn (insertion operator). endl là một "manipulator" chèn ký tự xuống dòng và "đẩy" (flush) bộ đệm, đảm bảo nội dung hiển thị ngay lập tức.
  • return 0;: Câu lệnh này kết thúc hàm main và trả về giá trị 0.

Bài tập nhỏ: Hãy thử thay đổi chuỗi "Chao mung toi the gioi C++!" thành một câu khác mà bạn thích và chạy chương trình xem sao nhé!

Làm Việc Với Biến và Các Kiểu Dữ Liệu Cơ Bản

Trong lập trình, chúng ta cần nơi để lưu trữ dữ liệu. Đó chính là mục đích của biến (variables). Mỗi biến có một kiểu dữ liệu (data type) nhất định, quy định loại giá trị nó có thể chứa (số nguyên, số thực, ký tự, v.v.) và kích thước bộ nhớ cần thiết.

Hãy xem cách khai báo, gán giá trị và sử dụng biến:

#include <iostream>
#include <string> // Can them thu vien nay cho string

int main() {
    // Khai bao (tao) cac bien voi cac kieu du lieu khac nhau
    int soLuongQuaTao;        // So nguyen
    double giaMoiKilogram;    // So thuc (co phan thap phan)
    char kyTuDauTienTenBan;   // Ky tu don
    bool dangHocLapTrinh;     // Gia tri logic (true/false)
    string tenMonHoc;    // Chuoi ky tu (can #include <string>)

    // Gan gia tri cho cac bien
    soLuongQuaTao = 50;
    giaMoiKilogram = 1.5;
    kyTuDauTienTenBan = 'H'; // Ky tu dung dau nhay don ''
    dangHocLapTrinh = true;  // Gia tri true hoac false
    tenMonHoc = "C++ Programming"; // Chuoi dung dau nhay kep ""

    // In gia tri cua cac bien ra man hinh
    cout << "So luong tao: " << soLuongQuaTao << endl;
    cout << "Gia moi kg: $" << giaMoiKilogram << endl;
    cout << "Ky tu dau ten ban: " << kyTuDauTienTenBan << endl;
    cout << "Dang hoc lap trinh: " << dangHocLapTrinh << endl; // true in ra 1, false in ra 0
    cout << "Mon hoc: " << tenMonHoc << endl;

    return 0;
}
  • Khai báo biến: Cú pháp cơ bản là KieuDuLieu TenBien;. Ví dụ: int soLuongQuaTao;. Dòng này yêu cầu hệ thống cấp phát một vùng nhớ để lưu một số nguyên và đặt tên cho vùng nhớ đó là soLuongQuaTao.
  • Gán giá trị: Sử dụng toán tử gán =. Ví dụ: soLuongQuaTao = 50;. Dòng này đưa giá trị 50 vào vùng nhớ được đặt tên là soLuongQuaTao.
  • Bạn có thể khai báo và gán giá trị ngay lập tức (khởi tạo - initialization): int soLuongQuaLe = 20;. Đây là cách làm thường được khuyến khích để tránh biến có giá trị "rác" (không xác định) ban đầu.
  • Kiểu char dùng để lưu một ký tự đơn, được đặt trong dấu nháy đơn ('A', 'b', '5', '$').
  • Kiểu bool chỉ có hai giá trị: true (đúng) hoặc false (sai). Khi in ra màn hình với cout, true thường hiển thị là 1, false0.
  • Kiểu string dùng để lưu trữ chuỗi ký tự (nhiều ký tự nối lại), được đặt trong dấu nháy kép ("Hello", "FullhouseDev"). Để sử dụng string, bạn cần #include <string>.

Bài tập nhỏ: Hãy thêm các biến với kiểu dữ liệu khác (ví dụ: float, long long) và thử lưu trữ các giá trị khác nhau vào chúng.

Thực Hiện Các Phép Tính Toán Học Đơn Giản

C++ cung cấp các toán tử cơ bản để thực hiện các phép tính:

#include <iostream>

int main() {
    int a = 10;
    int b = 3;

    int tong = a + b;       // Phep cong
    int hieu = a - b;       // Phep tru
    int tich = a * b;       // Phep nhan
    int thuongNguyen = a / b; // Phep chia lay phan nguyen (khi ca hai la so nguyen)
    int soDu = a % b;       // Phep chia lay so du (modulo) - chi dung voi so nguyen

    double x = 10.0; // Su dung so thuc de co ket qua chia thuc
    double y = 3.0;
    double thuongThuc = x / y; // Phep chia lay phan thuc

    cout << "a = " << a << ", b = " << b << endl;
    cout << "Tong: " << tong << endl; // 13
    cout << "Hieu: " << hieu << endl; // 7
    cout << "Tich: " << tich << endl; // 30
    cout << "Thuong (nguyen): " << thuongNguyen << endl; // 3
    cout << "So du: " << soDu << endl; // 1

    cout << "x = " << x << ", y = " << y << endl;
    cout << "Thuong (thuc): " << thuongThuc << endl; // 3.333...

    // Ket hop phep toan va in truc tiep
    cout << "Tong cua a va b la: " << a + b << endl;

    return 0;
}
  • Các toán tử +, -, *, / hoạt động như trong toán học thông thường.
  • Toán tử % (modulo) trả về số dư của phép chia. Nó chỉ hoạt động với các số nguyên.
  • Lưu ý quan trọng về phép chia /:
    • Nếu cả hai toán hạng (số bị chia và số chia) đều là kiểu số nguyên (int), kết quả sẽ là phần nguyên của phép chia (phần thập phân bị cắt bỏ).
    • Nếu ít nhất một trong hai toán hạng là kiểu số thực (double, float), kết quả sẽ là phép chia số thực. Bạn có thể "ép kiểu" (type casting) tạm thời một số nguyên thành số thực để thực hiện phép chia thực, ví dụ: double thuong = (double)a / b;.
  • Bạn có thể thực hiện các phép toán ngay trong câu lệnh cout.

Bài tập nhỏ: Hãy viết chương trình nhỏ nhập vào bán kính hình tròn từ người dùng (double banKinh; cin >> banKinh;) và tính diện tích, chu vi của hình tròn đó (S = pi R^2, C = 2 pi * R). Sử dụng const double PI = 3.14159; để khai báo hằng số PI.

Nhập Xuất (I/O) "Nâng Cấp" Một Chút

Chúng ta đã dùng cin để nhập một giá trị. Bạn hoàn toàn có thể nhập nhiều giá trị cùng lúc và kết hợp nhập/xuất một cách linh hoạt hơn.

#include <iostream>
#include <string>

int main() {
    int so1, so2; // Khai bao nhieu bien cung kieu tren mot dong

    cout << "Nhap hai so nguyen (cach nhau bang khoang trang): ";
    cin >> so1 >> so2; // Doc hai so lien tiep tu mot dong

    cout << "Ban da nhap: " << so1 << " va " << so2 << endl;
    cout << "Tong cua hai so la: " << so1 + so2 << endl;

    string tenDayDu;
    // cout << "Nhap ten day du cua ban: ";
    // cin >> tenDayDu; // Chi doc duoc tu dau den khoang trang dau tien!
    // cout << "Ten da nhap: " << tenDayDu << endl; // Se bi sai neu ten co khoang trang

    // De doc ca dong (bao gom khoang trang), dung getline
    cin.ignore(); // Loai bo ky tu xuong dong con lai tu lenh nhap truoc
    cout << "Nhap ten day du cua ban: ";
    getline(cin, tenDayDu); // Doc ca dong cho den khi gap Enter

    cout << "Xin chao, " << tenDayDu << "!" << endl;

    return 0;
}
  • Bạn có thể dùng toán tử >> nối tiếp nhau (cin >> var1 >> var2;) để đọc nhiều giá trị từ dòng nhập. cin sẽ tự động bỏ qua các ký tự trắng (khoảng trắng, tab, xuống dòng) giữa các giá trị.
  • cin với toán tử >> dừng đọc khi gặp ký tự trắng. Điều này có nghĩa là nó không phù hợp để đọc chuỗi có chứa khoảng trắng (ví dụ: tên đầy đủ).
  • Để đọc toàn bộ một dòng nhập từ người dùng (bao gồm cả khoảng trắng), bạn nên dùng hàm getline(cin, bien_string);.
  • Lưu ý dòng cin.ignore();. Khi bạn dùng cin >> để đọc số (hoặc bất kỳ kiểu dữ liệu nào khác không phải chuỗi), ký tự xuống dòng (\n) mà bạn gõ khi nhấn Enter vẫn còn lại trong bộ đệm nhập. Nếu ngay sau đó bạn dùng getline, getline sẽ đọc ngay ký tự xuống dòng đó và nghĩ rằng đã kết thúc dòng, dẫn đến việc bỏ qua dòng nhập thực tế của bạn. cin.ignore(); được dùng để loại bỏ (bỏ qua) ký tự xuống dòng còn sót lại đó, chuẩn bị bộ đệm cho getline.

Bài tập nhỏ: Hãy viết chương trình nhập vào 3 số nguyên và in ra tổng, trung bình cộng, tích của chúng.

Rẽ Nhánh Chương Trình với if

Các chương trình thường cần đưa ra quyết định dựa trên các điều kiện khác nhau. Câu lệnh if là cách cơ bản nhất để làm điều này.

#include <iostream>

int main() {
    int diemSo;

    cout << "Nhap diem so cua ban (0-100): ";
    cin >> diemSo;

    // Kiem tra dieu kien
    if (diemSo >= 50) {
        cout << "Chuc mung! Ban da dau." << endl;
    }

    // Co the ket hop voi else de xu ly truong hop dieu kien sai
    if (diemSo < 50) {
        cout << "Ban chua dat. Hay co gang hon nhe!" << endl;
    } else { // Neu dieu kien tren (diemSo < 50) la SAI, thi thuc hien khoi code nay
        cout << "Va ban co the tiep tuc hoc cac bai nang cao hon." << endl;
    }

    // Ket hop voi else if cho nhieu truong hop
    if (diemSo >= 90) {
        cout << "Ban dat loai Xuat sac!" << endl;
    } else if (diemSo >= 75) { // Chi kiem tra dieu kien nay neu dieu kien tren SAI
        cout << "Ban dat loai Gioi." << endl;
    } else if (diemSo >= 50) { // Chi kiem tra dieu kien nay neu cac dieu kien tren SAI
        cout << "Ban dat loai Kha." << endl;
    } else { // Neu tat ca cac dieu kien tren deu SAI
        cout << "Ban dat loai Trung binh hoac Yeu." << endl;
    }


    cout << "Ket thuc chuong trinh danh gia diem." << endl;

    return 0;
}
  • Cú pháp cơ bản: if (dieu_kien) { // code thuc thi neu dieu_kien la true }.
  • dieu_kien là một biểu thức logic, kết quả của nó phải là true hoặc false. Các toán tử so sánh thường dùng: > (lớn hơn), < (nhỏ hơn), >= (lớn hơn hoặc bằng), <= (nhỏ hơn hoặc bằng), == (bằng), != (khác).
  • Khối code bên trong cặp dấu ngoặc nhọn {} là phần sẽ được thực thi chỉ khi dieu_kien là đúng. Nếu chỉ có một dòng lệnh sau if, bạn có thể bỏ qua cặp {} nhưng luôn khuyến khích sử dụng chúng để code rõ ràng hơn và tránh lỗi.
  • Bạn có thể thêm else { ... } sau khối if. Phần code trong else sẽ được thực thi chỉ khi điều kiện trong if là sai.
  • Bạn có thể dùng else if (dieu_kien_moi) { ... } để kiểm tra nhiều điều kiện theo thứ tự. Các điều kiện này chỉ được kiểm tra nếu các điều kiện if hoặc else if đứng trước nó đều sai. Chương trình sẽ thực thi khối code của điều kiện đúng đầu tiên mà nó gặp và bỏ qua các phần else ifelse còn lại.

Bài tập nhỏ: Nhập vào một số nguyên. Dùng if kiểm tra xem số đó là số chẵn hay số lẻ (gợi ý: dùng toán tử %).

Lặp Lại Công Việc với Vòng Lặp for

Khi bạn cần thực hiện một công việc lặp đi lặp lại một số lần nhất định, vòng lặp là cứu cánh. Vòng lặp for là một trong những vòng lặp phổ biến nhất, thường dùng khi bạn biết trước số lần lặp hoặc muốn lặp qua một dãy giá trị.

#include <iostream>

int main() {
    // Lap 5 lan de in ra mot loi chao
    for (int i = 0; i < 5; ++i) {
        // Khoi code nay se lap lai
        cout << "Hello lap trinh vien! Day la lan lap thu " << i + 1 << endl;
    }

    cout << "Vong lap for da ket thuc." << endl;

    // Vi du khac: Lap tu 10 den 1
    for (int j = 10; j > 0; --j) {
        cout << "Dem nguoc: " << j << endl;
    }

    // Vi du: Lap voi buoc nhay khac 1
    for (int k = 0; k <= 20; k = k + 2) { // k += 2; cung tuong tu
         cout << "So chan: " << k << endl;
    }

    return 0;
}
  • Cấu trúc của vòng lặp for là: for (khoi_tao; dieu_kien; cap_nhat) { // code can lap }.
    • khoi_tao: Phần này được thực thi một lần duy nhất khi vòng lặp bắt đầu. Thường dùng để khai báo và gán giá trị ban đầu cho biến đếm (counter variable).
    • dieu_kien: Phần này được kiểm tra trước mỗi lần lặp. Nếu dieu_kientrue, thân vòng lặp ({...}) sẽ được thực thi. Nếu là false, vòng lặp kết thúc.
    • cap_nhat: Phần này được thực thi sau mỗi lần thân vòng lặp được thực thi. Thường dùng để thay đổi giá trị của biến đếm (tăng hoặc giảm).
  • Trong ví dụ đầu tiên: int i = 0; (khởi tạo i bằng 0), i < 5; (lặp khi i nhỏ hơn 5), ++i; (tăng i lên 1 sau mỗi vòng). Vòng lặp sẽ chạy với i có giá trị 0, 1, 2, 3, 4 (tổng cộng 5 lần).
  • ++ii++ đều là toán tử tăng (increment) i lên 1. Trong phần cap_nhat của vòng lặp for, chúng thường có tác dụng tương tự. --j là toán tử giảm (decrement).

Bài tập nhỏ: Viết chương trình sử dụng vòng lặp for để tính tổng các số nguyên từ 1 đến 100.

Thêm Ghi Chú Cho Code "Dễ Hiểu Hơn"

Khi viết code, đặc biệt là những đoạn phức tạp, việc thêm comment (ghi chú) là cực kỳ quan trọng. Comment là những dòng văn bản mà trình biên dịch sẽ hoàn toàn bỏ qua, nhưng chúng giúp bạn (và những người khác đọc code của bạn) hiểu rõ hơn mục đích, cách hoạt động của từng phần code.

C++ hỗ trợ hai loại comment:

#include <iostream>

int main() {
    // Day la mot comment tren mot dong.
    // Moi thu sau // tren cung mot dong se bi bo qua boi trinh bien dich.

    /*
    Day la mot comment tren nhieu dong.
    No bat dau bang /*
    va ket thuc bang */.
    Ban co the viet nhieu dong tuy thich o giua.
    */

    int diemTrungBinh = 85; // Co the dat comment o cuoi dong code de giai thich bien

    cout << "Diem trung binh: " << diemTrungBinh << endl; // In ra diem trung binh

    return 0;
}
  • Comment một dòng: Bắt đầu bằng //. Mọi ký tự từ // đến cuối dòng đều là comment.
  • Comment nhiều dòng: Bắt đầu bằng /* và kết thúc bằng */. Mọi thứ nằm giữa hai ký hiệu này (trên một hoặc nhiều dòng) đều là comment.
  • Sử dụng comment một cách thông minh. Đừng chỉ diễn tả lại code (ví dụ: // Tang i len 1 sau ++i;). Hãy giải thích tại sao bạn làm điều đó, mục đích của một khối code phức tạp, hoặc các giả định quan trọng.

Bài tập nhỏ: Quay lại một trong các ví dụ code ở trên và thêm comment vào để giải thích các phần khác nhau của code.

Tóm Lại (Không Phải Kết Luận Nhé!)

Qua bài thực hành này, bạn đã làm quen (hoặc củng cố kiến thức) về:

  • Cấu trúc cơ bản của chương trình C++.
  • Cách sử dụng biến và các kiểu dữ liệu thông dụng (int, double, char, bool, string).
  • Thực hiện các phép tính cơ bản.
  • Sử dụng cincout để nhập/xuất dữ liệu, bao gồm cả đọc chuỗi có khoảng trắng với getline.
  • Đưa ra quyết định trong chương trình với câu lệnh if (và else, else if).
  • Lặp lại công việc với vòng lặp for.
  • Cách thêm ghi chú (comment) vào code.

Bài tập ví dụ: C++ Bài 1.A5: Hàm sqrt và cbrt.

Cho số nguyên dương \(a\), nhiệm vụ của bạn là tính căn bậc \(2\) và căn bậc \(3\) của \(a\).

Input Format

Nhập vào số nguyên dương \(a\). \((-10^9 ≤ a ≤ 10^9).\)

Output Format

In ra căn bậc \(2\) của \(a\) với \(3\) số sau dấu phẩy và căn bậc \(3\) của \(a\) với \(3\) số sau dấu phẩy mỗi đáp án cách nhau \(1\) dấu cách.

Ví dụ:

Dữ liệu vào:
28
Dữ liệu ra:
5.292 3.037
Giải thích ví dụ mẫu:
  • Căn bậc 2 của 28 là 5.292 và căn bậc 3 là 3.037.
  1. Mục tiêu: Đọc một số nguyên a, tính căn bậc 2 và căn bậc 3 của a, sau đó in kết quả với độ chính xác 3 chữ số thập phân.

  2. Các thư viện cần dùng:

    • Cần thư viện để nhập xuất dữ liệu: iostream.
    • Cần thư viện chứa các hàm toán học như căn bậc 2 (sqrt) và căn bậc 3 (cbrt): cmath.
    • Cần thư viện để định dạng đầu ra (số chữ số sau dấu phẩy): iomanip.
  3. Đọc dữ liệu:

    • Khai báo một biến kiểu số nguyên (int) để lưu giá trị của a.
    • Sử dụng đối tượng cin để đọc giá trị của a từ đầu vào chuẩn.
  4. Tính toán:

    • Hàm sqrt()cbrt() trong thư viện cmath nhận đối số kiểu dấu phẩy động (như double) và trả về kết quả kiểu dấu phẩy động.
    • Bạn cần truyền biến a vào hai hàm này. Biến a kiểu int sẽ được tự động chuyển đổi sang kiểu dấu phẩy động khi truyền vào các hàm này, hoặc bạn có thể ép kiểu tường minh sang double nếu muốn (ví dụ: sqrt((double)a)).
    • Lưu kết quả tính toán vào hai biến kiểu dấu phẩy động (ví dụ: double).
  5. Định dạng và in kết quả:

    • Sử dụng đối tượng cout để in kết quả.
    • Để định dạng số chữ số sau dấu phẩy khi in ra bằng cout, bạn cần sử dụng các "manipulator" từ thư viện iomanip.
    • Sử dụng fixed để đảm bảo in số theo dạng thập phân cố định, không phải dạng khoa học (ví dụ: 1.234e+05).
    • Sử dụng setprecision(3) để chỉ định số chữ số sau dấu phẩy là 3 khi dùng kèm với fixed.
    • In kết quả của căn bậc 2, sau đó in một dấu cách (" "), rồi in kết quả của căn bậc 3.
    • Kết thúc dòng bằng endl hoặc '\n'.
  6. Cấu trúc chương trình:

    • Bắt đầu với hàm main().
    • Bao gồm các câu lệnh #include cho các thư viện cần thiết.
    • Viết các bước đọc dữ liệu, tính toán và in kết quả bên trong hàm main().
    • Kết thúc hàm main() bằng return 0;.

Lưu ý về giới hạn đầu vào: Mặc dù đề bài ghi "số nguyên dương a" nhưng lại cho giới hạn "-10^9 ≤ a ≤ 10^9", bao gồm cả số âm.

  • Hàm sqrt() của số âm sẽ trả về một giá trị biểu diễn "Not a Number" (NaN).
  • Hàm cbrt() xử lý số âm bình thường và trả về kết quả âm (ví dụ: cbrt(-8)-2).
  • Cách cout in giá trị NaN với định dạng cố định có thể khác nhau tùy hệ thống, nhưng thông thường sẽ in ra chuỗi như "nan". Dạng output "___.___" cho phép hiển thị cả "nan".

Làm thêm nhiều bài tập miễn phí tại đây

Comments

There are no comments at the moment.