CHNG 12 Chng 2 BIU THC Expressions 1
CHƯƠNG 12 Chương 2 BIỂU THỨC (Expressions) 1
2. Kiểu dữ liệu(Data type) q Dữ liệu (data) là tất cả những gì được máy tính xử lý. Xét về phương diện điện tử thì máy tính chỉ hiểu các thông tin biểu diễn dưới dạng mã nhị phân. q Về phương diện ngôn ngữ bậc cao thì dữ liệu đã được khái quát hóa thành các kiểu dữ liệu và ta không cần quan tâm đến biểu diễn chi tiết trong máy tính của các kiểu dữ liệu. q Một ngôn ngữ lập trình khác nhau sẽ có kiểu dữ liệu và cú pháp khác nhau. 2
2. Kiểu dữ liệu(Data type) -tt Trong một ngôn ngữ lập trình, một dữ liệu bao giờ cũng thuộc về một kiểu dữ liệu nhất định. Các thuộc tính của một kiểu dữ liệu bao gồm: Tên kiểu dữ liệu. Miền giá trị. Kích thước lưu trữ. Tập các phép toán tác động lên kiểu dữ liệu. 3
2. Kiểu dữ liệu(Data type) -tt q. Các kiểu dữ liệu cơ sở: − Ký tự − Số nguyên − Số thực − Kiểu liệt kê q. Kích thước và phạm vi của những kiểu dữ liệu này có thể thay đổi tùy theo loại CPU và trình biên dịch. 4
2. 1. Kiểu số nguyên Ghi chú Từ khóa Phạm vi char -128 127 Kích thước 1 byte int -32768 32767 2 bytes Số nguyên short int -32768 32767 2 bytes long 4 bytes unsigned char -2147483648 2147483647 0 255 Số nguyên ngắn. Có thể viết tắt là short. Số nguyên dài unsigned int 0 65535 2 bytes unsigned long 0 4294967295 4 bytes 1 byte Có thể dùng như số nguyên 1 byte có dấu hoặc kiểu kí tự. Số nguyên 1 byte không dấu hoặc kí tự Có thể gọi tắt là unsigned. 5
Cách biểu diễn số nguyên dưới dạng số Hexa Ngoài cách viết dưới dạng thập phân, C++ còn quy ước cho phép viết số nguyên dưới dạng số bát phân (hệ đếm 8) bằng cách thêm 0 đầu, hoặc dưới dạng thập lục phân (hệ đếm 16) bằng cách thêm 0 x. Ví dụ Giá trị thập phân Dưới hệ bát phân Dưới hệ thập lục phân 198 0360 0 x. C 6 Cách viết theo hệ 8 hoặc hệ 16 thường tạo thuận lợi cho những người lập trình hệ thống. 6
Hằng số nguyên có định trước kiểu Đôi lúc chúng ta muốn ghi các hằng số với kiểu được định trước một cách tường minh để đảm bảo độ chính xác bằng cách ghi thêm một kí tự vào cuối dãy số: L cho kiểu long, U cho kiểu unsigned int và UL cho kiểu unsigned long. Ví dụ: • 52000 U hằng số nguyên theo kiểu unsigned int. • 123456789 L hằng số nguyên theo kiểu long. • 012345 L hằng số nguyên viết dưới dạng số hệ 8, kiểu long. 7
Ghi chú Khi thực hiện các phép tính trên số nguyên, cần hết sức thận trọng xem các phép toán đó có cho kết quả vượt quá phạm vi biểu diễn của nó không. Chẳng hạn, với a và b là dữ liệu kiểu int, khi đó hai câu lệnh sau: a = 80; b = (a*500)/200; cho kết quả sai giá trị của b, vì a*500 = 40000 vượt quá phạm vi của int. Tuy nhiên ta có thể viết: b = (a*500 L)/200; 8
2. 2. Kiểu số thực • Một giá trị kiểu số thực là một phần tử của tập các số thực mà ta có thể biểu diễn được trên máy. • Có hai cách ghi hằng số thực: Cách 1: Dạng viết thập phân bình thường, trong đó dấu phẩy được thay bằng dấu chấm: 2. 12; 4. 0; -125. 09; 235. 55 Cách 1: Dạng viết có phần mũ hay còn gọi dạng viết khoa học. Gồm hai phần: phần định trị và phần mũ viết sau chữ E để biểu diễn số mũ của cơ số 10. 9
Ví dụ • 627. 12345 = 6. 2712345*102 sẽ được viết lại cho máy tính là: 6. 2712345 E+02 Phần định trị Phần mũ • -0. 001234 = -1. 234*10 -3 được viết là -1. 234 E-03 Lưu ý: Phần định trị và phần mũ đều có thể có dấu đi kèm, chúng được viết liền nhau, không có dấu cách ở giữa. 10
Trong C++ cho phép sử dụng các kiểu số thực sau: Từ khóa Phạm vi float 3. 4 E-38 3. 4 E 38 1. 7 E-308 1. 7 E 308 3. 4 E-4932 1. 1 E 4932 double Ghi chú Kích thước 4 bytes Độ chính xác khoản 7 chữ số 8 bytes Độ chính xác khoản 15 chữ số 10 bytes Độ chính xác khoản 19 chữ số long double Lưu ý: Cột phạm vi giá trị chỉ miền biến thiên trị tuyệt đối của số. Chẳng hạn với số x kiểu float thì x có trị tuyệt đối nằm trong khoảng từ 3. 4*10 -38 đến 3. 4*1038. Nếu > 3. 4*1038 thì không biểu diễn x trong máy được, còn nếu < 3. 4*10 -38 thì 11 x được coi là bằng không.
Cách viết đúng các hằng số thực • 4. không cần phần lẻ sau dấu chấm • 3 E-6 không cần dấu chấm ở phần định trị nếu có phần mũ • 5. 7 viết bình thường • . 2152 không cần số 0 đầu tiên • 0. 02 e-3 chấp nhận dùng chữ e 12
Bảng tóm tắt các Kiểu dữ liệu (Data type) 13
3. Định danh (Identifier Name) q. Trong C/C++, tên biến, hằng, hàm, … được gọi là định danh q. Những định danh này có thể là 1 hoặc nhiều ký tự. Ký tự đầu tiên phải là một chữ cái hoặc dấu _ (underscore), những ký tự theo sau phải là chữ cái, chữ số, hoặc dấu _ q. C/C++ phân biệt ký tự HOA và thường. qĐịnh danh không được trùng với từ khóa (keywords). 14
4. Từ khóa (keywords) q. Là những từ được dành riêng bởi ngôn ngữ lập trình cho những mục đích riêng của nó q. Tất cả các từ khóa trong C/C++ đều là chữ thường (lowercase). q. Danh sách các từ khóa trong C/C++ 15
Câu lệnh q Nhằm ra lệnh cho máy thực hiện; q Mỗi câu lệnh sẽ có cú pháp và ý nghĩa riêng; q Lệnh được kết thúc bằng “ ; “ (không phải hết 1 dòng) q C++ chia các câu lệnh thành ba loại: Ø lệnh biểu thức, Ø lệnh kép (compound statement) Ø lệnh điều khiển. 16
Câu lệnh biểu thức Bao gồm một biểu thức đơn giản và theo sau là dấu chấm phẩy. Các biểu thức có thể là mối quan hệ giữa các phép toán, gọi hàm hoặc chỉ có dấu chấm phẩy. Chẳng hạn, ta có các lệnh biểu thức sau: [1] x = 2*y – 7. 4; [2] cout << “Hello. ”; [3] int. Result=Test(n); [n] ; 17
Câu lệnh khối • Lệnh kép bao gồm một số lệnh riêng lẻ được gói trong cặp dấu { … }. Những lệnh riêng lẻ này có thể là lệnh biểu thức, lệnh kép hay lệnh điều khiển. Khác với lệnh biểu thức, lệnh kép không được kết thúc bởi dấu chấm phẩy. Chẳng hạn: { } r = 2. 5; dt = M_PI*r*r; cout<< “Diện tích hình tròn là: “<<dt<< endl; 18
Câu lệnh điều khiển Lệnh điều khiển bao gồm các câu lệnh như: 1. Lệnh rẽ nhánh: if 2. Lệnh Lựa chọn: switch 3. Lệnh lặp: for, while, do… while (Phần này sẽ giải thích rõ trong chương 3) 19
Câu lệnh Gán q. Phép gán: dấu “=“ dùng để gán giá trị của một biểu thức cho một biến đã được khai báo. q. Cú pháp của lệnh gán: <tên biến> = <biểu thức>; Ý nghĩa: Đầu tiên máy tính trị của biểu thức vế phải, sau đó gán giá trị tính được cho tên biến ở vế trái. 20
Ý nghĩa Câu lệnh Gán q Vế trái của phép gán chỉ và chỉ có thể là một biến hoặc là giá trị dạng một địa chỉ ô nhớ. q Có thể sử dụng phép gán kép: a = b = c = 5; // gán giá trị 5 cho cả 3 biến a, b, c. a = 2 + (b = 5); /* gọi là lệnh gán dây chuyền; tương đương với b = 5; a = 2 + b; */ 21
5. Biến (Variables) q. Biến là định danh của một vùng trong bộ nhớ dùng để giữ một giá trị mà có thể bị thay đổi bởi chương trình. q. Tất cả biến phải được khai báo trước khi sử dụng. 22
Cách khai báo type variable. Names; − type: là một trong các kiểu dữ liệu hợp lệ. − variable. Names: tên của một hay nhiều biến phân cách nhau bởi dấu phẩy. 23
Khởi tạo Biến Ngoài ra, ta có thể vừa khai báo vừa khởi tạo giá trị ban đầu cho biến: type var. Name 1=value, . . . , var. Name_n = value; Ví dụ: float mark 1, mark 2, mark 3, average = 0; 24
Ý nghĩa của Biến q. Việc khai báo biến nhằm ba công việc chính: ü dành vùng bộ nhớ để sử dụng ü đặt tên vùng đó bởi một tên gọi ü qui định kiểu dữ liệu cho biến. q. Ngay trên dòng khai báo ta có thể gán cho biến một giá trị. Việc làm này gọi là khởi đầu cho biến. 25
Phạm vi của biến q. Biến cục bộ (local variables) • Là những biến được định nghĩa ở trong một hàm hoặc một khối lệnh. • Được cấp phát bộ nhớ tự động (Auto) • Tồn tại (life time) từ khi định nghĩa cho đến khi kết thúc hàm hoặc khối lệnh 26
Ví dụ void func 1(void) { int x 1; x = 10; } void func 2(void) { int x 2; x 2 = -199; X 1=10; x là biến cục bộ ( x trong func 1 khác x trong func 2 ) } 27
int sum(int from, int to) { int total=0; for(int i=from ; i<=to ; i++) total +=i; return total; } Biến cục bộ 28
Phạm vi của biến q Biến toàn cục (global variables) • Là những biến được định nghĩa ở ngoài tất cả các hàm. • Được cấp phát bộ nhớ tự động (Auto) • Tồn tại (life time) từ khi định nghĩa cho đến khi kết thúc chương trình • Biến toàn cục có thể được truy xuất mọi nơi trong chương trình • Không gian bộ nhớ cho các biến toàn cục được dành riêng trước khi sự thực hiện của chương trình bắt đầu, nhưng ngược lại không gian bộ nhớ cho các biến cục bộ được cấp phát ở thời điểm thực hiện chương trình. 29
Ví dụ #include <iostream. h> int g. Var = 100; void increase() ; // prototype Biến toàn cục void main() { cout << “Value of g. Var= “ << g. Var; increase(); cout << “After decreased, g. Var= “ << g. Var; } Truy xuất void increase() { biến global g. Var = g. Var + 1; } 30
7. Từ khóa const q. Hằng là một đại lượng có giá trị không thay đổi trong chương trình. q. Thông thường ta dùng chữ HOA để đặt tên cho hằng. Ví dụ: const int. MAX = 200; 31
Ví dụ: q. Hằng ký tự được đặt trong cặp nháy đơn. Ví dụ: ‘a’ q. Hằng nguyên Ví dụ 100 -50 32
Hằng số thực • Hằng số thực yêu cầu một dấu chấm phân cách phần nguyên và phần thập phân. Ví dụ: 123. 45 • Cách viết một số loại hằng số 33
8. Hằng chuỗi ký tự (string constants) q. Hằng chuỗi ký tự là một tập các ký tự đặt trong cặp nháy kép “”. Ví dụ: • "This is a string" //là một chuỗi. • ‘a’ //là một hằng ký tự. • “a” //là một hằng chuỗi. 34
Hằng ký tự đặc biệt (escape sequences) 35
Ví dụ #include <iostream. h> int main() { cout <<"Items: n"; cout <<”t. Item 1n”; cout <<”t. Item 2n”; cout <<”t. Item 3n”; return 0; } 36
10. Toán tử (operators) Toán tử gán (assignment operator) variable. Name = expression; Với: − variable. Name: Tên biến − expression: Biểu thức Lưu ý: phía bên trái dấu = phải là một biến hay con trỏ và không thể là hàm hay hằng. Ví dụ: total = a + b + c + d; 37
11. Chuyển đổi kiểu trong câu lệnh gán • Vế phải và vế trái của lệnh gán phải cùng kiểu Ví dụ: int i=100; double d = 123. 456; • Nếu thực thi lệnh i = d; thì i = 123 (chuyển đổi kiểu mất mát thông tin). • Nếu thực thi lệnh d = i; thì d =100. 0 (chuyển đổi kiểu không mất mát thông tin). 38
11. Chuyển đổi kiểu trong câu lệnh gán -tt • Khi chuyển đổi từ kiểu dữ liệu có miền giá trị nhỏ sang kiểu dữ liệu có miền giá trị lớn hơn: char int long float double, thì việc chuyển đổi kiểu này là không mất mát thông tin • Khi chuyển đổi từ kiểu dữ liệu có miền giá trị lớn sang kiểu dữ liệu có miền giá trị nhỏ hơn: double float long int char, thì việc chuyển đổi kiểu này là mất mát thông tin 39
12. Toán tử số học (Arithmetic operators) Toán tử Tên Ví dụ + Cộng 12 + 4. 9 // kết quả 16. 9 - Trừ 3. 98 - 4 // kết quả -0. 02 * Nhân 2 * 3. 4 // kết quả 6. 8 / Chia 9 / 2. 0 // kết quả 4. 5 % Lấy phần dư 13 % 3 // kết quả 1 40
12. Toán tử số học (arithmetic operators) –tt q. Khi tử số và mẫu số của phép chia là số nguyên thì đó là phép chia nguyên nên phần dư của phép chia nguyên bị cắt bỏ. Ví dụ: 5/2 cho kết quả là 2. q. Toán tử lấy phần dư % (modulus operator) chỉ áp dụng với số nguyên. 41
13. Toán tử gán phức hợp Toán Tử Ví dụ Tương đương với += n += 25 n = n + 25 -= n -= 25 n = n – 25 *= n *= 25 n = n * 25 /= n /= 25 n = n / 25 %= n %= 25 n = n % 25 42
Ví dụ #include <iostream. h> int main() { int a, b=3; a = b; a+=2; // tương đương với a=a+2 cout << a; return 0; 43 }
14. Toán tử ++ và -- (increment and decrement operators) Toán tử tăng (++) và toán tử giảm (--) có tác dụng làm tăng hoặc giảm 1 giá trị lưu trong biến. Ví dụ: a++; //tương đương với a+=1; và a=a+1 a--; //tương đương với a-=1; và a=a-1 44
Tiền tố (prefix) Toán tử ++/-- đặt trước toán hạng, hành động tăng/giảm trên toán hạng được thực hiện trước, sau đó giá trị mới của toán hạng sẽ tham gia định trị của biểu thức. Ví dụ: b=3; a=++b; Kết quả: a chứa giá trị 4, b chứa giá trị 4 45
Hậu tố (postfix) Toán tử ++/-- đặt sau toán hạng, giá trị trong toán hạng được tăng/giảm sau khi đã tính toán. Ví dụ b=3; a=b++; Kết quả: a chứa giá trị 3, b chứa giá trị 4 46
Ví dụ int x = 100; int n, m; n = ++x + 1; // n sẽ có giá trị là 102 (1) n = x++ + 1; // n sẽ có giá trị là 101 (2) • Sau lệnh (1), (2) thì x có giá trị là 101 m = --x + 1; // m sẽ có giá trị là 100 (3) m = x-- + 1; // m sẽ có giá trị 101 (4) • Sau lệnh (3), (4) thì x có giá trị là 99 47
Độ ưu tiên • Khi các toán tử số học xuất hiện trong một biểu thức, thì độ ưu tiên thực hiện như sau: Toán tử ++ – – Độ ưu tiên 1 – (dấu âm) 2 * 3 / + % – 4 48
15. Toán tử quan hệ & luận lý (relational & logical operators) • Toán tử quan hệ được định trị là true hoặc false. Toán tử Tên Ví dụ == So sánh bằng 5 == 5 // kết quả 1 != So sánh không bằng 5 != 5 // kết quả 0 < So sánh nhỏ hơn 5 < 5. 5 // kết quả 1 <= So sánh nhỏ hơn hoặc bằng 5 <= 5 // kết quả 1 > So sánh lớn hơn 5 > 5. 5 // kết quả 0 >= So sánh lớn hơn hoặc bằng 6. 3 >= 5 //kết quả 1 49
15. Toán tử quan hệ & luận lý (relational & logical operators) -tt • Toán tử luận lý: Operator Action Ví dụ ! Not !(5 == 5) // kết quả là 0 && and 5 < 6 && 6 < 6// kết quả là 0 || or 5 < 6 || 6 < 5 // kết quả là 1 • Bảng chân trị: P 0 0 1 1 Q 0 1 P&&Q 0 0 0 1 P||Q 0 1 1 1 !P 1 1 0 500
Ví dụ biểu thức: (10>9 && 8!=7) || (6<=5 || 5>4) Được định trị như sau: 52
16. Toán tử ? (? operator) § Toán tử ? là một toán tử ba ngôi do đó phải có ba toán hạng. § Dạng tổng quát của toán tử ? là: Exp 1 ? Exp 2 : Exp 3; Với Exp 1, Exp 2, và Exp 3 là các biểu thức. § Ý nghĩa: 1. Nếu Exp 1 đúng thì Exp 2 được định trị và nó trở thành giá trị của biểu thức. 2. Ngược lại, nếu Exp 1 sai, Exp 3 được định trị và trở thành giá trị của biểu thức. 53
Ví dụ X = 10 Y = X > 9 ? 100*X : 200*X Vì X>9 là true nên giá trị của biểu thức sẽ là 1000. Vậy y sẽ có giá trị là 1000. Ví dụ: int m = 1, n = 2, p =3; int min =(m < n ? (m < p ? m : p) : (n < p ? n : p)); 54
17. Toán tử sizeof • sizeof là toán tử một ngôi mà trả về số byte của kiểu dữ liệu chiếm trong bộ nhớ. Tùy môi trường (hệ điều hành, loại CPU, . . . ) mà mỗi kiểu dữ liệu có số byte khác nhau. • Cú pháp: sizeof(operand) • operand có thể là tên kiểu dữ liệu, biến, biểu thức. 55
18. Toán tử dấu phẩy (comma operator) • Toán tử comma buộc các biểu thức cùng với nhau. • Biểu thức bên trái của toán tử comma luôn được định trị như void, biểu thức bên phải được định trị và trở thành giá trị của biểu thức. • Dạng tổng quát của toán tử comma: (exp_1, exp_2, . . . , exp_n) 56
Ví dụ • Các biểu thức được định trị từ trái sang phải, biểu thức cuối cùng (exp_n) được định trị và trở thành giá trị của toàn bộ biểu thức. • Ví dụ: x = (y=3, y+1); y được gán giá trị 3, sau đó x được gán giá trị y+1 là 4. 57
19. Độ ưu tiên của các toán tử 58
20. Biểu thức (expressions) • Một biểu thức trong C/C++ là sự kết hợp của các thành phần: toán tử, hằng, biến, và hàm có trả về giá trị. • Thứ tự định trị của biểu thức tùy thuộc vào độ ưu tiên của các toán tử. • Để biểu thức rõ ràng và thực hiện việc định trị đúng, nên dùng cặp dấu ngoặc tròn () bao quanh các biểu thức con của biểu thức. 59
Định trị biểu thức sau: Thứ tự định trị biểu thức result = x * y - z % 10 + w/2; 60
21. Chuyển kiểu trong biểu thức • Khi các hằng và biến của những kiểu khác nhau tồn tại trong một biểu thức, giá trị của chúng phải được chuyển thành cùng kiểu trước khi các phép toán giửa chúng được thực hiện. • Trình biên dịch sẽ thực hiện việc chuyển kiểu (convert) tự động đến kiểu của toán hạng có kiểu lớn nhất. Việc chuyển kiểu này gọi là thăng cấp kiểu (type promotion). 61
Ví dụ char ch; int i; float f; double d; 62
22. Ép kiểu (casting) • Casting dùng để ép kiểu của một biểu thức thành một kiểu theo ý muốn của lập trình viên. • Dạng tổng quát của casting là (type)expression Hoặc type(expression) (type là tên một kiểu dữ liệu hợp lệ). 63
Ví dụ float result; result = 7/2; • Do 7/2 là phép chia nguyên nên kết quả không có phần thập phân. • Sau lệnh trên result có giá trị là 3. Để phép chia trên là phép chia số thực ta thực hiện ép kiểu tử số hoặc mẫu số hoặc cả hai. 64
Các cách viết sau đây cho cùng kết quả: result = (float)7/2; result = 7/(float)2; result = (float)7/(float)2; result = float(7)/float(2); 65
- Slides: 65