C++ Fundamentals

📦 Biến – Kiểu dữ liệu – Nhập xuất trong C++

Bài học giúp học sinh hiểu chương trình nhận dữ liệu, lưu dữ liệu trong biến, xử lý theo đúng kiểu và xuất kết quả. Có mô phỏng phép gán, kiểu dữ liệu, chia nguyên, chuyển kiểu, overflow và cin/getline.

VariableÔ nhớ có tên
Data typeQuy định miền giá trị
cin / coutNhập và xuất chuẩn
OverflowChọn kiểu đủ lớn

🎯 Mục tiêu bài học

Cần hiểu

  • Cấu trúc tối thiểu của chương trình C++.
  • Biến, khai báo, khởi tạo và phép gán.
  • Chọn kiểu dữ liệu phù hợp.
  • Chia nguyên và chia thực.
  • cin, cout, getline.

Cần làm được

  • Đọc nhiều giá trị từ input.
  • Tính toán và in đúng định dạng.
  • Tránh overflow trong biểu thức.
  • Ép kiểu khi cần.
  • Đọc họ tên có khoảng trắng.

1. Đặt vấn đề

Bài toán mở đầu.
Một cửa hàng bán n sản phẩm, mỗi sản phẩm có giá p đồng. Nhập n và p, tính tổng tiền phải trả.
Input
đọc n, p
Process
total = n × p
Output
in total

1.1. Những câu hỏi phải trả lời

  • Dùng biến nào để lưu n, p và total?
  • Dùng int hay long long?
  • Nếu n và p đều lớn, phép nhân có bị tràn không?
  • Đọc input và in output bằng lệnh nào?
Nếu n = 10^6p = 10^6, tổng là 10^12. Kiểu int không đủ.
Kết luận: Trước khi viết phép tính, phải xác định dữ liệu, miền giá trị và kiểu phù hợp.

2. Cấu trúc chương trình C++

Khung chương trình

#include 
using namespace std;

int main() {
    // Các câu lệnh
    return 0;
}

Ý nghĩa

  • #include: đưa thư viện vào.
  • using namespace std;: dùng tên chuẩn ngắn gọn.
  • main(): điểm bắt đầu chạy.
  • return 0;: kết thúc bình thường.
#include phổ biến trong thi đấu với GCC nhưng không phải header chuẩn trên mọi trình biên dịch.

3. Biến và phép gán

Khai báo

int age;

Tạo biến.

Khởi tạo

int age = 15;

Tạo và gán giá trị đầu.

Gán lại

age = age + 1;

Tính vế phải rồi ghi đè.

3.1. Mô phỏng biến như một ô nhớ

a = a + 1 không phải phương trình toán học. Dấu = trong C++ là phép gán.

4. Kiểu dữ liệu

KiểuDùng để lưuKích thước thường gặpMiền/độ chính xácVí dụ
boolĐúng/saiThường 1 bytefalse, truebool ok=true;
charMột ký tự1 bytePhụ thuộc signed/unsignedchar c='A';
intSố nguyênThường 4 byteKhoảng ±2.1×10⁹int n=100;
long longSố nguyên lớnThường 8 byteKhoảng ±9.22×10¹⁸long long sum=0;
doubleSố thựcThường 8 byteKhoảng 15 chữ số có nghĩadouble x=3.14;
stringChuỗiĐộngPhụ thuộc bộ nhớstring name="An";
Không ghi nhớ long luôn là 64-bit. Kích thước long phụ thuộc nền tảng. Khi cần khoảng 1018, ưu tiên long long.

4.1. Mô phỏng số byte

5. Phép toán và chuyển kiểu

Số nguyên

  • +, -, *
  • /: chia nguyên nếu hai toán hạng nguyên.
  • %: phần dư.

Số thực

  • 5 / 2 = 2
  • 5.0 / 2 = 2.5
  • static_cast(5) / 2 = 2.5

5.1. Mô phỏng phép chia

double x = 5 / 2; vẫn cho 2.0 vì phép chia nguyên xảy ra trước phép gán.

6. Nhập và xuất dữ liệu

cin và cout

int age;
string name;
cin >> age;
cin >> name;
cout << name << ' ' << age << '
';

cin >> name chỉ đọc đến khoảng trắng.

getline

int age;
string fullName;
cin >> age;
cin.ignore(numeric_limits::max(), '
'); getline(cin, fullName);

6.1. Mô phỏng Input → Process → Output

Input
Process
Output

7. Overflow và cách phòng tránh

Lỗi trung gian

int a = 1000000000;
int b = 1000000000;
long long product = a * b; // có thể sai

Cách đúng

long long product = 1LL * a * b;

1LL nâng kiểu biểu thức trước khi nhân.

7.1. Mô phỏng kiểm tra miền int32

Chuẩn C++: signed integer overflow là undefined behavior. Không nên dựa vào việc giá trị chắc chắn “quay vòng” sang âm.

8. Phân tích trước khi viết code

BướcCâu hỏiVí dụ tổng tiền
1Input là gì?n, p.
2Output là gì?n×p.
3Giá trị lớn nhất?10⁶×10⁶=10¹².
4Chọn kiểu?long long.
5Biểu thức có nâng kiểu trước?Cả n và p là long long.
6Định dạng output?Một số và xuống dòng.

9. Code mẫu

#include 
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    long long quantity, price;
    cin >> quantity >> price;

    long long total = quantity * price;
    cout << total << '
'; }
bool passed = true;
char grade = 'A';
int age = 15;
long long population = 10000000000LL;
double average = 8.75;
string fullName = "Nguyen Van An";

cout << boolalpha << passed << '
'; cout << fixed << setprecision(2) << average;
int age;
string fullName;

cin >> age;
cin.ignore(numeric_limits::max(), '
'); getline(cin, fullName); cout << fullName << '
' << age;
int a = 5, b = 2;
int integerResult = a / b;
double realResult = static_cast(a) / b;

cout << integerResult << '
'; cout << fixed << setprecision(2) << realResult;
int a = 1000000000;
int b = 1000000000;
long long correct = 1LL * a * b;
cout << correct;

10. Giải thích code

10.1. Vì sao dùng long long?

Để cả toán hạng và kết quả đều được tính trong miền đủ lớn.

10.2. Vì sao có hậu tố LL?

10000000000LL tạo literal kiểu long long.

10.3. Vì sao dùng '
'?

endl còn flush bộ đệm; '
'
thường nhanh hơn khi in nhiều.

10.4. Vì sao ignore trước getline?

Ký tự xuống dòng còn lại sau cin >> có thể khiến getline đọc dòng rỗng.

10.5. Vì sao gán vào double chưa đủ?

Phép chia xảy ra trước phép gán. Phải ép kiểu một toán hạng trước khi chia.

10.6. Vì sao long long result = a*b vẫn có thể sai?

Nếu a và b là int, phép nhân int xảy ra trước. Dùng 1LL*a*b hoặc ép kiểu trước.

11. Lỗi thường gặp

  • Dùng biến cục bộ chưa khởi tạo.
  • Nhầm = với ==.
  • Dùng int cho tổng/tích lớn.
  • Gán sang long long nhưng biểu thức vẫn tính bằng int.
  • Mong 5/2 bằng 2.5.
  • Dùng cin >> name cho họ tên có khoảng trắng.
  • Dùng getline ngay sau cin >> mà không xử lý newline.
  • Cho rằng long luôn 64-bit.
  • Dựa vào signed overflow quay vòng.

12. Quiz và bài tập

Câu 1. Kiểu phù hợp để lưu khoảng 10¹⁸?
Câu 2. Kết quả của 5/2 với hai int?
Câu 3. Cách tính tích hai int lớn an toàn hơn?

📘 Cơ bản

  1. Nhập hai số, in tổng, hiệu, tích.
  2. Đổi giây thành giờ–phút–giây.
  3. Tính chu vi, diện tích.

📗 Luyện kiểu dữ liệu

  1. Tính n×p với n,p≤10⁹.
  2. Tính trung bình ba số.
  3. Đọc họ tên bằng getline.

📙 Sửa lỗi

  1. Sửa lỗi chia nguyên.
  2. Sửa overflow trung gian.
  3. Sửa lỗi cin + getline.

🐣 Học tiếp

  1. Câu lệnh điều kiện.
  2. Vòng lặp.
  3. Mảng một chiều.