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

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 cin
và cout
. 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ơnint
. 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ơnint
.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
cholong
vàLL
cholong long
khi giá trị vượt quá phạm vi củaint
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ơnfloat
.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ằngdouble
, 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ặcF
). Nếu không có hậu tố, số thực mặc định sẽ được coi là kiểudouble
. - Khi gán giá trị cho biến kiểu
long double
, bạn nên thêm hậu tốL
(hoặcl
). - Chúng ta sử dụng thư viện
<iomanip>
vớifixed
vàsetprecision
để đ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ểuint
, 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ặcfalse
(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ặcfalse
. - Mặc định, khi in biến kiểu
bool
bằngcout
,true
được hiển thị là1
vàfalse
là0
. - Sử dụng
boolalpha
(cần#include <ios>
) sẽ khiếncout
in ra chuỗi"true"
hoặc"false"
. - Kiểu
bool
được sử dụng trực tiếp trong câu lệnhif
để 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++:
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âna
với (5/18).
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.
- Giá trị đầu vào
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êna
. - 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ết5.0 / 18.0
(hoặc5.0 / 18
hoặc5 / 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ầnfixed
để đả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ố.
- Bước 1: Đọc dữ liệu đầu vào. Sử dụng
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;
- Cần include các thư viện cần thiết:
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
Comments