Lập trình C: Bài 4 – Phép toán, toán tử trong C

Bài học hôm nay sẽ giới thiệu tới các bạn cách thực hiện các phép toán trong C, các toán tử để xử lý dữ liệu nữa.

1. Toán tử toán học

Ngôn ngữ C cung cấp 5 toán tử toán học cơ bản

STT Toán tử Tên Ví dụ Kết quả
1 + Cộng 3 + 4 7
2 Trừ 10.5 – 3 7.5
3 * Nhân 3 * 2 6
4 / Chia 6 / 3 2
5 % Chia lấy dư 8 % 3 2

Ok. Giờ thử làm ví dụ:

#include <stdio.h>

int main()
{
    int a = 5, b = 7;
    double c = 4.5, d = 6;

    printf("%d + %f = %f \n", a, c, a + c);
    printf("%d - %d = %d \n", a, b, a - b);
    printf("%d * %f = %f \n", b, d, b * d);

    /* Luu y phep chia nhe*/

    printf("%d / %d = %d \n", b, a, b / a);
    printf("%f / %d = %f \n", c, a, c / a);
    printf("%f / %f = %f \n", c, d, c / d);

    printf("%d %% %d = %d \n", b, a, b % a);

    return 0;
}

Kết quả:

5 + 4.500000 = 9.500000
5 – 7 = -2
7 * 6.000000 = 42.000000
7 / 5 = 1
4.500000 / 5 = 0.900000
4.500000 / 6.000000 = 0.750000
7 % 5 = 2

Toán tử lấy phần dư (%) yêu cầu cả hai toán hạng là số nguyên. Nó trả về phần dư còn lại của phép chia. Ví dụ 7 % 5 được tính toán bằng cách chia số nguyên 7 cho 5 để được 1 và phần dư là 2; vì thế kết quả là 2.

Thông thường, nếu cả hai toán hạng là số nguyên sau đó kết quả sẽ là một số nguyên. Tuy nhiên, một hoặc cả hai toán hạng là số thực thì sau đó kết quả sẽ là một số thực.

Khi cả hai toán hạng của toán tử chia là số nguyên thì sau đó phép chia được thực hiện như là một phép chia số nguyên và không phải là phép chia thông thường mà chúng ta sử dụng. Phép chia số nguyên luôn cho kết quả là phần nguyên của thương. Ví dụ: 7 / 5 = 1 chứ không phải 7 / 5 = 1.4. Để khắc phục lỗi này thì ta có thể chuyển một số hoặc cả 2 số sang kiểu thực rồi thực hiện phép chia. Cách chuyển kiểu (hay ép kiểu) ta như sau:

(kiểu cần chuyển) biến.
VD: (float) a;

Lưu ý khi ép kiểu thế này thì kiểu của các biến ban đầu không thay đổi mà chỉ là giá trị tức thời (tại thời điểm đó thay đổi sang kiểu mới). Để lưu lại giá trị tức thời này bạn cần khai báo thêm một biến mới có kiểu cần chuyển và gán giá trị đó lại. Ví dụ cho dễ.

#include <stdio.h>

int main()
{
    int a = 5, b = 7;
    double c;

    printf("%d / %d = %d \n", b, a, b / a);

    /* Chuyen gia tri tuc thoi cua b sang kieu so thuc*/
    printf("%d / %d = %f \n", b, a, (double)b / a);

    /* Chuyen gia tri tuc thoi cua a sang kieu so thuc*/
    printf("%d / %d = %f \n", b, a, b / (double)a);

    /* Neu lam the nay thi van khong dung, vi b/a duoc so nguyen
     * sau do chung ta moi ep kieu so nguyen do sang so thuc
     */
    printf("%d / %d = %f \n", b, a, (double)(b / a));

    return 0;
}

Kết quả:

7 / 5 = 1
7 / 5 = 1.400000
7 / 5 = 1.400000
7 / 5 = 1.000000

2. Toán tử quan hệ

Ngôn ngữ C cung cấp 6 toán tử quan hệ để so sánh các số. Các toán tử quan hệ có giá trị 1 (khi kết quả đúng) hoặc 0 (khi kết quả sai).

STT Toán tử Tên Ví dụ Kết quả
1 == So sánh bằng 5 == 5 1
2 != So sánh khác 5 != 5 0
3 > So sánh lớn hơn 5 > 4 1
4 < So sánh nhỏ hơn 5 < 4 0
5 >= So sánh lơn hơn hoặc bằng 5 >= 4 1
6 <= So sánh nhỏ hơn hoặc bằng 5 <= 5 1

Chúng ta sử dụng các toán tử này để so sánh các giá trị, các ký tự,… tuy nhiên không so sánh các xâu với nhau vì điều này sẽ dẫn đến các địa chỉ của chuỗi được so sánh chứ không phải là nội dung chuỗi. Chúng ta có các hàm so sánh xâu ở thư viện string và sẽ tìm hiểu sau. Khi so sánh các ký tự với nhau thì bản chất ta có thể hiểu là máy so sánh các mã ASCII của các ký tự với nhau. VD. ‘A’ >’B’ sẽ trả về giá trị 0 vì ‘A’ có mã ASCII là 65 còn ‘B’ là 66.

3. Toán tử luận lý

C cung cấp 3 toán tử luận lý cho việc kết nối các biểu thức luận lý. Giống như các toán tử quan hệ, các toán tử luận lý có giá trị là 1 hoặc 0.

STT Toán tử Tên Ví dụ Kết quả
1 ! Phủ định ! (5 > 4) 0
2 && 5 > 4 && 5 > 6 0
3 || Hoặc 5 > 4 || 5 > 6 1

4. Toán tử tăng giảm

Các toán tử tăng một (++) và giảm một (- -) cung cấp các tiện lợi tương ứng cho việc cộng thêm 1 vào một biến số hay trừ đi 1 từ một biến số.

#include <stdio.h>

int main()
{
    int i, k;

    i = 5; k = i++;
    printf("i = %d, k = %d\n", i, k);

    i = 5; k = ++i;
    printf("i = %d, k = %d\n", i, k);

    i = 5; k = i--;
    printf("i = %d, k = %d\n", i, k);

    i = 5; k = --i;
    printf("i = %d, k = %d\n", i, k);

    return 0;
}

Kết quả:

i = 6, k = 5
i = 6, k = 6
i = 4, k = 5
i = 4, k = 4

Tức là ta có:

++i và –i thì i được tính trước sau đó sẽ lấy kết quả để thực hiện biểu thức
i++ và i– thì i được đưa vào thực hiện biểu thức trước sau đó mới tính i

5. Toán tử gán

Toán tử gán được sử dụng để lưu trữ giá trị cho 1 biến nào đó.

Toán tử Ví dụ Tương đương với
= x = 5 Gán 5 cho x
+= x += 5 x = x + 5
-= x -= 5 x = x – 5
*= x *= 5 x = x * 5
/= x /= 5 x = x / 5
%= x %= 5 x = x % 5

Chạy test thử nhé.

#include <stdio.h>

int main()
{
    int x;

    x = 5;
    printf("x = 5 => x = %d\n", x);

    x += 5;
    printf("x += 5 => x = %d\n", x);

    x -= 5;
    printf("x -= 5 => x = %d\n", x);

    x *= 5;
    printf("x *= 5 => x = %d\n", x);

    x /= 5;
    printf("x /= 5 => x = %d\n", x);

    return 0;
}

Kết quả:

x = 5 => x = 5
x += 5 => x = 10
x -= 5 => x = 5
x *= 5 => x = 25
x /= 5 => x = 5

6. Một số toán tử khác

6.1 Toán tử phẩy

Nhiều biểu thức có thể được kết nối vào cùng một biểu thức sử dụng toán tử phẩy. Toán tử phẩy yêu cầu 2 toán hạng. Đầu tiên nó ước lượng toán hạng trái sau đó là toán hạng phải, và trả về giá trị của toán hạng phải như là kết quả sau cùng.
Ví dụ:

#include <stdio.h>

int main()
{
    int m, t;

    m = (t =2, t*5 + 10);
    printf("t = %d, m = %d\n", t, m);

    return 0;
}

Kết quả:

t = 2, m = 20

6.2 Toán tử lấy kích thước

C cung cấp toán tử hữu dụng, sizeof, để tính toán kích thước của bất kỳ hạng mục dữ liệu hay kiểu dữ liệu nào. Nó yêu cầu một toán hạng duy nhất có thể là tên kiểu (ví dụ, int) hay một biểu thức (ví dụ, 100) và trả về kích thước của những thực thể đã chỉ định theo byte. Chạy thử ví dụ nhá. Toán tử này chúng ta đã làm quen ở phần Kiểu dữ liệu rồi.

Chạy ví dụ test thử:

#include <stdio.h>

int main()
{
    printf("char size = %d byte\n", sizeof(char));
    printf("short size = %d byte\n", sizeof(short));
    printf("int size = %d byte\n", sizeof(int));
    printf("long size = %d byte\n", sizeof(long));
    printf("float size = %d byte\n", sizeof(float));
    printf("double size = %d byte\n", sizeof(double));
    printf("1.55 size = %d byte\n", sizeof(1.55));
    printf("\"Hello\" size = %d byte\n", sizeof("Hello"));
    return 0;
}

Kết quả:

char size = 1 byte
short size = 2 byte
int size = 4 byte
long size = 8 byte
float size = 4 byte
double size = 8 byte
1.55 size = 8 byte
“Hello” size = 6 byte

7. Độ ưu tiên của các toán tử

Độ ưu tiên các toán tử được thực hiện từ trên xuống dưới theo bảng sau. Trong mỗi hàng lại có độ ưu tiên như ở cột thứ 3.

Loại Toán tử Thứ tự ưu tiên
Postfix () [] -> . ++ – – Trái sang phải
Unary + – ! ~ ++ – – (type)* & sizeof Phải sang trái
Tính nhân * / % Trái sang phải
Tính cộng + – Trái sang phải
Dịch chuyển << >> Trái sang phải
Quan hệ < <= > >= Trái sang phải
Cân bằng == != Trái sang phải
Phép AND bit & Trái sang phải
Phép XOR bit ^ Trái sang phải
Phép OR bit | Trái sang phải
Phép AND logic && Trái sang phải
Phép OR logic || Trái sang phải
Điều kiện ?: Phải sang trái
Gán = += -= *= /= %=>>= <<= &= ^= |= Phải sang trái
Dấu phảy , Trái sang phải

Bài tập

  1. Viết chương trình nhập vào số giây, đổi số giây nhập vào thành dạng “gio:phut:giay”, mỗi thành phần là một số nguyên có 2 chữ số. VD nhập vào 7826 thì in ra 02:10:26

  2. Cho biến x = 3; Không chạy chương trình, đoán xem giá trị của x sau khi thực hiện lệnh:
    x = ++x – 3 + x;
    Sau khi đoán xong thì thử viết chương trình để kiểm tra kết quả.