Tác giả phạm hồng thái bài giảng ngôn ngữ LẬp trình c/C++



tải về 1.98 Mb.
trang11/55
Chuyển đổi dữ liệu07.07.2016
Kích1.98 Mb.
1   ...   7   8   9   10   11   12   13   14   ...   55

Các phép gán


Phép gán thông thường: Đây là phép gán đã được trình bày trong mục trước.

Phép gán có điều kiện:



biến = (điều_kiện) ? a: b ;

điều_kiện là một biểu thức logic, a, b là các biểu thức bất kỳ cùng kiểu với kiểu của biến. Phép toán này gán giá trị a cho biến nếu điều kiện đúng và b nếu ngược lại.

Ví dụ:

x = (3 + 4 < 7) ? 10: 20 // x = 20 vì 3+4<7 là sai



x = (3 + 4) ? 10: 20 // x = 10 vì 3+4 khác 0, tức điều kiện đúng

x = (a > b) ? a: b // x = số lớn nhất trong 2 số a, b.

Cách viết gọn của phép gán: Một phép gán dạng x = x @ a ; có thể được viết gọn dưới dạng x @= a trong đó @ là các phép toán số học, xử lý bit ... Ví dụ:

thay cho viết x = x + 2 có thể viết x += 2;

hoặc x = x/2 ; x = x*2 có thể được viết lại như x /= 2; x *= 2;

Cách viết gọn này có nhiều thuận lợi khi viết và đọc chương trình nhất là khi tên biến quá dài hoặc đi kèm nhiều chỉ số … thay vì phải viết hai lần tên biến trong câu lệnh thì chỉ phải viết một lần, điều này tránh viết lặp lại tên biến dễ gây ra sai sót. Ví dụ thay vì viết:

ngay_quoc_te_lao_dong = ngay_quoc_te_lao_dong + 365;

có thể viết gọn hơn bởi:

ngay_quoc_te_lao_dong += 365;

hoặc thay cho viết :

Luong[Nhanvien[3][2*i+1]] = Luong[Nhanvien[3][2*i+1]] * 290 ;

có thể được viết lại bởi:

Luong[Nhanvien[3][2*i+1]] *= 290;

Biểu thức


Biểu thức là dãy kí hiệu kết hợp giữa các toán hạng, phép toán và cặp dấu () theo một qui tắc nhất định. Các toán hạng là hằng, biến, hàm. Biểu thức cung cấp một cách thức để tính giá trị mới dựa trên các toán hạng và toán tử trong biểu thức. Ví dụ:

(x + y) * 2 - 4 ; 3 - x + sqrt(y) ; (-b + sqrt(delta)) / (2*a) ;


Thứ tự ưu tiên của các phép toán


Để tính giá trị của một biểu thức cần có một trật tự tính toán cụ thể và thống nhất. Ví dụ xét biểu thức x = 3 + 4 * 2 + 7

nếu tính theo đúng trật tự từ trái sang phải, ta có x = ((3+4) * 2) + 7 = 21,

nếu ưu tiên dấu + được thực hiện trước dấu *, x = (3 + 4) * (2 + 7) = 63,

nếu ưu tiên dấu * được thực hiện trước dấu +, x = 3 + (4 * 2) + 7 = 18.

Như vậy cùng một biểu thức tính x nhưng cho 3 kết quả khác nhau theo những cách hiểu khác nhau. Vì vậy cần có một cách hiểu thống nhất dựa trên thứ tự ưu tiên của các phép toán, tức những phép toán nào sẽ được ưu tiên tính trước và những phép toán nào được tính sau ...

C++ qui định trật tự tính toán theo các mức độ ưu tiên như sau:

Các biểu thức trong cặp dấu ngoặc ()

Các phép toán 1 ngôi (tự tăng, giảm, lấy địa chỉ, lấy nội dung con trỏ …)

Các phép toán số học.

Các phép toán quan hệ, logic.

Các phép gán.

Nếu có nhiều cặp ngoặc lồng nhau thì cặp trong cùng (sâu nhất) được tính trước. Các phép toán trong cùng một lớp có độ ưu tiên theo thứ tự: lớp nhân (*, /, &&), lớp cộng (+, -, ||). Nếu các phép toán có cùng thứ tự ưu tiên thì chương trình sẽ thực hiện từ trái sang phải. Các phép gán có độ ưu tiên cuối cùng và được thực hiện từ phải sang trái. Ví dụ. theo mức ưu tiên đã qui định, biểu thức tính x trong ví dụ trên sẽ được tính như x = 3 + (4 * 2) + 7 = 18.

Phần lớn các trường hợp muốn tính toán theo một trật tự nào đó ta nên sử dụng cụ thể các dấu ngoặc (vì các biểu thức trong dấu ngoặc được tính trước). Ví dụ:

Để tính D = b2 - 4ac ta viết delta = b * b - 4 * a * c ;

Để tính nghiệm phương trình bậc 2: x = viết : x = -b + sqrt(delta) / 2*a; là sai vì theo mức độ ưu tiên x sẽ được tính như -b + ((sqrt(delta)/2) * a) (thứ tự tính sẽ là phép toán 1 ngôi đổi dấu -b, đến phép chia, phép nhân và cuối cùng là phép cộng). Để tính chính xác cần phải viết (-b + sqrt(delta)) / (2*a).

Cho a = 1, b = 2, c = 3. Biểu thức a += b += c cho giá trị c = 3, b = 5, a = 6. Thứ tự tính sẽ là từ phải sang trái, tức câu lệnh trên tương đương với các câu lệnh sau:

a = 1 ; b = 2 ; c = 3 ;

b = b + c ; // b = 5

a = a + b ; // a = 6

Để rõ ràng, tốt nhất nên viết biểu thức cần tính trước trong các dấu ngoặc.


Phép chuyển đổi kiểu


Khi tính toán một biểu thức phần lớn các phép toán đều yêu cầu các toán hạng phải cùng kiểu. Ví dụ để phép gán thực hiện được thì giá trị của biểu thức phải có cùng kiểu với biến. Trong trường hợp kiểu của giá trị biểu thức khác với kiểu của phép gán thì hoặc là chương trình sẽ tự động chuyển kiểu giá trị biểu thức về thành kiểu của biến được gán (nếu được) hoặc sẽ báo lỗi. Do vậy khi cần thiết NSD phải sử dụng các câu lệnh để chuyển kiểu của biểu thức cho phù hợp với kiểu của biến.

Chuyển kiểu tự động: về mặt nguyên tắc, khi cần thiết các kiểu có giá trị thấp sẽ được chương trình tự động chuyển lên kiểu cao hơn cho phù hợp với phép toán. Cụ thể phép chuyển kiểu có thể được thực hiện theo sơ đồ như sau:

char « int ® long int ® float ® double

Ví dụ:


int i = 3;

float f ;

f = i + 2;

trong ví dụ trên i có kiểu nguyên và vì vậy i+2 cũng có kiểu nguyên trong khi f có kiểu thực. Tuy vậy phép toán gán này là hợp lệ vì chương trình sẽ tự động chuyển kiểu cuả i+2 (bằng 5) sang kiểu thực (bằng 5.0) rồi mới gán cho f.

Ép kiểu: trong chuyển kiểu tự động, chương trình chuyển các kiểu từ thấp đến cao, tuy nhiên chiều ngược lại không thể thực hiện được vì nó có thể gây mất dữ liệu. Do đó nếu cần thiết NSD phải ra lệnh cho chương trình. Ví dụ:

int i;


float f = 3 ; // tự động chuyển 3 thành 3.0 và gán cho f

i = f + 2 ; // sai vì mặc dù f + 2 = 5 nhưng không gán được cho i

Trong ví dụ trên để câu lệnh i = f+2 thực hiện được ta phải ép kiểu của biểu thức f+2 về thành kiểu nguyên. Cú pháp tổng quát như sau:

(tên_kiểu)biểu_thức // cú pháp cũ trong C

hoặc:


tên_kiểu(biểu_thức) // cú pháp mới trong C++

trong đó tên_kiểu là kiểu cần được chuyển sang. Như vậy câu lệnh trên phải được viết lại:

i = int(f + 2) ;

khi đó f+2 (bằng 5.0) được chuyển thành 5 và gán cho i.

Dưới đây ta sẽ xét một số ví dụ về lợi ích của việc ép kiểu.

Phép ép kiểu từ một số thực về số nguyên sẽ cắt bỏ tất cả phần thập phân của số thực, chỉ để lại phần nguyên. Như vậy để tính phần nguyên của một số thực x ta chỉ cần ép kiểu của x về thành kiểu nguyên, có nghĩa int(x) là phần nguyên của số thực x bất kỳ. Ví dụ để kiểm tra một số nguyên n có phải là số chính phương, ta cần tính căn bậc hai của n. Nếu căn bậc hai x của n là số nguyên thì n là số chính phương, tức nếu int(x) = x thì x nguyên và n là chính phương, ví dụ:

int n = 10 ;

float x = sqrt(n) ; // hàm sqrt(n) trả lại căn bậc hai của số n

if (int(x) == x) cout << "n chính phương" ;

else cout << "n không chính phương" ;

Để biết mã ASCII của một kí tự ta chỉ cần chuyển kí tự đó sang kiểu nguyên.

char c ;


cin >> c ;

cout << "Mã của kí tự vừa nhập là " << int(c) ;



Ghi chú: Xét ví dụ sau:

int i = 3 , j = 5 ;

float x ;

x = i / j * 10; // x = 6 ?

cout << x ;

trong ví dụ này mặc dù x được khai báo là thực nhưng kết quả in ra sẽ là 0 thay vì 6 như mong muốn. Lý do là vì phép chia giữa 2 số nguyên i và j sẽ cho lại số nguyên, tức i/j = 3/5 = 0. Từ đó x = 0*10 = 0. Để phép chia ra kết quả thực ta cần phải ép kiểu hoặc i hoặc j hoặc cả 2 thành số thực, khi đó phép chia sẽ cho kết quả thực và x được tính đúng giá trị. Cụ thể câu lệnh x = i/j*10 được đổi thành:

x = float(i) / j * 10 ; // đúng

x = i / float(j) * 10 ; // đúng

x = float(i) / float(j) * 10 ; // đúng

x = float(i/j) * 10 ; // sai

Phép ép kiểu: x = float(i/j) * 10 ; vẫn cho kết quả sai vì trong dấu ngoặc phép chia i/j vẫn là phép chia nguyên, kết quả x vẫn là 0.

1   ...   7   8   9   10   11   12   13   14   ...   55


Cơ sở dữ liệu được bảo vệ bởi bản quyền ©hocday.com 2016
được sử dụng cho việc quản lý

    Quê hương