Skip to content

L2. Các Toán Tử và Biểu Thức trong C++¤

Giải đáp bài cũ

double vs long double:

  • Phụ thuộc vào trình biên dịch và hệ điều hành
  • Kiểu double luôn là 8 bytes
  • Hệ điều hành x86: long double thường là 8 bytes
  • Hệ điều hành x64: long double có thể là 16 bytes

#define vs const:

  • #define: Khi biên dịch, tên hằng được thay thế bằng giá trị → Không cần bộ nhớ
  • const: Là biến hằng → Chiếm dung lượng trên bộ nhớ

5. Các Phép Toán¤

5.1. Toán Tử Gán (Assignment Operator)¤

Toán tử gán = dùng để gán giá trị cho một biến.

C++
int x = 10;        // Gán 10 cho biến x
int y = 10;
int x = y;         // Gán giá trị của y cho biến x

Truy vết thực thi:

C++
int a, b; 
a = 10;            // a = 10, b = ?
b = 4;             // a = 10, b = 4
a = b;             // a = 4, b = 4
b = 7;             // a = 4, b = 7

Gán nhiều biến:

C++
int x, y;
y = 2 + (x = 5);   // Tương đương: x = 5; y = 2 + x;

int x = y = z = 5; // Gán giá trị 5 cho 3 biến z, y, x

5.2. Toán Tử Toán Học (Arithmetic Operators)¤

Phép toán Ý nghĩa Ví dụ Kết quả
+ Cộng x = 11 + 3 14
- Trừ x = 11 - 3 8
* Nhân x = 11 * 3 33
/ Chia x = 11 / 3.0 3.666...
/ Lấy phần nguyên x = 11 / 3 3
% Lấy phần dư x = 11 % 3 2

Phép chia trong C++

Khi nào là phép chia?

  • Khi ít nhất một trong các đối số là số thực

Khi nào là phép lấy phần nguyên?

  • Khi tất cả các đối số đều là số nguyên
C++
float a = 5 / 2;       // a = 2 (chia nguyên, sau đó chuyển sang float)
float b = 5 / 2.;      // b = 2.5 (chia thực)
float c = 5. / 2;      // c = 2.5 (chia thực)
float d = (float)5/2;  // d = 2.5 (ép kiểu, sau đó chia thực)

Vấn đề thường gặp

1. Phép nhân (tràn kiểu dữ liệu):

C++
int a = 123456;
int b = 654321;
std::cout << a * b;  // Kết quả sai: 80779853376 (tràn số)

// Giải pháp: Ép kiểu
std::cout << (long long)a * b;  // Kết quả đúng

2. Phép chia (sai logic do chia nguyên):

C++
int a = 123456;
int b = 654321;
std::cout << a / b;  // Kết quả: 0 (chia nguyên)

// Giải pháp: Ép kiểu
std::cout << (float)a / b;  // Kết quả: 0.188678

5.3. Toán Tử Tăng/Giảm (+±-)¤

Dùng để tăng hoặc giảm 1 đơn vị:

C++
int a;
a = a + 1;   // Cách 1
a += 1;      // Cách 2
a++;         // Cách 3 (khuyến nghị)

Sự khác biệt giữa ++x và x++?

Tiền tố (++x - Pre-increment):

C++
int x = 5;
int y = ++x;
// Thực hiện:
// 1. ++x     → x = 6
// 2. y = x   → y = 6
// Kết quả: x = 6, y = 6

Hậu tố (x++ - Post-increment):

C++
int x = 5;
int y = x++;
// Thực hiện:
// 1. y = x   → y = 5
// 2. x++     → x = 6
// Kết quả: x = 6, y = 5

5.4. Toán Tử Phẩy (Comma Operator)¤

Các biểu thức cách nhau bằng dấu , được tính từ trái sang phải, kết quả là giá trị của biểu thức cuối cùng.

C++
int x = 0;
int y = 2;
int z = (++x, ++y);

// Thực hiện:
// 1. ++x    → x = 1
// 2. ++y    → y = 3
// 3. z = y  → z = 3
// Kết quả: x = 1, y = 3, z = 3

5.5. Toán Tử Toán Học & Gán (Compound Assignment)¤

Toán tử Ví dụ Tương đương Ý nghĩa
+= x += 5 x = x + 5 Cộng
-= x -= 5 x = x - 5 Trừ
*= x *= 5 x = x * 5 Nhân
/= x /= 5 x = x / 5 Chia/Lấy phần nguyên
%= x %= 5 x = x % 5 Lấy phần dư
<<= x <<= 5 x = x << 5 Dịch trái
>>= x >>= 5 x = x >> 5 Dịch phải
&= x &= 5 x = x & 5 AND
^= x ^= 5 x = x ^ 5 XOR
|= x |= 5 x = x | 5 OR

5.6. Toán Tử Bit (Bitwise Operators)¤

Bảng chân trị:

p q p & q (AND) p ^ q (XOR) p | q (OR) ~p (NOT)
0 0 0 0 0 1
0 1 0 1 1 1
1 0 0 1 1 0
1 1 1 0 1 0

Toán tử dịch bit:

C++
// Dịch trái (<<)
3 = 0011
3 << 1 = 0110 = 6
3 << 2 = 1100 = 12
3 << 3 = 1000 = 8

// Dịch phải (>>)
12 = 1100
12 >> 1 = 0110 = 6
12 >> 2 = 0011 = 3
12 >> 3 = 0001 = 1

Ví dụ toán tử trên bit:

C++
int main() {
    int a = 5;    // 0000 0000 0000 0101
    int b = 6;    // 0000 0000 0000 0110

    int z1 = a & b;   // 0000 0000 0000 0100 = 4
    int z2 = a | b;   // 0000 0000 0000 0111 = 7
    int z3 = a ^ b;   // 0000 0000 0000 0011 = 3
    int z4 = ~a;      // 1111 1111 1111 1010 = -6
    int z5 = a >> 2;  // 0000 0000 0000 0001 = 1
    int z6 = a << 2;  // 0000 0000 0001 0100 = 20

    return 0;
}

Ứng dụng của toán tử bit:

1. Kiểm tra chia hết cho 2:

C++
int number = 5;
if (number & 1 == true)
    std::cout << "So le\n";
else
    std::cout << "So chan\n";

// Tổng quát:
// a & 1  → a % 2
// a & 3  → a % 4
// a & 7  → a % 8

2. Tích và thương cho 2ⁿ:

C++
int a = 2 << 1;   // a = 2 * 2¹ → a = 4
int b = 2 << 2;   // b = 2 * 2² → b = 8
int c = 8 >> 1;   // c = 8 / 2¹ → c = 4
int d = 8 >> 2;   // d = 8 / 2² → d = 2

5.7. Toán Tử Điều Kiện (Ternary Operator)¤

Cú pháp:

C++
<điều_kiện> ? <biểu_thức_1> : <biểu_thức_2>

Ý nghĩa: Nếu điều kiện đúng thì thực hiện biểu_thức_1, ngược lại thực hiện biểu_thức_2.

C++
// Ví dụ 1: Tìm số lớn hơn
int a = 1;
int b = 2;
int c = (a > b) ? a : b;  // c = 2

// Ví dụ 2: Định nghĩa hằng có điều kiện
int so_sinh_vien = 55;
const int so_lop = (so_sinh_vien > 50) ? 2 : 1;  // so_lop = 2

Ứng dụng

Toán tử điều kiện hữu ích khi cần gán giá trị cho hằng số dựa trên điều kiện, vì câu lệnh if không thể sử dụng trong trường hợp này.

5.8. Toán Tử Quan Hệ (Relational Operators)¤

Toán tử Ký hiệu Ví dụ Giải thích
Lớn hơn > x > y Nếu x lớn hơn y → true (1), ngược lại → false (0)
Nhỏ hơn < x < y Nếu x nhỏ hơn y → true (1), ngược lại → false (0)
Lớn hơn hoặc bằng >= x >= y Nếu x ≥ y → true (1), ngược lại → false (0)
Nhỏ hơn hoặc bằng <= x <= y Nếu x ≤ y → true (1), ngược lại → false (0)
Bằng == x == y Nếu x = y → true (1), ngược lại → false (0)
Khác != x != y Nếu x ≠ y → true (1), ngược lại → false (0)

5.9. Toán Tử Luận Lý (Logical Operators)¤

Toán tử Ký hiệu Ví dụ
NOT ! !x
AND && x && y
OR || x || y

Bảng chân trị:

Giá trị 1 Giá trị 2 OR (||) AND (&&)
false false false false
false true true false
true false true false
true true true true

Bài tập:

C++
1. (true && true) || false              // true
2. (false && true) || true              // true
3. (false && true) || false || true     // true
4. (5 > 6 || 4 > 3) && (7 > 8)         // false
5. !(7 > 6 || 3 > 4)                   // false

5.10. Độ Ưu Tiên Toán Tử (Operator Precedence)¤

Mức độ Toán tử Nhóm ưu tiên
1 :: Trái → Phải
2 ++ -- () [] . -> Trái → Phải
3 ++ -- ~ ! + - & * new delete sizeof (type) Phải → Trái
4 .* ->* Trái → Phải
5 * / % Trái → Phải
6 + - Trái → Phải
7 << >> Trái → Phải
8 < > <= >= Trái → Phải
9 == != Trái → Phải
10 & Trái → Phải
11 ^ Trái → Phải
12 | Trái → Phải
13 && Trái → Phải
14 || Trái → Phải
15 = *= /= %= += -= >>= <<= &= ^= |= ?: Phải → Trái
16 , Trái → Phải

Bài tập:

C++
1. x = 3 + 4 + 5;
   // Giải: x = ((3 + 4) + 5);

2. x = y = z;
   // Giải: x = (y = z);

3. z *= ++y + 5;
   // Giải: z *= (++y) + 5;

4. a || b && c || d;
   // Giải: (a || (b && c)) || d;

Bài tập về các phép toán

Bài 1: Tính

  1. (5 > 3 && 4 < 8) → true
  2. (4 > 6 && true) → false
  3. (3 >= 3 || false) → true
  4. (true || false) ? 4 : 5 → 4

Bài 2: Tính

  1. 7 / 4 → 1 (chia nguyên)
  2. 14 % 5 → 4 (phần dư)
  3. 3 / 0 → Lỗi (chia cho 0)

6. Biểu Thức (Expression)¤

Định nghĩa: Biểu thức được tạo thành từ các toán tử (Operator) và các toán hạng (Operand).

  • Toán tử: Tác động lên các giá trị của toán hạng và cho giá trị có kiểu nhất định
  • Toán hạng: Hằng, biến, lời gọi hàm...

Ví dụ:

C++
int a = 2 + 3;
int b = a / 5;
int c = (a + b) * 5;
int d = (x >= 3);

Biểu thức kiểm tra điều kiện:

C++
// Biểu thức này kiểm tra gì?
(x >= 0) ^ (y < 0)
// Kiểm tra x và y có dấu khác nhau (một dương một âm)
C++
int year = 2000;
int month = 29;
if ((year % 4 != 0) || (year % 400 != 0)) 
    return 28;
// Kiểm tra năm nhuận

7. Nhập Xuất Dữ Liệu¤

7.1. Câu Lệnh Xuất¤

Có 2 cách xuất dữ liệu trong C++:

  • Cách 1: Sử dụng cout (C++)
  • Cách 2: Sử dụng printf (C)

Lựa chọn tùy thuộc vào lập trình viên.

7.2. Câu Lệnh Xuất cout (C++)¤

Thư viện:

C++
#include <iostream>

Cú pháp:

C++
std::cout << Tham_số_1 << Tham_số_2 << ... << Tham_số_k;

Tham số có thể là:

  • Văn bản thường (literal text)
  • Ký tự điều khiển (escape sequence)
  • Biến, hằng số, biểu thức, hàm

Ví dụ:

C++
int i = 10;
std::cout << "Chuong trinh xuat gia tri i\n";
std::cout << "gia tri la " << i;

Output:

Text Only
Chuong trinh xuat gia tri i
gia tri la 10

7.2.1. Xuất văn bản thường¤

Cú pháp:

C++
std::cout << "Chuoi can in";

Ví dụ:

C++
#include <iostream>

int main() {
    std::cout << "Chao ban! Toi co the giup gi khong?";
    std::cin.get();
    return 0;
}

Output:

Text Only
Chao ban! Toi co the giup gi khong?

7.2.2. Ký tự điều khiển (Escape Sequence)¤

Ký tự Ý nghĩa
\n Xuống dòng
\a Phát ra thông báo (beep)
\b Lùi con trỏ 1 vị trí
\t Dấu tab
\" In ký tự "
\\ In ký tự \

Ví dụ:

C++
#include <iostream>

int main() {
    std::cout << "Chao ban!\nToi co the giup gi khong?";
    std::cin.get();
    return 0;
}

Output:

Text Only
Chao ban!
Toi co the giup gi khong?

7.2.3. Thiết lập độ rộng khi xuất¤

Cú pháp:

C++
cout.width(n);  // n là độ rộng mới

Chú ý

Độ rộng quy định chỉ có tác dụng cho một giá trị xuất. Sau đó C++ lại áp dụng độ rộng mặc định bằng 0.

Ví dụ:

C++
#include <iostream>

int main() {
    int a = 1706;
    std::cout << a << "\n";
    std::cout.width(10);
    std::cout << a;
    std::cin.get();
    return 0;
}

Output:

Text Only
1706
      1706

7.2.4. Độ chính xác khi xuất¤

Cú pháp:

C++
cout.precision(n);  // n là độ chính xác áp dụng

Chú ý

Độ chính xác được thiết lập sẽ có hiệu lực cho tới khi gặp một câu lệnh thiết lập độ chính xác mới.

Ví dụ:

C++
#include <iostream>

int main() {
    float x = 176.859;
    std::cout << x << "\n";
    std::cout.precision(5);
    std::cout << x << "\n";
    std::cin.get();
    return 0;
}

Output:

Text Only
176.859
176.86

7.3. Câu Lệnh Xuất printf (C)¤

Thư viện:

C++
#include <stdio.h>  // standard input/output

Cú pháp:

C++
printf(<chuỗi định dạng>[, <đs1>, <đs2>, ...]);

Chuỗi định dạng gồm:

  • Văn bản thường (literal text)
  • Ký tự điều khiển (escape sequence)
  • Đặc tả (conversion specifier)

7.3.1. Đặc tả (Conversion Specifier)¤

Đặc tả Ý nghĩa Kiểu dữ liệu
%c Ký tự char
%d, %ld Số nguyên có dấu int, short, long
%f, %lf Số thực float, double
%s Chuỗi ký tự char[], char*
%u Số nguyên không dấu unsigned int/short/long

Ví dụ:

C++
int a = 10, b = 20;
printf("%d", a);           // Xuất ra 10
printf("%d", b);           // Xuất ra 20
printf("%d %d", a, b);     // Xuất ra 10 20

float x = 15.06;
printf("%f", x);           // Xuất ra 15.060000
printf("%f", 1.0/3);       // Xuất ra 0.333333

7.3.2. Định dạng xuất (printf)¤

Cú pháp:

  • Định dạng xuất số nguyên: %nd
  • Định dạng xuất số thực: %n.kf

Ví dụ:

C++
int a = 1706;
float x = 176.85;

printf("%10d", a);         //       1706
printf("\n");
printf("%10.2f", x);       //     176.85
printf("\n");
printf("%.2f", x);         // 176.85

Phối hợp các thành phần:

C++
int a = 1, b = 2;

// Cách dài dòng:
printf("%d", a);           // Xuất giá trị của a
printf(" cong ");          // Xuất chuỗi " cong "
printf("%d", b);           // Xuất giá trị của b
printf(" bang ");          // Xuất chuỗi " bang "
printf("%d", a + b);       // Xuất giá trị của a + b
printf("\n");              // Xuống dòng

// Cách ngắn gọn (khuyến nghị):
printf("%d cong %d bang %d\n", a, b, a + b);

7.4. Câu Lệnh Nhập¤

Có 2 cách nhập dữ liệu:

  • Cách 1: Sử dụng cin (C++)
  • Cách 2: Sử dụng scanf (C)

7.5. Câu Lệnh Nhập std::cin>> (C++)¤

Thư viện:

C++
#include <iostream>

Cú pháp:

C++
std::cin >> Tham_số_1 >> Tham_số_2 >> ... >> Tham_số_k;

Lưu ý

Tham số không có dạng chuỗi (không có dấu nháy kép).

Ví dụ:

C++
#include <iostream>

int main() {
    int nam_sinh = 0;  // Bước 1: Khai báo biến

    std::cout << "Nam sinh: ";  // Bước 2: Thông báo
    std::cin >> nam_sinh;       // Bước 3: Nhập giá trị

    std::cin.get();
    return 0;
}

Chương trình cộng 2 số nguyên:

C++
#include <iostream>

int main() {
    int a = 0, b = 0;

    std::cout << "Chuong trinh cong 2 so a, b" << "\n";
    std::cout << "a: ";
    std::cin >> a;
    std::cout << "b: ";
    std::cin >> b;
    std::cout << "a + b = " << a + b << "\n";

    std::cin.get();
    return 0;
}

Output:

Text Only
Chuong trinh cong 2 so a, b
a: 5
b: 6
a + b = 11

7.6. Câu Lệnh Nhập scanf (C)¤

Thư viện:

C++
#include <stdio.h>  // standard input/output

Cú pháp:

C++
scanf(<chuỗi định dạng>[, <&đs1>, <&đs2>, ...]);

  • <chuỗi định dạng>: Giống định dạng xuất nhưng chỉ có các đặc tả
  • Các đối số là tên các biến và bắt buộc đặt trước dấu &

Ví dụ:

C++
int a, b;

// Cách 1: Nhập từng biến
scanf("%d", &a);   // Nhập giá trị cho biến a
scanf("%d", &b);   // Nhập giá trị cho biến b

// Cách 2: Nhập nhiều biến (khuyến nghị)
scanf("%d%d", &a, &b);

Các lỗi thường gặp

C++
scanf("%d", a);              // SAI: Thiếu dấu &
scanf("%d", &a, &b);         // SAI: Thiếu %d cho biến b
scanf("%f", &a);             // SAI: a là int không phải float
scanf("%9d", &a);            // SAI: không được định dạng
scanf("a = %d, b = %d", &a, &b);  // SAI: không nên thêm text

8. Một Số Hàm Hữu Ích¤

Các Hàm Trong Thư Viện Toán Học¤

Thư viện:

C++
#include <math.h>

Hàm với 1 đối số đầu vào (double) và trả về double:

Hàm Ý nghĩa
acos, asin, atan Hàm lượng giác ngược
cos, sin, tan Hàm lượng giác
exp e mũ x
log Logarit tự nhiên
log10 Logarit cơ số 10
sqrt Căn bậc 2
ceil Làm tròn lên
floor Làm tròn xuống
abs, fabs Giá trị tuyệt đối

Hàm với 2 đối số đầu vào (double) và trả về double:

  • double pow(double x, double y): x mũ y

Ví dụ:

C++
#include <iostream>
#include <math.h>

int main() {
    float x = 2;

    std::cout << cos(x) << "\n";      // Hàm cos: -0.416147
    std::cout << sin(x) << "\n";      // Hàm sin: 0.909297
    std::cout << tan(x) << "\n";      // Hàm tan: -2.18504
    std::cout << acos(x) << "\n";     // Hàm arc cos: nan
    std::cout << asin(x) << "\n";     // Hàm arc sin: nan
    std::cout << atan(x) << "\n";     // Hàm arc tan: 1.10715
    std::cout << log(x) << "\n";      // Hàm log: 0.693147
    std::cout << log10(x) << "\n";    // Hàm log10: 0.30103
    std::cout << sqrt(x) << "\n";     // Căn bậc 2: 1.41421
    std::cout << fabs(-x) << "\n";    // Giá trị tuyệt đối: 2
    std::cout << pow(x, 2);           // Hàm mũ: 4

    std::cin.get();
    return 0;
}

9. Bài Tập Minh Họa¤

Bài 1: Nhập năm sinh và tính tuổi¤

C++
#include <iostream>

int main() {
    int nam_sinh = 0;

    std::cout << "Vui long nhap nam sinh: ";
    std::cin >> nam_sinh;
    std::cout << "Ban " << 2024 - nam_sinh << " tuoi" << "\n";

    std::cin.get();
    return 0;
}

Bài 2: Tính tổng, hiệu, tích, thương¤

C++
#include <iostream>

int main() {
    int a, b;

    std::cout << "Nhap a = ";
    std::cin >> a;
    std::cout << "Nhap b = ";
    std::cin >> b;

    std::cout << "a + b = " << a + b << "\n";
    std::cout << "a - b = " << a - b << "\n";
    std::cout << "a * b = " << (long long)a * b << "\n";
    std::cout << "a / b = " << (double)a / b << "\n";

    std::cin.get();
    return 0;
}

Bài 3: Tính tiền và thuế VAT¤

C++
#include <iostream>

int main() {
    int so_luong = 0, don_gia = 0;

    std::cout << "Vui long nhap so luong: ";
    std::cin >> so_luong;
    std::cout << "Vui long nhap don gia: ";
    std::cin >> don_gia;

    std::cout << "Tien: " << so_luong * don_gia << "\n";
    std::cout << "VAT: " << so_luong * don_gia * 0.1 << "\n";

    std::cin.get();
    return 0;
}

Bài 4: Tính chu vi và diện tích hình tròn¤

C++
#include <iostream>
#define PI 3.14

int main() {
    float r = 0;

    std::cout << "Nhap ban kinh duong tron: ";
    std::cin >> r;
    std::cout << "Chu vi: " << 2 * PI * r << "\n";
    std::cout << "Dien tich: " << PI * r * r << "\n";

    return 0;
}

10. Bài Tập Về Nhà¤

Bài 1: Tách chữ số biển xe

Cho số xe gồm 4 chữ số. Tính tổng các chữ số (số nút).

Gợi ý: Sử dụng phép chia và chia lấy dư.

Bài 2: Chuyển đổi chữ hoa - chữ thường

Cho 1 ký tự chữ thường. In ra ký tự chữ hoa tương ứng.

Gợi ý: Sử dụng bảng mã ASCII. Khoảng cách giữa chữ hoa và chữ thường là 32.

Bài 3: Tìm min/max

Cho 3 số nguyên. Tìm số lớn nhất và nhỏ nhất.

Gợi ý: Sử dụng toán tử điều kiện hoặc hàm max, min.

Bài 4: Cộng/trừ giờ

Viết chương trình nhập 2 giờ (giờ, phút, giây) và thực hiện cộng, trừ 2 giờ này.

Gợi ý: - Chuyển đổi sang tổng số giây - Thực hiện phép tính - Chuyển ngược lại sang (giờ, phút, giây)

Bài 5: Tổng bội số của 3 và 5

Tổng các bội số của 3 và 5 nhỏ hơn 10 là 23.

Ví dụ: Ta có các bội số: 3, 5, 6, 9 → Tổng: 23

Tính tổng các bội số của 3 và 5 nhỏ hơn 1000.


Tổng kết Chương Toán Tử

Trong chương này, chúng ta đã học:

  • 10 loại toán tử: gán, toán học, tăng/giảm, phẩy, phức hợp, bit, điều kiện, quan hệ, luận lý
  • Độ ưu tiên và thứ tự thực hiện của các toán tử
  • Biểu thức và cách tính giá trị
  • Nhập xuất dữ liệu với cin/coutscanf/printf
  • Các hàm toán học thông dụng
  • Các bài tập thực hành cơ bản

Chương tiếp theo: Cấu trúc điều khiển (if-else, switch-case)