Bài 1.2: Các kiểu dữ liệu cơ bản và trong C++

Chào mừng các bạn quay trở lại với series blog về C++! Ở bài trước chúng ta đã làm quen với việc nhập xuất dữ liệu đơn giản bằng cincout. Hôm nay, chúng ta sẽ đi sâu vào một khái niệm cốt lõi khác của bất kỳ ngôn ngữ lập trình nào: Kiểu dữ liệu (Data Types).

Bạn hãy tưởng tượng nhé, máy tính lưu trữ mọi thứ dưới dạng số (bit và byte). Nhưng làm sao nó biết được "30" là tuổi của một người, "3.14" là số Pi, hay "A" là một chữ cái? Đó chính là lúc các kiểu dữ liệu ra đời! Chúng giúp chúng ta phân loại dữ liệu, cho trình biên dịch biết cách dữ liệu đó được lưu trữ trong bộ nhớ và những thao tác nào có thể thực hiện được với nó. Chọn đúng kiểu dữ liệu không chỉ giúp chương trình chạy đúng mà còn tối ưu hiệu quả sử dụng bộ nhớ nữa đấy!

Trong C++, các kiểu dữ liệu được chia làm hai nhóm chính: cơ bản (built-in/primitive) và phức tạp (user-defined/complex). Chúng ta sẽ cùng tìm hiểu chi tiết về từng nhóm nhé!

I. Các Kiểu Dữ Liệu Cơ Bản (Primitive Data Types)

Đây là những khối xây dựng nền tảng nhất trong C++. Chúng biểu diễn các giá trị đơn lẻ và được tích hợp sẵn trong ngôn ngữ.

Bảng so sánh các kiểu dữ liệu cơ bản trong C++:
Kiểu Dữ Liệu Kích Thước (byte) Phạm Vi Giá Trị (dấu) Phạm Vi Giá Trị (không dấu)
int 4 -2,147,483,648 đến 2,147,483,647 0 đến 4,294,967,295
short 2 -32,768 đến 32,767 0 đến 65,535
long 4 hoặc 8 -2,147,483,648 đến 2,147,483,647 (trên 32-bit) 0 đến 4,294,967,295 (trên 32-bit)
long long 8 -9,223,372,036,854,775,808 đến 9,223,372,036,854,775,807 0 đến 18,446,744,073,709,551,615
float 4 Khoảng -3.4E+38 đến 3.4E+38 Không áp dụng
double 8 Khoảng -1.7E+308 đến 1.7E+308 Không áp dụng
long double 8 hoặc 16 Khoảng -1.7E+308 đến 1.7E+308 Không áp dụng
1. Số Nguyên (Integer Types)

Dùng để lưu trữ các số không có phần thập phân. C++ cung cấp nhiều loại số nguyên với kích thước và phạm vi khác nhau, phù hợp với nhu cầu lưu trữ từ nhỏ đến rất lớn:

  • int: Kiểu số nguyên phổ biến nhất, kích thước thường là 4 byte (32 bit) trên hầu hết các hệ thống hiện đại, có thể lưu trữ số dương và âm.
  • short: Thường là 2 byte (16 bit), phạm vi nhỏ hơn int. Dùng khi bạn cần tiết kiệm bộ nhớ và giá trị không quá lớn.
  • long: Thường là 4 hoặc 8 byte (32 hoặc 64 bit), phạm vi lớn hơn int.
  • long long: Được chuẩn hóa từ C++11, đảm bảo ít nhất 8 byte (64 bit), dùng cho các số nguyên rất lớn.
  • Các biến thể unsigned: Dùng khi bạn chắc chắn số đó không âm. unsigned int, unsigned short, unsigned long, unsigned long long chỉ lưu trữ các giá trị không âm, do đó phạm vi dương của chúng lớn gấp đôi so với loại có dấu cùng kích thước. Điều này hữu ích khi bạn cần lưu trữ các giá trị như số lượng, kích thước, không bao giờ nhỏ hơn 0.

Ví dụ minh họa:

#include <iostream>

int main() {
    using namespace std;
    int a = 100;
    short b = 25;
    long c = 1000000L;
    long long d = 7800000000LL;
    unsigned int e = 500;

    cout << "int: " << a << endl;
    cout << "short: " << b << endl;
    cout << "long: " << c << endl;
    cout << "long long: " << d << endl;
    cout << "unsigned int: " << e << endl;

    return 0;
}

Output:

int: 100
short: 25
long: 1000000
long long: 7800000000
unsigned int: 500

Giải thích code:

  • Chúng ta khai báo và gán giá trị cho các biến thuộc các kiểu số nguyên khác nhau (int, short, long, long long, unsigned int).
  • Lưu ý cách sử dụng hậu tố L cho longLL cho long long khi giá trị vượt quá phạm vi của int mặc định.
  • cout được sử dụng để in tên kiểu dữ liệu và giá trị của biến ra màn hình console. endl giúp xuống dòng sau mỗi lần in.
2. Số Thực (Floating-Point Types)

Dùng để lưu trữ các số có phần thập phân. Chúng được biểu diễn xấp xỉ trong bộ nhớ máy tính, nên đôi khi có thể gặp sai số nhỏ trong tính toán. C++ cung cấp các mức độ chính xác khác nhau:

  • float: Thường là 4 byte (32 bit), cung cấp độ chính xác đơn (single-precision), thường đủ dùng cho các tính toán đơn giản không yêu cầu độ chính xác cao.
  • double: Thường là 8 byte (64 bit), cung cấp độ chính xác kép (double-precision), là kiểu phổ biến nhất và được khuyến khích dùng cho số thực trong hầu hết các trường hợp vì độ chính xác cao hơn float.
  • long double: Kích thước và độ chính xác có thể khác nhau tùy hệ thống, thường lớn hơn hoặc bằng double, dùng khi cần độ chính xác rất cao (ví dụ: tính toán khoa học, tài chính).

Ví dụ minh họa:

#include <iostream>
#include <iomanip>

int main() {
    using namespace std;
    float a = 8.75f;
    double b = 3.141592653589793;
    long double c = 1.234567890123456789L;

    cout << fixed << setprecision(2);
    cout << "Diem trung binh (float): " << a << endl;

    cout << setprecision(15);
    cout << "Pi (double): " << b << endl;

    cout << setprecision(20);
    cout << "Gia tri chinh xac (long double): " << c << endl;

    return 0;
}

Output:

Diem trung binh (float): 8.75
Pi (double): 3.141592653589793
Gia tri chinh xac (long double): 1.23456789012345670000

Giải thích code:

  • Khai báo các biến với kiểu float, double, long double.
  • Khi gán giá trị cho biến kiểu float, bạn nên thêm hậu tố f (hoặc F). Nếu không có hậu tố, số thực mặc định sẽ được coi là kiểu double.
  • Khi gán giá trị cho biến kiểu long double, bạn nên thêm hậu tố L (hoặc l).
  • Chúng ta sử dụng thư viện <iomanip> với fixedsetprecision để điều chỉnh số chữ số thập phân hiển thị, giúp thấy rõ hơn sự khác biệt về độ chính xác giữa các kiểu.
3. Ký Tự (Character Type)
  • char: Dùng để lưu trữ một ký tự duy nhất (chữ cái, số, ký hiệu, dấu câu...). Ký tự được lưu trữ dưới dạng mã số tương ứng trong bộ mã ký tự (phổ biến nhất là ASCII cho các ký tự tiếng Anh cơ bản, hoặc các bộ mã lớn hơn như Unicode). Kích thước thường là 1 byte.

Ví dụ minh họa:

#include <iostream>

int main() {
    using namespace std;
    char a = 'A';
    char b = '9';
    char c = ';';

    cout << "Ky tu chu cai: " << a << endl;
    cout << "Ky tu chu so: " << b << endl;
    cout << "Ky tu dac biet: " << c << endl;

    cout << "Ma ASCII cua 'A': " << static_cast<int>(a) << endl;
    cout << "Ma ASCII cua '9': " << static_cast<int>(b) << endl;

    return 0;
}

Output:

Ky tu chu cai: A
Ky tu chu so: 9
Ky tu dac biet: ;
Ma ASCII cua 'A': 65
Ma ASCII cua '9': 57

Giải thích code:

  • Biến kiểu char được gán giá trị là một ký tự trong cặp dấu nháy đơn (''). Đây là điểm khác biệt quan trọng so với chuỗi ký tự (string) dùng dấu nháy kép ("").
  • static_cast<int>(chuCai) là một cách ép kiểu (type casting) để chuyển đổi giá trị char thành kiểu int, giúp chúng ta in ra mã số (ASCII) tương ứng của ký tự.
4. Boolean Type
  • bool: Dùng để lưu trữ giá trị logic: true (đúng) hoặc false (sai). Kiểu này cực kỳ quan trọng trong việc điều khiển luồng chương trình bằng các câu lệnh điều kiện (if, else, while, v.v.). Kích thước thường là 1 byte.

Ví dụ minh họa:

#include <iostream>
#include <ios>

int main() {
    using namespace std;
    bool a = true;
    bool b = false;

    cout << "Trang thai hoc vien (so): " << a << endl;

    cout << boolalpha;
    cout << "Trang thai hoc vien (chu): " << a << endl;
    cout << "Trang thai tot nghiep: " << b << endl;

    if (a) {
        cout << "Hien tai ban dang theo hoc tai day!" << endl;
    } else {
        cout << "Ban khong phai la hoc vien hien tai." << endl;
    }

    return 0;
}

Output:

Trang thai hoc vien (so): 1
Trang thai hoc vien (chu): true
Trang thai tot nghiep: false
Hien tai ban dang theo hoc tai day!

Giải thích code:

  • Khai báo hai biến bool và gán giá trị true hoặc false.
  • Mặc định, khi in biến kiểu bool bằng cout, true được hiển thị là 1false0.
  • Sử dụng boolalpha (cần #include <ios>) sẽ khiến cout in ra chuỗi "true" hoặc "false".
  • Kiểu bool được sử dụng trực tiếp trong câu lệnh if để kiểm tra điều kiện.

Bài tập ví dụ: C++ Bài 1.A2: Chuyển đổi tốc độ

Hãy viết chương trình chuyển đổi \(a\) \(km/h\) sang \(m/s\).

INPUT FORMAT

Dòng đầu tiên chứa giá trị của \(a (1 \leq a \leq 10^6)\) là giá trị \(km/h\) cần chuyển đổi.

OUTPUT FORMAT

In ra là một số kết quả của bài toán được làm tròn hai chữ số sau phần thập phân.

Ví dụ 1:

Input
5
Ouput
1.39
Giải thích ví dụ mẫu:
  • Chuyển đổi 5 km/h thành 1.39 m/s, kết quả làm tròn hai chữ số thập phân.

Đây là hướng dẫn giải bài này bằng C++:

  1. Phân tích công thức chuyển đổi:

    • Ta biết 1 km = 1000 mét.
    • Ta biết 1 giờ = 60 phút = 60 * 60 = 3600 giây.
    • Vậy, 1 km/h = 1 km / 1 giờ = 1000 mét / 3600 giây = (1000 / 3600) m/s.
    • Rút gọn phân số 1000/3600 ta được 10/36 hay 5/18.
    • Do đó, để chuyển đổi a km/h sang m/s, ta nhân a với (5/18).
  2. Chọn kiểu dữ liệu:

    • Giá trị đầu vào a là số nguyên, nhưng kết quả chuyển đổi sang m/s thường là số thực.
    • Phép tính a * (5/18) cũng cần được thực hiện với các số thực để có kết quả chính xác.
    • Bạn nên sử dụng kiểu dữ liệu dấu phẩy động như double để lưu trữ kết quả trung gian và cuối cùng.
  3. Các bước thực hiện trong chương trình C++:

    • Bước 1: Đọc dữ liệu đầu vào. Sử dụng cin để đọc giá trị số nguyên a.
    • Bước 2: Thực hiện phép chuyển đổi. Tính toán giá trị tốc độ theo m/s bằng công thức a * (5.0 / 18.0). Lưu ý viết 5.0 / 18.0 (hoặc 5.0 / 18 hoặc 5 / 18.0) để đảm bảo phép chia là phép chia số thực.
    • Bước 3: Định dạng và in kết quả. Sử dụng cout để in kết quả. Để làm tròn và hiển thị kết quả với đúng hai chữ số sau dấu thập phân, bạn cần sử dụng các manipulator từ thư viện <iomanip>. Cụ thể, bạn sẽ cần fixed để đảm bảo số chữ số sau dấu thập phân được cố định, và setprecision(2) để chỉ định là 2 chữ số.
  4. Lưu ý:

    • Cần include các thư viện cần thiết: <iostream> cho nhập/xuất cơ bản và <iomanip> cho định dạng.
    • Sử dụng namespace std;

Chúc bạn lập trình tốt!

#include <iostream>
#include <iomanip>

int main() {
    using namespace std;
    double a;
    cin >> a;
    double kq = a * (5.0 / 18.0);
    cout << fixed << setprecision(2) << kq << endl;
    return 0;
}

Output:

1.39

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

Comments

There are no comments at the moment.