You are on page 1of 82

Nội dung 2: Biến và kiểu

TS. Trần Thanh Hải

u = x + z*y
Nội dung

• Mở đầu.
• Các kiểu dữ liệu.
• Định danh.
• Khai báo biến (Declaration of variables).
• Các hằng.
• Khởi tạo giá trị của biến ban đầu.
• …..
Mở đầu
• Để viết được chương trình thực hiện thêm nhiệm vụ có ích.
Giới thiệu khái niệm về biến (variables).

• Hãy tưởng tượng yêu cầu bạn nhớ số 5, sau đó cũng yêu cầu
bạn nhớ số 2. Bạn chỉ việc phải lưu hai giá trị khác nhau trong
bộ nhớ của bạn (5 và 2).
• Bây giờ yêu cầu bạn cộng số 1 vào số ban đầu. Bạn nên cất giữ
số 6 (6 = 5 + 1) và số 2 trong bộ nhớ của bạn.
• Tiếp theo trừ hai giá trị đó cho nhau và được kết quả là 4.
• Toàn bộ quá trình miêu tả ở trên là một sự đơn giản những gì
máy tính có thể làm đối với hai biến. Quá trình trên có thể
được biểu diễn trong C++ bằng một tập các câu lệnh sau:

a = 5; b = 2;
a = a + 1;
ketqua = a – b; // 4
Mở đầu
• Mục đích: Biến được sử dụng để lưu trữ dữ liệu cho quá trình
tính toán. Giá trị của biến có thể thay đổi một hoặc nhiều lần
khi một chương trình chạy và được gọi là biến bởi vì ta có thể
thay đổi giá trị lưu trữ.
• Biến là vị trí lữu trữ được đặt tên, có thể lưu trữ giá trị của
một kiểu nào đó. Nói cách khác: biến có KIỂU,TÊN và GIÁ TRỊ
lưu trữ.
1. Các kiểu dữ liệu

• Máy tính lưu trữ hàng tỷ số như vậy tại cùng một thời gian.
• Mỗi biến cần một tên để định danh nó (chứng minh thư –
identifies) và dùng để phân biệt biến này với biến khác.(miễn
là định danh hợp lệ).
• Ví dụ: Chương trình sau tạo:
- Một biến gọi là value, đặt cho value một giá trị 1023.
- Và hiện lên màn hình thông báo:
Chuong trinh in gia tri Value = 1023.
• int value; // khai bao bien nguyen
value = 1023; // bien duoc gan gia tri 1023
cout<<"Chuong trinh in gia tri Value = ";
cout<<value<<endl; // hien len man hinh 1023

// dấu này là một điểm mới C++ so với C


Giải thích chương trình

• Câu lệnh: int value;


- Khai báo 1 biến kiểu số nguyên có tên là value:
(vì 1023 int).
int : -2147483648  2147483647.
short int: -32,768  32,767. (lựa chọn khai báo hợp lý)
unsigned short int: 0  65,535.
unsigned int: 0  4,294,967,295.
- Khai báo: đặt biến trước từ khóa: int. (int value;)
- Như vậy:
 Toàn bộ biến phải được khai báo trước khi sử dụng.
 Kiểu của biến: xác định giá trị của của biến.
(int – value là nguyên).
Giải thích - Chương trình

+ Câu lệnh: value = 1023;


- Gán giá trị 1023 cho biến value.
- Toán tử gán bằng (assignment): =
Qui tắc: Copy giá trị bên phải sang biến bên trái nó.
Sau câu lệnh gán: biến value chứa số 1023. (tại một địa
chỉ nào đó – muốn biết địa chỉ: cout<<&value;)
+ Hai câu lệnh cout: hiện thị thông báo và kết quả ra màn hình
• Tổng quát: Muốn hiện thị giá trị của biến đơn giản là đặt biến
vào bên phải toán tử chèn<< trong cout. Như trong câu lệnh:
cout<<value;
• endl chèn một ký tự newline (dòng mới) sau mỗi dòng,
• Hằng ký tự “\n”: xuống dòng (đặt vị trí bất kỳ trong xâu).
Một số vấn đề?

• Khai báo biến như thế nào? (mẫu khai báo biến)?
• Có các loại kiểu biến nào? Lưu trữ bộ nhớ như thế nào?
• Tên của biến - định danh, viết thế nào là hợp lệ?
• Khởi tạo – gán giá trị ban đầu, hoặc không gán thì như thế nào?
• Biến thay đổi – biến const.

Kiểu Tên biến Giá trị?

int a; cout<<a<<endl; a = ?
... …. ...
Kiểu (type) của biến

• 2 loại kiểu là: kiểu


dựng sẵn và kiểu
người dùng định
nghĩa.
• Bảng hiển thị kiểu
biến - lượng bộ
nhớ dùng để lưu
giá trị - giá trị lớn
nhất và nhỏ nhất
có thể được lưu với
các kiểu biến đó.

Giống toán: N, Z, Q, R, và R
2. Định danh
2.1. Tập ký tự dùng trong ngôn ngữ C/C++ (Character set)
• Mọi ngôn ngữ được xây dựng từ một bộ ký tự nào đó. Các ký tự
nhóm lại để lập nên các từ (dãy kí tự viết liền nhau)
• Ngôn ngữ C/C++ được xây dựng trên bộ kí tự sau:
+ 26 chữ cái hoa: A, B, C,…,Z.
+ 26 chữ cái thường a, b, c,…,z.
+ 10 chữ số: 0, 1, 2, …,9.
+ Các ký tự toán học: + - * / = ().
+ Ký tự gạch nối: _ (chú ý phân biệt với dấu -)
+ Các ký tự đặc biệt: . ; : [] {} ? ! \ & | %, @,...
+ Khoảng trắng (whitespace): dấu cách, \t (tab), ký tự
xuống dòng \n.
+ Dấu cách (space): một khoảng trống dùng để tách các từ.
Ví dụ

• HA NOI gồm 6 kí tự, còn HANOI gồm 5 ký tự. (2 từ - 1 từ)

• Chú ý: Khi viết chương trình ta không sử dụng bất kỳ ký hiệu


nào khác ngoài các ký tự nói trên.
2.2. Từ khóa

• C++ hay bất kỳ ngôn ngữ lập trình nào khác, đều có sẵn một
số các từ khóa do người tạo ra ngôn ngữ đó định nghĩa sẵn.
• Mỗi từ khóa có một ý nghĩa riêng. C++ có khoảng 85 từ khóa
alignas, alignof, and, and_eq, asm, auto, bitand, bitor,
bool, break, case, catch, char, char16_t, char32_t, class, compl,
const, constexpr, const_cast, continue, decltype, default, delete,
do, double, dynamic_cast, else, enum, explicit, export, extern,
false, float, for, friend, goto, if, inline, int, long, mutable,
namespace, new, noexcept, not, not_eq, nullptr, operator, or,
or_eq, private, protected, public, register, reinterpret_cast,
return, short, signed, sizeof, static, static_assert, static_cast,
struct, switch, template, this, thread_local, throw, true, try,
typedef, typeid, typename, union, unsigned, using, virtual, void,
volatile, wchar_t, while, xor, xor_eq

Ghi chú: mầu đỏ là điểm mới C++ so với C


2.3. Định danh

• Định danh (Tên): là một chuỗi các ký tự, dùng để xác định các đại
lượng khác nhau trong một chương trình như: tên hằng, tên biến,
tên mảng, tên hàm, tên con trỏ, tên tệp, tên cấu trúc,…
• Định danh (Tên) được đặt theo qui tắc:
+ Tên là một dãy các ký tự : chữ, số và dấu gạch nối(_) (không
gạch ngang -)
+ Ký tự đầu tiên: phải là chữ hoặc gạch nối (_).
+ Tên không được trùng với từ khóa (keyword).
+ Không bắt đầu bằng số, không chứa ký tự có gạch chân (U)
+ Các khoảng trống, hệ thống chấm câu, và các ký hiệu
(symbol - [] {}?! \&|%...) không thuộc phần định danh.
+ Độ dài của tên mặc định là 32 ký tự. (thay đổi theo biên
trình dịch lên đến 255 ký tự).
2.3. Định danh

• Ví dụ đúng: _abc, abc; Abc, aBc; abC;


• Ví dụ định danh sai: 1sttest, oh!god, và start…end; this;
• Chú ý:
+ Trong các tên, chữ hoa và chữ thường được xem là
khác nhau: AB ab Ab aB.
+ Chữ hoa (AB) để đặt tên cho các hằng, chữ thường để
đặt tên cho các đại lượng khác.
+ Ví dụ: #define MAX 100
#define PI 3.141516
Đặt tên biến theo truyền thống

• Tên biến là một danh từ hoặc cụm danh từ.


• Từ đầu tiên là chữ viết thường. Từ tiếp theo viết thường trừ
từ đầu tiên và không có khoảng trống giữa các từ.
• Trừ một số từ thông dụng: i, j chỉ chỉ số của mảng. x, y, z là tọa
độ.
• Không nên đặt biến không có nghĩa: a, b, …
• Ví dụ: xMax, yMin, xTopLeft,
double sum, product, average;
const double PI = 3.1415;
(MIN_VALUE, MAX_SIZE)
3. Khai báo biến (Declaration of variables)
• Mỗi biến phải được khai báo trước khi sử dụng lần đầu. Mỗi
biến chỉ cần khai báo một lần và lấy 1 kiểu.
• Biến được khai báo ở bất kỳ vị trí nào trong chương trình, kiểu
biến không thể thay đổi trong chương trình.
• Khi biến được khai báo, nó chứa giá trị bất kỳ (rác) đến khi
gán một giá trị ban đầu.
• Mục đích của khai báo biến là thông tin đến compiler (biên
dịch) kích thước để lưu trữ trong bộ nhớ và cách thông dịch
giá trị của của nó.
a) Cú pháp : type danh_sách_biến;
type: là kiểu hợp hệ của C++ (char, float, double, int,
void, và định nghĩa)
danh_sách_biến: chứa một hoặc nhiều định danh cách
nhau bởi dấu phảy.
3. Khai báo biến (Declaration of variables)

• Cụ thể một số dạng khai báo:


 Khai báo 1 biến đơn: int a;
 Khai báo nhiều biến cùng một kiểu và cách nhau bởi dấu phẩy:
float f, bal; // nhiều biến – tương đương: float f; float bal;
char ch, chr;
 Khai báo một biến và gán giá trị khởi đầu:
double d = 20.5;
 Khai báo nhiều biến với giá trị khởi đầu:
double a = 20.5, b = 30.0;
• Sự khác biệt trong khai báo: int a = 10; // khai báo + khởi tạo.
int a;
a = 10;
3. Khai báo biến (Declaration of variables)

• CHÚ Ý với biến không có khởi tạo ban đầu tức là không có dạng
// int number = 10;
• THÌ IN ra số bất kỳ (RÁC)
int number; // khai báo nhưng không khởi tạo ban đầu
cout<<number<<endl; // in ra số bất kỳ (rác)
Ví dụ

• Tính tần số dao động (rad/s) của hệ một bậc tự do.

k Bắt đầu
n 
m
• k – độ cứng lò xo (N/m) k, m
• m – khối lượng của vật (kg).
int main(){
double stiffnessK, massM, omega;  = sqrt(k/m)
omega = sqrt(stiffnessK/massM);
}
Bắt đầu
b) vị trí biến có thể được đặt khai báo: (3 vị trí)

 Bên trong các hàm (local variable – biến cục bộ - biến địa
phương)
 Trong định nghĩa các tham số hàm.(tham số hình thức – formal
parameters ) ( là các biến cục bộ nhận giá trị của đối được truyền
cho hàm)
 Bên ngoài các hàm (biến toàn cục global variables)
#include<iostream>
int func (int a, int b) // Tham so hinh thuc
int count; // global variable
int main() { {
int value; // bien cuc bo
return 0;
}
* Khai báo linh hoạt hơn C: C++ cho phép trộn lẫn các khai báo dữ liệu với các hàm và chương trình
thực hiện
Thuộc tính của biến (2 thuộc tính)

• Kiểu và lớp lưu trữ (storage class)


• Kiểu: hình thành kiểu dữ liệu có thể được lưu dữ trong một biến. Ví
dụ: int, float, char…
• Lớp lưu trữ điều khiển hai thuộc tính của một biến:
+ thời gian tồn tại (xác định biến có thể tồn tại bao lâu) và
+ phạm vi (xđ phần nào của chương trình có thể truy cập biến).
• Phụ thuộc vào lớp lưu trữ của một biến, có thể chia làm 4 kiểu
chính.
+ Biến cục bộ.
+ Biến toàn cục .
+ Biến cục bộ static (biến cục bộ tĩnh).
+ Biến register.
+ Biến thread local storage.
Thuộc tính của biến

a) Biến cục bộ
• Biến định nghĩa bên trong một hàm (định nghĩa bên trong
thân hàm giữa các ngoặc {} ) được gọi là biến cục bộ hoặc là
biến tự động (automatic variable).
• Phạm vi: chỉ giới hạn trong hàm đó nơi mà nó định nghĩa. Biến
cục bộ tồn tại và chỉ có thể truy cập bên trong hàm.
• Thời gian tồn tại: biến cục bộ kết thúc khi hàm kết thúc.
b) Biến toàn cục
• Biến định nghĩa bên ngoài toàn bộ hàm gọi là biến toàn cục.
• Phạm vi: là toàn bộ chương trình, nghĩa là nó có thể được sử
dụng và bị thay đổi tại bất kỳ phần nào của chương trình sau
khai báo của nó.
Thuộc tính của biến

c) Biến cục bộ tĩnh (static local variable)


• Sử dụng từ khóa: static để hình thành biến tĩnh
ví dụ
int main()
{
static float a;
}

• Tồn tại: chỉ trong một hàm, nơi khai báo (tương tự như biến
địa phương) nhưng thời gian tồn tại của nó khi hàm được gọi
và chỉ kết thúc khi chương trình kết thúc.
• Sự khác biệt giữa biến cục bộ và biến tĩnh (static) là: giá trị của
biến tĩnh tiếp tục tồn tại đến khi kết thúc chương trình.
Ví dụ sử dụng static
#include<iostream> Gia tri hien thoi cua num = 3
void count(int i); Gia tri hien thoi cua num = 7
int main() {
count(3);
count(4);
// cout<<num<<endl; khong the truy cap duoc (cuc bo)
return 0;
}
void count(int i) {
static int num = 0;
num +=i;
cout<<"Gia tri hien thoi cua num = "<<num<<endl;
}

• Khai báo static: chỉ được khởi tạo 1 lần duy nhất và tồn tại
suốt thời gian chạy của chương trình. Giá trị của biến num sẽ
được tích luỹ mỗi khi hàm count được gọi.
• Biến num là 1 biến cục bộ (local variable).
4. Hằng (literals)

• Hằng là một giá trị cụ thể (123, -456, 3.14, ‘a’, “Hello”) có thể
gán trực tiếp cho một biến; hoặc là sử dụng như một phần
của một biểu thức.
• Các đại lượng này có giá trị không thay đổi trong quá trình
tính toán.
• Ví dụ: int number = -123;
int sum = 4567;
int bigSum = 8234567890; // lỗi, giá trị này vượt qua giới hạn
int number2 = 01234// octal 1234, hệ số 10: 2322
int number3 = 0x1abc; // hexadecimal 1ABC, decimal: 15274
a) Hằng dấu phẩy động (float và double)

1. Dạng thập phân 3.14159 // 3.14159


(phần nguyên dấu chấm thập phân và phần 3.0 // 3.0
phân) .34, 15. (không thể thiếu dấu chấm)

2. Dạng khoa học hay dạng mũ 6.02e23 // 6.02 x 10^23


(Số được tách làm 2 phần: định trị và 1.6e-19 // 1.6 x 10^-19
phần bậc cách nhau bởi kí tự e hoặc E) 0.12E3 // 120

*float hoặc long double có thể được hình 6.02e23f // float


thành bằng cách thêm vào hậu tố 3.14159L // long double
float (f hoặc F),long double (l hoặc L) 6.02e23F // float
b) Hằng int [-2147483648, 2147483648]
int 1776 biểu diễn: một nghìn bảy trăm sáu bảy.
75 // int

Hậu tố có thể thêm vào một chữ 75u // unsigned int


số nguyên để thiết lập kiểu số 75l // long
nguyên khác. 75ul // unsigned long
unsigned (u hoặc U), long (l or L) 75lu // unsigned long
long longll or LL

Chú ý: phân biệt số nguyên và số 125 và 125.0 (nguyên và thực)


thực
Chú ý: tràn bộ nhớ trên/dưới

• Nếu giá trị vượt rải khai báo – tràn bộ nhớ trên hoặc tràn bộ
nhớ dưới.
• Khi đó: kết quả của quá trình là các giá trị nháp (rác) làm tròn
nào đó.
• C++ không đưa ra lời cảnh báo/hoặc là lỗi nào cả nhưng tạo ra
một kết quả sai.
• Do đó, người lập trình phải chịu trách nhiệm kiểm tra sự tràn
nhớ trên/dưới.
• Ví dụ: // Dai kieu int [-2147483648, 2147483648]
int i1 = 2147483647; // max int = INT_MAX
cout<<"overflow: i1 + 1 = "<< i1 + 1<<endl; //-2147483648
cout<<"Ket qua khong chinh xac: i1*i1 = "<<i1*i1<<endl; // 1
c) Hằng int hệ số 8 và hệ số 16
• Hệ octal (cơ số 8): số được đặt trước với một ký tự 0 (zero).
0c1c2…. với, ci – là số nguyên trong khoảng từ 0 đến 7.
• Hệ hexa (cơ số 16): được đặt trước bởi ký tự 0x (zero, x).
0xc1c2.
• (sử dụng 16 ký tự: 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F) để tránh
nhầm lẫn giữa số 11
• Ví dụ: int number2 = 071263;
• int number3 = 0xA2F7;
Ví dụ (mở rộng làm thêm – ra giấy)
75 // decimal 75 = 7101 + 5100. // he co so 10
0113 // octal 75 = 182 + 181 + 380.// he co so 8
0x4b // hexadecimal 75 = 4161 + 11160. // he co so 16
• Chương trình chuyển đổi cơ số 10 sang cơ số 8 (octal).
Xanh: phần dư
Tím: cơ số 8 (octal) 16 8
Đỏ: phần nguyên chia tiếp cho 8 16 2 8
Hướng mũi tên: Viết ngược lên.
(16)10 = (20)8 hay 020 0 0 0
Chú ý:
2
(phần dư sau gấp phần dư trước 10 lần)
+ Hằng ký tự (Character literal):
là một ký tự riêng biệt được viết trong 2 dấu nháy đơn:

Ví dụ: 'a', giá trị của 'a' là 97: theo bảng mã ASCII.
- Hằng ký tự có thể tham gia vào các phép toán như mọi số
nguyên khác:
Ví dụ: '9' - '0' = 57 – 48 = 9. (STT mã)
- Hằng ký tự còn có thể viết theo cách khác: '\c1c2c3'
Với: c1c2c3 là hệ 8 của nó = mã ASCII của ký tự cần biểu diễn:
Ví dụ: chữ a có hệ 10 là 97  mã 8 là 0141 vậy hằng ký tự a có
thể viết dưới dạng là: '\141‘ (tức là bỏ 0 (zero))
hệ cơ số 16: một ký tự x được chèn giữa dấu gạch ngang và số hệ
cơ số 16 (ví dụ chữ a trong hệ 16: \x61)
example
Ví dụ

• https://en.cppreference.com/w/cpp/header/climits
#include<cstdlib>
#include<climits>
using namespace std;
int main(){
cout<<"int max = "<<INT_MAX<<endl;
cout<<"int min = "<<INT_MIN<<endl;
return EXIT_SUCCESS;
}
Một vài hằng ký tự đặc biệt

Escape code Description Miêu tả

\n newline Chuyển dòng


\r carriage return Về đầu dòng
\t tab Tab ngang
\v vertical tab Tab thẳng
\b backspace Backspace
\f form feed (page feed) Sang trang
\a alert (beep) Tiếng beep
\' single quote (') nháy đơn “ \’ ” = ‘
\" double quote (") nháy kép “\” “ = “
\? question mark (?) dấu ? “\?” = ?
\\ backslash (\) ngạch ngang “\\” = \
\N Octan constant hệ cơ số 8 “\141” = a
\xN Hexadecimal constant Hệ cơ số 16 “\x61” = a
Ví dụ
#include<iomanip>
cout<<“\a”; cout<<“\007”;// tao tieng bell
cout.setf(ios::showbase); //bật số nguyên hệ 8, 16
cout<<"So 41 dang co so 16 (hex) la: "<<hex<<41<<endl;
cout<<"So 41 dang co so 8 (oct) la: "<<oct<<41<<endl;
cout<<"So 41 dang so thap phan la: "<<dec<<0x29<<endl;
cout<<"\141"<<endl; // octan \N... Hằng
cout<<"\x61"<<endl; // hex \x
Output: 0x29
051
41
a
a
d) Hằng xâu ký tự

• Hằng xâu ký tự (string literals): là một dãy ký tự bất kỳ đặt


trong hai dấu nháy kép (" ")
• Ví dụ: "Hello world", "HaNoi", " " // xâu rỗng
• Xâu ký tự được lưu trữ dưới dạng một mảng có các phần tử là
các ký tự riêng biệt. Trình biên dịch tự động thêm ký tự null
(\0) vào cuối mỗi xâu (ký tụ \0 được xem là dấu hiệu kết thúc
của một xâu ký tự)
• Phân biệt:
• ‘a' và “a”: ‘a’ – ký tự hằng lưu trữ trong 1 byte, còn “a” là hằng
xâu ký tự lưu trong mảng 2 phần trử (phần tử a và phần tử \0)
• Chữ số 0 có mã 48, còn \0 có mã: 26 (theo bảng mã ASCII)
e) Hằng khác

• Ba từ khóa bằng chữ tồn tại trong C++: true, false và nullptr
true và false là hai giá trị có thể của biến kiểu bool.
bool foo = true; bool bar = false;
cout<<true<<false<<endl; // in ra 1 và 0
int* p = nullptr; // nullptr là giá trị con trỏ null.
• Lệnh khai báo biến hằng Tên hằng:
Định nghĩa bộ tiền xử lý (Preprocessor definitions) : (#define)
Cú pháp: #define identifier replacement
#define PI 3.141516 // Không có thông tin kiểu
• Ví dụ:
Ví dụ: khai báo hằng sử dụng từ khóa: const
• Giá trị không thay đổi trong quá trình chạy, sử dụng const cần
phải khởi gán trong khi khai báo.
const double PI = 3.14159;
const char newline = '\n';
int main (){
double radius = 5.0;
double circleArea;
circleArea = 2 * PI * radius;
cout << circleArea;
cout << newline;
}
OUTPUT:31.4159

*const trong c chỉ để thay thế define, và const mượt từ C++,


*trong C++ const có thể được dùng ở vị trí mọi hằng ký hiệu.
Tóm tắt
5. Khởi tạo giá trị của biến ban đầu

• Khi các biến trong ví dụ trên được khai báo, chúng có giá trị
không xác định đến khi chúng được gán giá trị lần đầu.
• Nhưng biến có giá trị xác định tại thời điểm khai báo được
gọi là khởi tạo giá trị ban đầu của biến.

Trong C++, có ba cách để khởi tạo biến ban đầu


Phương pháp thứ 1: khởi tạo giống C (bởi vì Cú pháp: type identifier = initial_value;
nó kế thừa từ ngôn ngữ C) int x = 0;// int x; x = 0;
Phương pháp thứ 2: khởi tạo constructor Cú pháp: type identifier (ini_value);
(giới thiệu bởi ngôn ngữ C++) int x(0);
Phương pháp thứ 3: khởi tạo đồng dạng Cú pháp: type identifier {itial_value};
(uniform initialization), C++ 2011 int x {0};
Ví dụ Khởi tạo giá trị của biến ban đầu
// initialization of variables
#include <iostream>
using namespace std;
int main () {
int result; // initial value undetermined
cout << result; // Giá trị = ?
int a=5; // initial value: 5 ,
// hoac a= 5; //tuong duong
int b(3); // initial value: 3
int c{2}; // initial value: 2 //Version 11
a = a + b;
result = a - c;
cout << result; // Giá trị = ?
return 0; }
// In giá trị result trước và sau gán
Mặc định khởi tạo biến toàn cục - cục bộ

• Biến toàn cục có giá trị khởi động theo bảng sau

Kiểu dữ liệu Giá trị khởi tạo


int 0
char '\0'
float 0
double 0
pointer NULL

• Còn biến cục bộ có giá trị bất kỳ. (trừ char) vậy = ? (VNXEM)
Ví dụ

int X;
char ch;

int main() {
// bien cuc bo
int a;
char b;
cout<<"Gia tri khoi dau cua bien toan cuc X = "<<X<<endl;
cout<<"Gia tri khoi dau cua bien toan cuc char ch "<<int(ch)<<endl;
cout<<"Gia tri khoi dau cua bien cuc bo a = "<<a<<endl;
cout<<"Gia tri khoi dau cua bien cuc bo char b = "<<int(b)<<endl;
}
6. Qui tắc chuyển kiểu tự động (đối với 2 toán hạng khác nhau)

a) Một số định nghĩa cơ bản


• Toán hạng: là một đại lượng có giá trị nào đó gồm: hằng, biến,
phần tử mảng và hàm.
1.const int a = 100;
2. int x; float y; // toán hạng x,y
3. float z; // toán hạng z
• Biểu thức: là sự kết hợp các phép toán và các toán hạng để
tạo nên những giá trị mới.
4. z = x+y; // z là biểu thức lập bởi các toán hạng x và y và phép tính cộng (+)
5. z = x;
• Như vậy, biểu thức dùng để diễn đạt một công thức, một qui
trình tính toán.
b) Trường hợp chuyển đổi kiểu giá trị
(tự động (ẩn) – hiển)

• Chuyển đổi tự động trong 2 trường hợp sau:


 Khi biểu thức gồm các toán hạng khác kiểu. (ví dụ kiểu int và
float) (line 4)
 Khi gán một giá trị kiểu này cho một biến (hoặc phần tử mảng)
kiểu khác (line 5). Hoặc truyền giá trị các tham số thực sự cho
đối.
• Ngoài ra chuyển từ một kiểu giá trị này sang một kiểu bất kỳ
mà ta muốn bằng phép ép kiểu:
Cú pháp: (type) (biểu thức)
ví dụ: (float)(x)// chuyển từ kiểu int sang float, nhưng
bản thân kiểu của x cũng không bị thay đổi vẫn là int.
Qui tắc chuyển đổi kiểu tự động
 Chuyển đổi kiểu trong biểu thức: khi hai toán hạng trong một phép toán có
kiểu khác nhau thì kiểu thấp hơn sẽ được nâng thành kiểu cao hơn trước
khi thực hiện phép toán. Kết quả thu được là một giá trị có kiểu cao hơn.
Cụ thể: Giữa int và long thì int  long.
Giữa int và float thì int  float. (1/2 = 0.5) (1./2) kq là float
Giữa float và double thì  double.
 Phép chuyển đổi kiểu cũng được thực hiện thông qua phép gán.
• Giá trị vế phải được chuyển sang kiểu của vế trái đó là kiểu của kết quả.
int  float: (11.0)
float  int do chặt cụt phần thập phân: (1.51)
double  float bằng cách làm tròn: 1.567  1.567
long  int bằng cách ngắt bỏ vài chữ số: 0.5  0.
• (nếu làm như vậy máy tính sẽ đưa ra lời cảnh báo sau)
Máy đưa ra cảnh báo: warning C4244: '=' : conversion from 'double' to 'float', possible loss of data
Ví dụ

Kiểu Ví dụ Hoạt động

int 2+3 int 2 + int 3  int 5


double 2.2 + 3.3 double 2.2 + double 3.3  double 5.5
mix (trộn) 2 + 3.3 int 2+ double 3.3 double 5.3
int 1/2 int 1/int2  int0
double 1.0/2.0 double 1.0/double 2.0 double0.5
mix 1/2.0 int 1/double 2.0
 double 1.0/double 2.0
 double 0.5.
Ví dụ:

#include<iostream>
using namespace std;
int main() {
float e;
e = 15/4; // int 15/int 4 = int 3
// Biểu thức cho kết quả đúng
e = 15.0/4.0;
cout<<"Gia tri cua e = "<<e<<endl;
return 0;
}
• Chú ý: Vế phải phải phù hợp với vế trái
Một số chú ý
• Muốn có giá trị chính xác trong phép chia 2 số nguyên cần dùng phép ép kiểu.
• Ví dụ:
int a = 5;int b =2; float c;
c = a/b; // c = 2.0 chuyen sang kieu ve trai tuc la c la (int)
c = ((float)a)/b;// luc nay a chuyen thanh float 5.0, b (int)  kiểu float
sau đó kết quả = 2.5 (float) và gán cho c = 2.5.
• Để đổi giá trị thực r sang giá trị nguyên, nên dùng: (int)(r+0.5)
• chú ý đến thứ tự ưu tiên: (int)1.4*10 = 1*10 = 10;
(int)(1.4*10)=(int)14.0=14. // () trước, sau (type)
• Cách viết ép kiểu sau là tương đương
int i;
float f = 3.14;
i = (int) f; // cach viet nay
i = int (f); // i = f; // i = 3;
// tuong duong cach viet tren nghia là dong ngoac khac nhau, nhung cung can than
Ví dụ

#include <iostream>
int main() {
int X = 200;
//Chuyen doi kieu theo cach cua C
long Y = (long) X;
//Chuyen doi kieu theo cach moi cua C++
long Z = long(X);
cout<< "X = "<<X<<"\n";
cout<< "Y = "<<Y<<"\n";
cout<< "Z = "<<Z<<"\n";
}
Ép kiểu
• static_cast <type-id> (expression )
Ví dụ:
• float afloat = 5.61;
• cout<<"static_cast<int>: "<<static_cast <int>(afloat)<<endl;
Toán tử - operator

int y; // cout<<“Gia tri cua y = ”<<y;


y = -3+6 * 3 - 2; =(-3 + 18 – 2) = 13.
1. Toán tử toán học. (+, -, *, /, %)
2. Toán tử logic. {AND (&&), OR (||), NOT(!)}.
3. Toán tử tăng và giảm (++, --)
4. Toán tử quan hệ. (==, !=, >, <, >=, <=)
5. Toán tử ép kiểu (cast operator). float(x), (int)x
6. Toán tử bitwise. (~, & (AND), ^ (XOR), | (OR), << dịch trái, >>)
7. Toán tử gán [=, +=, -=, *=, /=, %=, >>=, <<=, &=)
8. Hàm sizeof():
Chú ý: đến sự xuất hiện của nhiều toán hạng trong một biểu
thức và mức độ ưu tiên của chúng.
7. Toán tử (operator)

• Toán tử: là một ký hiệu (symbol) nói cho compiler thực hiện
thao tác toán học hoặc logic cụ thể.
• Biểu thức: là sự kết hợp các toán tử và toán hạng (biến hoặc
giá trị hằng) có thể được ước lượng để sinh ra một giá trị của
một kiểu nào đó.

• Ví dụ: 1 + 10 *5 // = 51;
int sum, number; sum + number;

• Để đánh giá đúng một biểu thức chứa nhiều toán tử: chúng ta
phải biết mỗi toán tử trong biểu thức đó thực hiện công việc
gì, và thứ tự mà chúng thực hiện.
7. Toán tử (operator)

• Độ ưu tiên của toán tử (operator precedence): là thứ tự thực


hiện các phép tính của một biểu thức kết hợp nhiều toán tử.
• Ví dụ:
biểu thức: 5 + 2 * 4 / 2, đánh giá lại biểu thức này dưới dạng 5
+ ((2 * 4) / 2) và kết quả là 9.
• Khi có 2 toán tử có cùng độ ưu tiên được đặt cạnh nhau trong
1 biểu thức, chúng ta sử dụng nguyên tắc kết hợp
(associativity rules) để biết được toán tử nào sẽ được thực
hiện trước.
a) Các phép toán số học
Operator Description Nghĩa Ví dụ
Toán tử Miêu tả

+ addition Cộng x =1; y=5; z = x+y; : out z = 6

- subtraction Trừ z = y – x; output: z = 4

* multiplication Nhân z = x*y; output: z = 5

/ division Chia z = y/x; output: z = 5

% modulo Lấy phần dư z = 5%2; output: z = 1

x = 3; y = ++x; x = 3; y = x++;
Tăng (viết tắt) //x =x+3 // x= x+3, // x = 4, y =
++ Increment (thêm điền tố - // x=4, y=4 3
hậu tố) x tăng rồi gán cho biến y y gán bằng 3 xong,
x tăng sau: x = 4.
x = 3; x = 3;
y = --x;//x =x-3 y = x--; // x= x-3
-- Decrement Giảm (viết tắt) // x=2, y=2 // x = 2, y = 3
x giảm trước rồi gán cho y gán bằng 3 xong,
biến y x gảm sau: x = 2.
Toán tử tăng/giảm (++/--)

Toán tử ví dụ Kết quả


++ x++; ++x; tăng lên 1
giống: x += 1;
-- x--; --x; giảm đi 1;
giống x-= 1;

++var : tăng biến var lên 1, sau đó sử dụng biến mới;


y = ++x; Tương đương: x = x +1; y = x;
--var: giảm biến var đi một; sau đó sử dụng biến mới;
var++: sử dụng giá trị biến cũ của var, sau đó tăng lên 1;
var--: sử dụng giá trị biến cũ của var, sau đó giảm đi 1.
y = x--; tương đương: y = x; x = x – 1;
Ví dụ: ý nghĩa của i++, ++i (i++  i= i+1)

• Trường hợp: i++ (gán, tăng) tương đương


int i = 0, x;
x = i; int j = 0, y;
i = i +1; y = j++;
Kết quả: j, i = 1; và y, x = 0;
• Trường hợp: ++i (tăng, gán) tương đương
int i = 0, x;
i = i +1; int j = 0, y;
y = ++j;
x = i;
Kết quả: j, i = 1; và y, x = 1;
• Tương tự cho i--, --i.
Toán tử gán (=) kết hợp

Toán tử Cách sử dụng Miêu tả Ví dụ


= var = biểu thức Gán giá trị
bên trái cho
bên phải x = 5;
+= var+=biểu thức var = var + expr x+= 5; (x = x+5;)
-= var -= expr var = var – expr x-=5; (x = x – 5;)
*= var*=expr var = var*expr x*=5; (x=x*5;)
/= var/=expr var = var/expr x /=5;(x=x/5;)
%= var%=expr var = var%expr x%=5; (x=x%5;)
Ví dụ

a) Chương trình sau in kết quả bằng bao nhiêu


float x = 5, product = 5;
product *= x++;
cout<<product<<endl;
ĐS: 25
b) Chương trình sau in kết quả bằng bao nhiêu
float x = 5, product = 5;
product *= ++x;
cout<<product<<endl;
ĐS: 30
b) Thứ tự ưu tiên của toán tử toán học

Cao nhất ++ -- Thực hiện tăng x trước rồi gán cho y

- (âm)

* / %

Thấp nhất + -

• int y; // cout<<“Gia tri cua y = ”<<y;


• y = -3 + 6 * 3 - 2; =(-3 + 18 – 2) = 13.
4 2 1 3

• y = 3 +4 % 5 – 6; = 3+ (4%5)-6 = 3 + (dư) 4 – 6 = 1
• y = -4 *3 % -6/5 = (-4*3)%(-6/5) = (-12)%(-1.2)= 10 dư 0
• y = (7 + 6) % 5 / 2 = 13%5/2 = 13%2.5 = (13/2 = 6 dư 1) (int)
b) toán tử quan hệ và so sánh
operator description Ví dụ

== Equal to (7 == 5) // evaluates to false

!= Not equal to (3 != 2) // evaluates to true

< Less than (5 < 5) // evaluates to false

> Greater than (5 > 4) // evaluates to true

<= Less than or equal to

>= Greater than or equal to (6 >= 6) // evaluates to true

Cao nhất > >= < <=

Thấp nhất == !=
c) Toán tử logic (Logical operators ( !, &&, || ))

a b a&&b (a and b) a||b (a OR b) !a (NOT p)

0 0 0 0 1

0 1 0 1 1

1 1 1 1 0

1 0 0 1 0

Cao nhất ! Logic

>>= <<= Quan hệ

== != Quan hệ

&& Logic

Thấp nhất || Logic


Toán tử xử lý tới bít (bitwise) (&, |, ^, ~, <<, >>)

operator asm equivalent description


& AND Bitwise AND
| OR Bitwise inclusive OR
^ XOR Bitwise exclusive OR
~ NOT Unary complement (bit inversion)
<< SHL Shift bits left
>> SHR Shift bits right

a b a&b a|b a^b ~a

0 0 0 0 0 1

0 1 0 1 1 1

1 0 0 1 1 0

1 1 1 1 0 0
Ví dụ

unsigned char a=195; // 1 byte giá trị 0 255


unsigned char b=87;
unsigned char c;
c=a&b; // = 67
Dịch bit bên trái và phải (<<, >>)

• Phép dịch trái (Shl): x << i cho giá trị nhận được từ số nguyên
x sau khi dịch số đó qua trái i bit.
• Quy tắc: Muốn nhân 1 số với 2 ta dịch số đó qua trái 1 bit.
Tổng quát, muốn nhân một số nguyên với 2^i ta dịch số đó
qua trái i bit;
• x << i = x*n; (với n=2^i), (dịch phải: x>>I = x/n)
• Ví dụ:
• char x, y; // int x,y;
• x = 19; //x=00010011//
• y = x << 2; //y=01001100 = x*(22=4)=76// do là kiểu char
• cout<<y; // output L (tra bảng ASCII) (y = x>>2; = 19/(2^2) = 4
Thứ tự ưu tiên của các phép toán
Level Precedence group Operator Description Grouping
1 Scope :: scope qualifier Left-to-right
++ -- postfix increment / decrement
() functional forms
2 Postfix (unary) Left-to-right
[] subscript
. -> member access
++ -- prefix increment / decrement
~! bitwise NOT / logical NOT
+- unary prefix
3 Prefix (unary) &* reference / dereference Right-to-left
new delete allocation / deallocation
sizeof parameter pack
(type) C-style type-casting
4 Pointer-to-member .* ->* access pointer Left-to-right
5 Arithmetic: scaling */% multiply, divide, modulo Left-to-right
Tiếp
6 Arithmetic: addition +- addition, subtraction Left-to-right
7 Bitwise shift << >> shift left, shift right Left-to-right
8 Relational < > <= >= comparison operators Left-to-right
9 Equality == != equality / inequality Left-to-right
10 And & bitwise AND Left-to-right
11 Exclusive or ^ bitwise XOR Left-to-right
12 Inclusive or | bitwise OR Left-to-right
13 Conjunction && logical AND Left-to-right
14 Disjunction || logical OR Left-to-right

= *= /= %= += -= assignment / compound
Assignment-level >>= <<= &= ^= |= assignment
15 Right-to-left
expressions
?: conditional operator
16 Sequencing , comma separator Left-to-right
Giải thích
• Các phép toán trên cùng một dòng có cùng thứ tự ưu tiên, các phép
toán hàng trên có thứ tự ưu tiên cao hơn các phép toán hàng dưới.
• Các phép toán cùng mức ứu tiên thì trình tự tính toán có thể từ trái
sang phải hay ngược lại
Ví dụ: *--px = *(--px) (phải qua trái)
• Để viết biểu thức một cách chính xác nên dụng các dấu ngoặc tròn.
 Khoảng trống và ngoặc
• Biểu thức có thể có dấu tab và khoảng trống để dễ đọc hơn.
• Sử dụng khoảng cách hoặc thêm các ngoặc tròn không gây lỗi và
làm chương trình chậm hơn.
x = y/3-34*temp&127 viết thành x = (y/3) – ((34*temp) & 127)
x=10/y*(127/x); có thể viết x = 10 / y * (127/x);
• Cho phép viết: x-- - --x hoặc (x--) – (--x) không cho viết x-----x
x++ + ++x hoặc (x++) + (++x) không cho viết x+++++x
Toán tử điều kiện tổ hợp bộ 3 (?) (toán tử điều kiện)
• Cú pháp: condition ? result1: result2
• Nếu điều kiện (condition) là true, toàn bộ biểu thức được gán
giá trị result1 và trái lại là result2.
• Ví dụ:
int main () {
int a,b,c;
a = 5;
b = 7;
c = (a>b) ? a : b; // (a<b) ? a : b; // ket qua = ?
cout << c << '\n';
} output: 7
Tìm min, max: của hai số
Toán tử sizeof:
• Cho kích cỡ (theo byte) của một kiểu dữ liệu.
Chương trình đưa ra kích cỡ chính xác kiểu dữ liệu trên máy tính của
bạn.
int main() {
cout << "Kich co cua char la: " << sizeof(char) << “byte”<< endl;
cout << "Kich co cua int la: " << sizeof(int) << “byte”<< endl;
cout << "Kich co cua short int la: " << sizeof(short int) << “byte”<< endl;
cout << "Kich co cua long int la: " << sizeof(long int) << “byte”<< endl;
cout << "Kich co cua float la: " << sizeof(float) << “byte” << endl;
cout << "Kich co cua double la: " << sizeof(double) << “byte” << endl;
cout << "Kich co cua wchar_t la: " << sizeof(wchar_t) << “byte” << endl;
return 0;}
Output:
Kich co cua char la: 1 byte
Kich co cua int la: 4 byte
Kich co cua short int la: 2 byte
Kich co cua long int la: 4 byte
Kich co cua float la: 4 byte
Kich co cua double la: 8 byte
Kich co cua wchar_t la: 4 byte
Giới thiệu xâu ký tự (string)

• Các kiểu cơ sở biểu diễn hầu hết // my first string


kiểu cơ bản kết nối với máy #include <iostream>
trong đó mã nguồn có thể chạy #include <string>
được (int, float, char, double... using namespace std;
• Điểm mạnh chính của C++ là:
giàu tập hợp kiểu kết hợp int main ()
{
• Ví dụ kiểu kết hợp (compound)
string mystring;
là: lớp string. Các biến của kiểu
mystring = "This is a string";
lưu trữ một chuỗi ký tự như là
cout << mystring;
một từ hoặc một câu.
return 0;
• Chương trình cần phải thêm vào }
head file include <string>
Giới thiệu xâu ký tự (string)
• Khởi tạo bất kỳ xâu ký tự hợp lệ #include <iostream>
nào: giống như kiểu số (3 kiểu). #include <string>
using namespace std;
string mystring = "This is a string";
string mystring ("This is a string"); int main ()
{
string mystring {"This is a string"};
string mystring;
• Kiểu xâu (string) có thể thực hiện mystring = "This is the initial string
toàn bộ các thao tác cơ bản của content";
các biến cơ sở, giống như khai cout << mystring << endl;
mystring = "This is a different string
báo không cần giá trị khởi tạo ban content";
đầu, và thay đổi giá trị trong suốt cout << mystring << endl;
quá trình chạy return 0;
}
Giới thiệu xâu ký tự (string)

• Chú ý : chèn ký tự điều khiển endl (ends the line) (in một ký tự
xuống dòng (newline) và làm sạch stream) (Xem Tuần 5 –
celog)
• Lớp string là một kiểu kết hợp. Sử dụng giống như kiểu cơ
bản: cùng cú pháp được sử dụng để khai báo biến và khởi tạo
ban đầu.
• Một số hàm cơ bản liên quan đến string
• http://www.cplusplus.com/reference/string/string/
• example
Mở rộng: Kiểu suy diễn - auto và decltype

• Khi biến mới được khởi động, compiler sẽ chỉ ra kiểu của biến một
cách tự động bằng giá trị khởi tạo. Đối với mục đích này, để đáp
ứng nhu cầu sử dụng auto như là kiểu định biến.
int foo = 0;
auto bar = foo; // the same as: int bar = foo;
• Ở đây bar được khai báo kiểu auto, kết quả là kiểu của bar là kiểu
của giá trị được sử dụng khởi đầu của biến, trong trường hợp này
nó sử dụng kiểu của foo, kiểu int.
• Các biến không có kiểu khởi tạo ban đầu cũng có thể sử dụng kiểu
suy diễn với khai báo decltype
int foo = 0;
decltype(foo) bar; // the same as: int bar;
• Ở đây bar được khai báo có kiểu giống như foo.
Mở rộng: Kiểu suy diễn - auto và decltype

• auto và decltype là: một thuộc tính mạnh gần đây được thêm
vào ngôn ngữ. Nhưng thuộc tính suy diễn kiểu chúng giới
thiệu phương pháp sử dụng trong trường hợp nâng cao khả
năng dễ đọc và trong trường hợp kiểu không thể nhận được
bằng phương pháp khác.

auto decltype
int foo = 0; int foo = 0;
// the same as: int bar = foo; // the same as: int bar;
auto bar = foo; decltype(foo) bar;
Bảng mã ASCII

• Bộ ký tự ASCII gồm 256 ký tự được phân bố như sau:


+ 32 ký tự đầu tiên là: các ký tự điều khiển không in được
như ký tự Enter (mã 13), ký tự ESC (mã 27).
+ Các mã ASCII 32-47, 58-64, 91-96 và 123-127 là các ký tự
đặc biệt như dấu chấm, dấu phẩy, dấu cách, dấu ngoặc, dấu
móc, dấu hỏi,...
+ Các mã ASCII 48-57 là 10 chữ số
+ Các mã ASCII 65-90 là các chữ cái hoa từ A đến Z
+ Các mã ASCII 97-122 là các chữ cái thường từ a đến z
+ Các mã ASCII 128-255 là các ký tự đồ hoạ.
Bảng mã ASCII (STT – Mã – Ký tự)
Ví dụ: in bảng mã ASCII – hệ 16
#include<iostream>
#include<stdlib.h>
cout<<"Ma <stt> trong bang ASCII"<<"Ky tu 0-128"<<endl;
for(int i = 0;i<128;i++)
{
cout.setf(ios::dec);
cout<<i<<" : ";
cout.setf(ios::hex);
cout<<hex<<i<<" : "<<char(i)<<endl;
}
Nhập/in một ký tự ra màn hình và tìm số thứ tự trong
bảng mã ASCII
char ch;
cout<<"Nhap mot ky tu tu ban phim: ";
cin>>ch;
cout<<"Ky tu vua nhap la: "<<ch<<endl; // in ra man hinh
// ep kieu// hoac int(ch)
cout<<"Ky tu nay co so thu tu (ma) trong bang ASCII la: "<< (int)ch;
cout<<endl;

• Output: a
• 97
Bảng mã ASCII

• Lưu ý: Chữ thường có mã ASCII lớn hơn 32 so với chữ hoa


tương ứng. Ví dụ mã ASCII của a là 97 còn mã ASCII của A là
65. (97-32 = 65)
• In chữ hoa ra màn hình
char ch = 'a';
for (int i = 65; i<90;++i) {
cout<<char(i)<<endl; // In chu hoa A - Z
}
cout<<"Chuyen a sang chu A hoa la: "<<char(ch-32)<<endl;
// (97 -32)= 65
Hàm số ngẫu nhiên rand():

• rand(): (032767), # include< cstdlib >


• RAND_MAX: hằng số mặc định RAND_MAX = 32767.
• srand(time(0)): sử dụng thời gian hiện tại làm hạt giống để tạo
số ngẫu nhiên.
• Tạo số ngẫu nhiên trong một khoảng [a, b]:
rand() % (b – a + 1) + a.
• Để tạo các số nguyên trong khoảng từ (0,5) chúng ta sử dụng
toán tử % với rand() như sau: rand()%6.
• Bài tập: Viết chương trình in ra 3 số nguyên/thực ngẫu nhiên
trong khoảng từ (0 5)
Macro constants <climits> (limits.h)
http://www.cplusplus.com/reference/climits/

CHAR_BIT, SCHAR_MIN, SCHAR_MAX, UCHAR_MAX, CHAR_MIN,


CHAR_MAX, MB_LEN_MAX, SHRT_MIN, SHRT_MAX, USHRT_MAX,
UINT_MAX, LONG_MIN, LONG_MAX, ULONG_MAX

Minimum value for an


INT_MIN -32767 (-215+1) or less*
object of type int

Maximum value for an


INT_MAX 32767 (215-1) or greater*
object of type int
Minimum value for -
LLONG_MIN an object of 92233720368547758
type long long int 07 (-263+1) or less*
Maximum value for
92233720368547758
LLONG_MAX an object of
07 (263-1) or greater*
type long long int
Maximum value for
18446744073709551
an object of
ULLONG_MAX 615 (264-1) or
type unsigned long
greater*
long int

You might also like