----> Lời khuyên cho các bạn bắt đầu học lập trình: nếu có tham khảo code trên mạng thì các bạn nên xem nó và tự viết lại rồi tìm hiểu xem từng phần trong code ý nó có mục đích là gì chứ đừng nên copy và paste một cách máy móc mà mình chả hiểu được code ý nó viết gì.
1. Tổng quan về kiểu dữ liệu cơ sở (basic data types)
Trong C++ có 7 kiểu cơ sở: char, wchar_t, int, float, double, bool, và void. Giả sử môi trường của chúng ta là một môi trường 32-bit thông thường:
2. Khai báo biến
Cú pháp chung của khai báo biến là:
Ví dụ:
int a, b, c;
char ch;
Ta cũng có thể khởi tạo giá trị cho biến ngay khi khai báo:
char ch=’T’; // ký tự phải được đặt trong dấu nháy đơn
3. Một số modifier cho kiểu dữ liệu
C++ cho phép “chế biến” các kiểu char, int, double bằng cách thêm modifier vào trước những kiểu dữ liệu này. Có 4 modifiers là: signed, unsigned, short, long.
Với kiểu int: có thể sử dụng được với cả 4 modifiers trên.
unsigned int x; // x được khai báo là kiểu nguyên không dấu.
short int x; // x được khai báo là kiểu nguyên ngắn
long int x; // x được khai báo là kiểu nguyên dài
Bây giờ ta sẽ xem xét chi tiết. Kiểu int mặc định là số nguyên có dấu, vì vậy khai báo signed int là không cần thiết, chỉ int là đủ. Khi đó một biến kiểu int sẽ chứa được những giá trị nằm trong miền -32,768 đến 32,767. Còn khi khai báo unsigned int, số nguyên sẽ được hiểu là không dấu. Do đó miền giá trị nó sẽ mở rộng gấp đôi vì không phải tốn một bit làm bit dấu. Về vấn đề này các bạn cần đọc lại cách biểu diễn số nguyên dưới dạng nhị phân, mã bù một, bù hai … Mình sẽ không nói sâu về vấn đề này vì nó nằm ngoài phạm vi topic. Còn về modifier short và long thì theo quy ước thông thường của các compiler C++: kiểu long int sẽ có dung lượng tối thiểu bằng int, còn kiểu int sẽ có dung lượng tối thiểu bằng short int. Các bạn có thể kiểm tra điều này bằng toán tử sizeof. Đây là chương trình mình test thử trên IDE – Dev C++ 4.9.9.2
using namespace std;
int main(){
cout << "short int: " << sizeof(short int) << endl;
cout << "int: " << sizeof(int) << endl;
cout << "long int: " << sizeof(long int) << endl;
return 0;
}
Kết quả:
Đối với kiểu char: ta có thể sử dụng signed và unsigned. Thông thường mặc định char là signed. Vì vậy không cần thiết phải thêm modifier signed, miền biểu diễn của char là từ -128 đến 127. Nếu sử dụng unsigned thì miền biểu diễn sẽ được mở rộng gấp đôi, từ 0 đến 255.
Đối với double: ta có thể dử dụng long. Một biến kiểu long double có dung lượng 12 bytes, nghĩa là được mở rộng thêm 4 bytes so với double (8 bytes).
Ta cũng có thể sử dụng nhiều modifier cho một kiểu dữ liệu nếu cần thiết và hợp lệ. Ví dụ:
unsigned short int;
Dựa vào miền biểu diễn của các kiểu dữ liệu các bạn có thể giải thích được một số hiện tượng như trong chương trình sau:
using namespace std;
int main(){
char x=126;
x++; // bây giờ x=127
cout << (int)x << endl; // in ra số 127
x++; // ta hy vọng x bây giờ là 128
cout << (int)x << endl; // x có bằng 128 ???
return 0;
}
Đây là kết quả (lưu ý rằng mình đã nói từ đầu, bài viết này được viết trong môi trường 32-bit điển hình. Hiện tại mình đang dùng Windows 7 _ Ultimate _ Copyright by Microsoft _ 15,000 VNĐ mua ở đại lý phân phối chính thức trên đường Lê Thanh Nghị).
Hiện tượng này gọi là “tràn số” (overflow), vì giá trị của biến vượt ngoài miền biểu diễn mà kiểu char quy định. Vì vậy, giá trị của biến bị “quay vòng” lại. Nói chung các bạn không cần confused quá nhiều về vấn đề dung lượng chính xác cho một kiểu dữ liệu cơ bản như in, float hay double là bao nhiêu. Điều này tùy thuộc vào trình biên dịch và platform của bạn.
4. Các toán tử (operators)
Kiểu dữ liệu không chỉ quy định miền biểu diễn của các biến thuộc kiểu đó mà nó con quy định các phép toán (hay toán tử - operators) được phép thao tác trên những biến đó. Ví dụ ta có thể lấy phần dư của một số kiểu int bằng toán tử % nhưng không thể làm điều này với kiểu double. Các toán tử của C++ có thể phân thành ba loại: toán tử số học (arithmetic), toán tử quan hệ và logic (relational and logical), và các toán tử thao tác trên bit (bitwise).
Toán tử số học (arithmetic operator): bao gồm
Chú ý rằng toán tử modulus (%) chỉ áp dụng được với giá trị nguyên (char, int, long, bool), không áp dụng được với float hay double. Nó trả về kết quả là phần dư của phép chia hai số nguyên. Ví dụ
cout << x%y << endl; // in ra kết quả là 2, vì 5 chia 3 dư 2
Toán tử division (/) khi áp dụng với số nguyên thì sẽ là phép chia nguyên. Nghĩa là kết quả trả về sẽ là phần nguyên của phép chia, muốn thu được kết quả chính xác ta phải “ép kiểu”. Ví dụ chương trình sau:
cout << x/y << endl; // in ra 2
cout << (double)x/y << endl; // in ra 2.5
Toán tử ++ và -- là hai toán tử chỉ có trong C++. Nó cho phép viết những câu lệnh hết sức súc tích. Nó có thể dùng cả ở dạng tiền tố (prefix) lẫn hậu tố (postfix).
--x hoặc x-- : tương đương với x=x-1;
Hầu hết các compiler C++ đều sinh mã máy rất nhanh và hiệu quả cho cho các toán tử ++ và --. Vì vậy câu lệnh x++; hoặc ++x; sẽ nâng cao hiệu suất chương trình hơn là sử dụng câu lệnh gán x=x+1.
Nếu các câu lệnh tăng/giảm giá trị của biến đứng độc lập, nghĩa là không được sử dụng trong các biểu thức tính toán, thì cách viết tiền tố và hậu tố là hoàn toàn như nhau. Tuy nhiên, nếu câu lệnh tăng/giảm giá trị này nằm trong biểu thức tính toán thì sẽ có sự khác biệt. Dạng tiền tố sẽ tăng giá trị của biến lên 1 đơn vị rồi mới sử dụng, còn dạng hậu tố sử dụng giá trị của biến xong rồi mới tăng giá trị biến lên 1. Xem xét chương trình sau.
using namespace std;
int main(){
int a=100;
int x=5, y=5;
cout << a*(x++) << endl; // in ra 500 vì dùng x=5 trước rồi mới tăng x thành 6
cout << a*(++y) << endl; // in ra 600 vì tăng y lên thành 6 rồi mới sử dụng
return 0;
}
Toán tử quan hệ và logic (relational and logic operators)
Các toán tử quan hệ thể hiện mối quan hệ giữa giá trị này với giá trị khác. Ví dụ: x>=5; y!=z; … Các toán tử logic thể hiện cách mà các giá trị logic (true/false) liên kết với nhau. Ví dụ (x>=3) && (x<=10), … Vì các toán tử quan hệ sinh ra các giá trị true/false nên nó thường đi kèm với các toán tử logic. Các toán tử quan hệ của C++ bao gồm: >, >=, <, <=, ==, !=. Các toán tử logic bao gồm: && (and), || (or), ! (not). Ý nghĩa của chúng hoàn toàn như trong đại số.