Chương trình mà chúng ta tạo ra cần có khả năng tự đưa ra quyết định trong một số trường hợp. Để làm được điều này, các lập trình viên sử dụng thứ mà họ gọi là các lệnh cấu trúc. Hơi trừu tượng nhỉ? Cụ thể hơn thì chúng được chia thành 2 nhóm mà chúng ta sẽ tìm hiểu trong bài học này:
Hiểu cách sử dụng các lệnh cấu trúc là cơ bản trong cơ bản của lập trình. Dù theo tôi thì bài học này không quá khó, tuy nhiên các bạn cần chú ý hiểu rõ các khái niệm cơ bản. Chúng không chỉ hữu dụng trong suốt quá trình bạn sử dụng C++ mà còn có thể áp dụng trong các ngôn ngữ lập trình khác nữa vì chúng sử dụng 1 cơ chế chung.
Để chương trình có thể tự đưa ra quyết định, chúng ta cần sử dụng trong mà nguồn các lênh điều kiện ( hay các cấu trúc điều kiện ). Yêu cầu rất đơn giản : ta muốn chương trình sẽ đưa ra phản ứng khác nhau trong những tình huống khác nhau. Chúng ta sẽ tìm hiểu sau đây các lệnh này trong C+.
Để bắt đầu, các bạn cần biết rằng các lệnh điều kiện cho phép kiểm tra các biến. Hẳn là các bạn vẫn còn nhớ tới các biến được lưu trong các ô nhớ ở bài học trước chứ? Phần này sẽ dạy bạn cách đưa ra các câu hỏi kiểu như "Giá trị của biến này có lớn hơn 10?", "Trong này có chứa siêu cấp mật khẩu?", vv...
Để thực hiện việc kiểm tra, chúng ta cần sử dụng các dấu so sánh. Bảng các dấu so sánh dưới đây cần phải được bạn thuộc nằm lòng :
Các dấu so sánh | Ý nghĩa |
---|---|
== | bằng |
> | lớn hơn |
< | nhỏ hơn |
>= | lớn hơn hoặc bằng |
<= | nhỏ hơn hoặc bằng |
!= | khác |
! Cần đặc biệt chú ý là trong C++, để kiểm tra 2 giá trị có bằng nhau không, chúng ta dùng dấu ==
chứ không phải =
. Những người mới thường quên mất điều này và chỉ dùng 1 dấu =
. Kết quả đưa ra hoàn toàn không phải điều mà bạn mong chờ.
Chúng ta sẽ sử dụng các dấu này trong câu lệnh điều kiện của mình. Trong C++ thì có nhiều loại lệnh điều kiện nhưng mà cái quan trọng nhất cần phải nắm được, đó là lệnh điều kiện if
.
if
Lại nhắc lại lần nữa, lệnh điều kiện dùng để kiểm tra các biến. Tôi đề nghị các bạn hay cùng tôi viết 1 chương trình để kiểm tra xem bạn có hiểu rõ cơ chế của nó không.
Chúng ta bắt đầu với đoạn mã :
#include <iostream> using namespace std; int main(){ int soCon(2); return 0; }
Chương trình này vẫn chưa làm gì cả ngoài việc khai báo 1 biến soCon
( chứa giá trị số con cái của bạn ) và kết thúc
Lệnh if
đầu tiên
Chúng ta muốn là chương trình in ra lời chúc mừng là bạn đã sinh ra được những đứa trẻ xinh đẹp và giỏi giang. Điều kiện cần xét đến là chỉ in thông điệp nếu số con cái lớn hơn 0.
#include <iostream> using namespace std; int main(){ int soCon(2); if (soCon > 0){ cout << "Chuc mung ban da sinh ra nhung dua tre xinh dep va gioi giang !" << endl; } cout << "Ket thuc" << endl; return 0; }
Kết quả chúng ta nhận được
Quan sát ky dòng sau đây if (soCon > 0)
Chính nó thực hiện việc kiểm tra xem số con cái có lớn hơn 0 không ("if" là từ tiếng Anh nghĩa là "nếu"). Nếu phép kiểm tra thành công ( tức là có con cái ), vậy máy tính sẽ đọc những lệnh bên trong dấu ngoặc nhọn {}
, ở đây là lệnh in thông báo ra màn hình.
? Chuyện gì xảy ra nếu 1 người không có con cái ?
Trong trường hợp đấy, phép thử thất bại và máy tính sẽ không đọc các lệnh trong dấu {}
mà nhảy thẳng đến lệnh sau dấu }
. Lúc đấy, chỉ có thông điệp Ket thuc là được in ra.
Hãy viết lại chương trình! Thay giá trị của soCon
thành 0 và bạn sẽ thấy.
else
: phản ứng xảy ra nếu phép thử thất bại
Bạn muốn là chương trình sẽ có phản ứng cụ thể nào đó khi phép thử thất bại ? Tôi thừa nhận là vừa rồi chương trình hơi bị im tiếng khi bạn không có con cái.
Thật tốt là chúng ta có thể dùng từ khóa else
nghĩa là "nếu không". Chúng ta sẽ hiện 1 thông báo khác cho những người không có con.
#include <iostream> using namespace std; int main(){ int soCon(0); if (soCon > 0){ cout << "Chuc mung ban da sinh ra nhung dua tre xinh dep va gioi giang !" << endl; }else{ cout << "O, hay tan huong tu do khi con chua co bon tre !" << endl; } cout << "Ket thuc" << endl; return 0; }
Và cho ra kết quả
Chú ý kỹ là tôi đã thay đổi giá trị của soCon
ở đầu chương trình nhé.
Nếu bạn thay vào đó là 1 giá trị lớn hơn 0, thông điệp bạn nhận được ban đầu sẽ lại hiện ra.
Chuyện gì đã xảy ra thế ? Rất đơn giản, máy tính làm phép thử cho điều kiện ở trong lệnh if và thấy thất bại vì điều kiện thành công là soCon phải lớn hơn 0. Vậy là máy tính bỏ qua những lệnh ở trong dấu {} đầu tiên và đi tới chỗ else và nó thực hiện những lệnh được viết trong {} ngay sau else.
else if
: thực hiện tiếp 1 lệnh điều kiện khác
Ta có thể thực hiện nhiều điều kiện liên tiếp nhau. Thử nghĩ đến trường hợp sau :
Để thực hiện phép thử cái này tiếp sau cái kia theo thứ tự, chúng ta sẽ sử dụng else if
có nghĩa là nếu không nếu... Các phép thử sẽ được kiểm tra lần lượt tới khi nào 1 trong số chúng được thỏa mãn.
#include <iostream> using namespace std; int main(){ int soCon(2); if (soCon == 0){ cout << "Ban chua co con ?" << endl; }else if (soCon == 1){ cout << "Bao gio thi den dua thu 2 day ?" << endl; }else if (soCon == 2){ cout << "Ban da sinh ra nhung dua tre that xinh dep va gioi giang !" << endl; }else{ cout << "Chac la nen dung lai thoi nhi?" << endl; } cout << "Ket thuc" << endl; return 0; }
Trroong khá phức tạp nhỉ ? Thật ra thì cũng không đến nỗi.
Đặt trường hợp là bạn có 2 con :
else if
thứ 2, máy tính sẽ kiểm tra nếu bạn co 2 con.Nếu không phép thử nào thành công thì thông điệp trong else
là "Chac nen dung lai thoi nhi?" được in.
switch
Trên lý thuyết thì lệnh if
cho phép ta thực hiện tất cả các phép thử mà ta muốn. Trong thực tiễn thì vẫn còn những cách khác để đưa ra các phép thử. Ví dụ nổi bật nhất là lệnh điều kiện switch
cho đơn giản phép thử nhiều giá trị khác nhau của cùng 1 biến.
Quay lại với ví dụ ta vừa mới làm ở trên nhé:
Bạn có 0 con? Bạn có 1 con? Bạn có 2 con? ....
Kiểu phép thử liên tiếp này có thể đươc thực hiện nhờ các lệnh else if
liên tục nhưng cũng có thể dùng lệnh switch
với mục đích giúp đoán mã dễ đọc và dễ hiểu hơn. Đây là 1 phiên bản khác của đoạn mã bên trên.
#include <iostream> using namespace std; int main(){ int soCon(2); switch (soCon){ case 0: cout << "Ban chua co con ?" << endl; break; case 1: cout << "Bao gio thi den dua thu 2 day ?" << endl; break; case 2: cout << "Ban da sinh ra nhung dua tre that xinh dep va gioi giang !" << endl; break; default: cout << "Chac la nen dung lai thoi nhi?" << endl; break; } return 0; }
Và kết quả nhận được là
Kết cấu có đôi chút khác biệt. Ở dòng thứ 8, chúng ta nói cho máy tính biết là chúng ta sẽ phân tích biến soCon. Sau đó chúng ta kiểm tra tất cả các trường hợp (case
) giá trị là 0, 1, 2,...
Lệnh break
là bắt buộc phải có ở đây vì máy tính không dừng việc kiểm tra dù là phép thử với 1 giá trị đã thành công. Theo kinh nghiệm thì tôi khuyên các bạn thêm nó vào cuối mỗi lệnh case
.
Cuối cùng, phép thử default
ở cuối tương tự như else
, sẽ được chạy nếu không có phép thử nào trong những giá trị cung cấp trước đó cho kết quả thành công.
!Lệnh switch
chỉ cho phép thử phép so sánh bằng. Điều đó nghĩa là bạn không thể kiểm tra "Số lượng con cái có lớn hơn 2?". Trong trường hợp đó thì bạn phải dùng lệnh if
. Ngoài ra switch
chỉ có thể làm việc với kiểu dữ liệu số nguyên như int
, unsigned int
, char
(vì trong C++, ký tự được coi là 1 số nguyên đặc biệt) chứ không hoạt động với số thực như double
. Về cơ bản thì switch
chịu khá nhiều hạn chế nhưng bù lại cung cấp cho ta một phương thức lệnh khác trong những trường hợp đơn giản.
Hãy tìm hiểu sâu thêm về các điều kiện. Chúng ta sẽ khám phá 2 khái niệm hơi nâng cao : kiểu bool và điều kiện kết hợp.
Các bạn còn nhớ kiểu dữ liệu bool
chứ? Nó chỉ có thể chúa được 2 giá trị : true
(đúng) và false
(sai).
Kiểu dữ liệu này rất hay được sử dụng với các lệnh điều kiện. Rất hợp lý đúng không, bởi vì một điều kiện thì cũng chỉ có thể là đúng hoặc sai và biến kiểu bool
cũng thế.
Nếu tôi nói về kiểu dữ liệu này thì là tại vì trong các lệnh điều kiện, nó được sử dụng 1 cách rất đặc biệt. Trước tiên, hãy bắt đầu với đoạn mã sau.
bool truongThanh(true); if (truongThanh == true){ cout << "Ban la nguoi truong thanh!" << endl; }
Điều kiện này kiểm tra 1 biến truongThanh
và in ra 1 thông điệp nếu biến đấy có giá trị true
.
Các bạn đang thắc mắc về ý định của tôi phải không? Cái tôi muốn nói là với kiểu bool
trong câu điều kiện thì phần == true
có thể được bỏ qua ! Đoạn mã dưới đây hoàn toàn tương đương.
bool truongThanh(true); if (truongThanh){ cout << "Ban la nguoi truong thanh!" << endl; }
Máy tính hiểu rằng bạn muốn kiểm tra xem giá trị của truongThanh
có phải là true
không mà không cần thêm == true
.
? Như thế không khiến mã khó đọc hơn à ?
Không hề, ngược lại, đoạn mã sẽ ngắn hơn và dễ đọc hơn! if (truongThanh)
có thể dễ dàng hiểu là "Nếu bạn là người trưởng thành".
Tôi đề nghị các bạn sử dụng cách viết rút gọn này khi kiểm tra các biến kiểu bool
để mã ngắn và dễ đọc hơn.
Một điều cần biết là chúng ta có thể đồng thời thực hiện nhiều phép thử cho nhiều điều kiện khác nhau trong cùng 1 câu lệnh if. Để làm điều này thì chúng ta cần thêm một số dấu mới. Dưới đây là các dấu mà chúng ta sẽ dùng để kết hợp các điều kiện và ý nghiã của chúng
&& | và |
|| | hoặc |
! | phủ định |
Dấu và
Hãy giả định rằng chúng ta muốn kiểm tra xem một người là người trưởng thành và đồng thời người đó có ít nhất 1 đứa con.
if (truongThanh && soCon >= 1)
Dấu &&
có nghĩa là và, vậy nên lệnh điều kiện của chúng ta có thể được dịch là "Nếu 1 người là người trưởng thành và có ít nhất 1 đứa con".
! Hãy để ý là tôi cúng có thể viết là if (truongThanh == true && soCon >= 1)
nhưng như đã nhắc đến ở bên trên, chúng ta có thể bỏ == true
đi.Đây là 1 thói quen tôi cho rằng các bạn nên học.
Dấu hoặc
Để thực hiện phép hoặc, chúng ta dùng dấu ||
. Dấu này bao gồm 2 dấu |
mà trên bàn phím QWERTY chúng ta có thể gõ bằng cách giữ phím shift và phím \ nằm bên gần phím Enter.
Một ví dụ phép thử 1 người có 1 hoặc 2 con.
if (soCon == 1 || soCon == 2)
Dấu phủ định
Đê phủ định, chúng ta sẽ sử dụng dấu !
. Trong tin học thì dấu này có nghĩa là "không".
Bạn có thể đặt dấu này trước mệnh đề đang xét và nó sẽ có nghĩa là "nếu mệnh đề không đúng".
if (!truongThanh)
... có nghĩa là nếu một người chưa trưởng thành.
Những vòng lặp giống như tên gọi, cho phép chúng ta lặp đi lặp lại một chuỗi hành động trong chương trình. Nguyên tắc như sau :
Vòng lặp sẽ được lặp đi lặp lại khi mà một mênh đề còn đúng. Ví dụ như, "Khi nào mà người dùng còn nhập 1 số âm cho biến lưu trữ thông tin về số con cái, máy tính sẽ yêu cầu nhập lại".
Có 3 kiêu vòng lặp cần biết :
while
Vòng lặp này trông như sau :
while (<điều kiện>){ /* Chuoi lenh can lap */ }
Tất cả các câu lệnh nắm giữa dấu {}
sẽ được lặp đi lặp lại khi nào mà dieuKien còn đúng.
Hãy thử thực hiện những gì mà tôi nói bên trên : Yêu cầu người dùng nhập lại số con cái khi nào cho đến khi nào dữ liệu nhập vào không nhỏ hơn 0. Kiểu vòng lặp này thường được dùng khi chúng ta muốn chắc chắn dữ liệu người dùng nhập vào phù hợp với yêu cầu.
int main(){ int soCon(-1); // So am de bat dau vong lap while ( soCon < 0 ){ cout << "Ban co bao nhieu dua con ?" << endl; cin >> soCon; } cout << "Cam on vi da nhap dung so con. Ban co " << soCon << " con." << endl; return 0; }
1 ví dụ khi chạy chương trình trên
Khi nào mà bạn còn nhập vào một số âm thì vòng lặp còn bắt đầu lại. while ( soCon < 0)
có nghĩa là "Khi nào mà số lưu trong biến soCon còn âm". Lần đầu tiên bạn nhập vào một số lớn hơn hoặc bằng 0, vòng lặp sẽ kết thúc và tiếp tục sau dấu {}
.
!Các bạn hẳn nhận ra tôi đã khởi tạo biến soCon với giá trị -1. Để máy tính có thể bước vào vòng lặp lần đầu tiên thì một giá làm cho mệnh đề đúng ở thời điểm đó là cần thiết.
do ... while
Kiểu vòng lặp này rất giống với vòng lặp trước, chỉ khác mỗi là điều kiện sẽ được kiểm tra ở cuối vòng lặp. Điều này có nghĩa là vòng lặp sẽ được thực hiện ít nhất một lần.
Vòng lặp này trông như sau :
do{ /* Chuoi lenh can lap */ } while (<điều kiện>);
Hãy chú ý là có dấu ; nằm ở cuối cùng !
Viết lại đoạn mã bên trên với vòng do ... while
int main(){ int soCon(0); do{ cout << "Ban co bao nhieu dua con ?" << endl; cin >> soCon; } while (soCon < 0); cout << "Cam on vi da nhap dung so con. Ban co " << soCon << " con." << endl; return 0; }
Nguyên tắc là như nhau, khi chạy chương trình cũng nhận được kết quả giống nhau. Lợi ích duy nhất là do ... while
đảm bảo vòng lặp được thực hiện ít nhất 1 lần.
Thêm vào đó, không cần thiết phải khai báo giá trị khởi đầu là -1 nữa. Trên thực tế, số con cái được khởi tạo với giá trị 0 giống như chúng ta vẫn làm và bời vì điều kiện chỉ được kiểm tra sau khi đã thực hiện xong 1 lần vòng lặp, chuổi các lệnh sẽ được thực hiện ít nhất 1 lần.
Vòng lặp for
Kiểu vòng lặp này có 3 yếu tố :
Vòng lặp này có cấu trúc như sau:
for(<khởi điểm>; <điều kiện>; <tăng bước>){ }
Hãy xem ví dụ cụ thể chúng ta dùng để in ra màn hình các số từ 0 tới 9.
int main(){ int chiSo(0); for (chiSo = 0 ; chiSo < 10 ; chiSo++){ cout << chiSo << endl; } return 0; }
Và đây là kết quả.
Ở dòng lệnh for
, chúng ta tìm thấy 3 yếu tố đã được nhắc ở trên.
chiSo = 0
: Biến chiSo được khởi tạo với giá trị 0 ở đàu vòng lặp. Vì việc này vừa được làm ngay trong dòng lệnh trước đó, dòng lệnh này trở nên không cần thiếtchiSo < 10
: Máy tính sẽ kiểm tra điều kiện này mỗi khi bắt đầu 1 vòng lặp mớichiSo++
: Ở cuối mỗi vòng lặp, ta sẽ tăng giá trị của chiSo
lên 1. Đây là lý do mà chúng ta hiển thì ra màn hình được các số từ 0 đến 9.! Bạn có thể làm 1 xử lý khác ngoài phép tăng bước ở phần cuối của vòng for
. Thật ra phần này được dành để thay đổi giá trị của biến để dùng cho vòng lặp tiếp theo. Vậy nên nếu muốn, bạn có thể làm chiSo--
hoặc chiSo += 2
cũng không sao cả
Cần biết là việc khai báo biến trực tiếp ở trong vòng for
cũng rất hay được các lập trình viên sử dụng.
int main(){ for (int chiSo(0) ; chiSo < 10 ; chiSo++) { cout << chiSo << endl; } return 0; }
Và biến chiSo
sẽ chỉ có tồn tại lúc xử lý vòng for
chứ không phải trong toàn bộ thời gian hoạt động của chuong trình. Đây là dạng hay gặp nhất của vòng lặp này. Chúng ta sẽ chỉ khai báo biến bên ngoài vòng for nếu cần nó cho mục đích sau này. Mà việc này thì khá hiếm.
! Khi nào thì chúng ta sử dụng vòng for
và khi nào thì dùng vòng while
?
Chúng ta dùng vòng for
khi xác định được số lần chúng ta muốn lặp chuỗi hành động và vòng while
cho những trường hợp không xác định được chỉ số này.
if ... else if ... else
nghĩa là "nếu ... nếu không thì nếu ... nếu không" là dạng hay gặp nhất của lệnh điều kiệnswitch
đặc biệt hơn cho phép kiểm tra những giá trị khác nhau của cùng 1 biếnfor
, while
và do ... while
for
dùng khi mà chúng ta biết chính xác số lần mà chúng ta muốn lặp lại chuỗi hành động trong khi 2 vòng còn lại thường dùng để lặp số lần không xác định đến khi nào điều kiện không được thỏa mãn nữa.