Chương 3: Cấu trúc điều khiển
Cấu trúc rẽ nhánh, vòng lặp và điều hướng luồng thực thi - những công cụ cốt lõi giúp chương trình có khả năng đưa ra quyết định thông minh và tự động hóa các tác vụ một cách hiệu quả.
1. Giới thiệu cấu trúc điều khiển
Trong , 1 chương trình sẽ bao gồm nhiều cấu trúc điều khiển khác nhau và cấu trúc điều khiển là tập hợp các câu lệnh quyết định chương trình được thực thi như thế nào.
1 cấu trúc điều khiển có thể có 1 hoặc nhiều chức năng sau:
- Cấu trúc tuần tự: thực hiện một chuỗi các phát biểu một cách tuần tự theo thứ tự xuất hiện của chúng trong chương trình.
- Cấu trúc chọn: phụ thuộc vào điều kiện của câu lệnh mà dữ liệu được đưa vào chương trình có được phép thực thi chương trình để giải quyết 1 vấn đề hay không.
- Cấu trúc lặp: dữ liệu được lặp đi lặp lại đến khi dữ liệu không thỏa điều kiện của cấu trúc nữa.
- Gọi hàm: gọi lại 1 hàm ngoài hàm chính để thực thi chức năng mà hàm chính cần để xử lí dữ liệu.
2. Khái niệm câu lệnh và khối lệnh trong lập trình
2.1 Câu lệnh:
- Câu lệnh giống như ban lãnh đạo trong bối cảnh này là người dùng đưa ra các chỉ thị cho ban chấp hành thực hiện ở đây là chương trình , là thao tác dùng để thực hiện 1 nhiệm vụ trong 1 chương trình như : gán giá trị, đọc/ xuất dữ liệu,....
2.2 Khối lệnh:
- Khối lệnh giống như 1 tập hợp các hành động là 1 dãy các câu lệnh được đặt trong dấu ngoặc nhọn.Ngoài ra, khối lệnh còn có thể chứa bên trong nhiều khối lệnh khác để thực thi nhiều chức năng trong 1 chương trình.
3. Phạm vi hoạt động của biến
3.1 Phạm vi hoạt động của biến
-
Phạm vi hoạt động của biến là không gian mà tại đó biến tồn tại và được sử dụng, có thể là trong 1 khối lệnh, có thể nằm trong 1 vòng lặp hoặc thuộc về 1 điều kiện nằm trong 1 khối lệnh.
-
Biến nằm trong khối lệnh thì dữ liệu chỉ có thể được sử dụng trong toàn bộ khối lệnh đó.
-
Biến nằm trong 1 vòng lặp hoặc điều kiện thì chỉ có thể sử dụng trong vòng lặp,điều kiện đó.
3.2. Biến toàn cục và biến cục bộ
- Phạm vi của biến nằm bên trong 1 hàm hoặc 1 khối lệnh thì được gọi là biến cục bộ.
- Phạm vi của biến nằm bên ngoài tất cả các hàm của 1 chương trình thì được gọi là biến toàn cục.
- Tham số hình thức: là tên biến được khai báo trong phần định nghĩa hàm, được dùng để nhận giá trị từ hàm khác.
#include <iostream>
using namespace std;
int chieudai; // Biến toàn cục
int chieurong; // Biến toàn cục
int Dientich(int a, int b){ // khai báo 2 tham số hình thức là a và b trong định nghĩa hàm
int S = a * b;
return S;
}
int main(){
int S = 0;
cout << "nhap chieu dai";
cin >> chieudai;
cout << "nhap chieu rong";
cin >> chieurong;
S = Dientich(chieudai, chieurong); // truyền vào hàm dientich 2 giá trị thực
cout << "dien tich HCN ="; // của chiều dài và chiều rộng đến biến a và b
cout << S;
return 0;
}
- Lưu ý
- Dù ít ai làm như vậy nhưng chúng ta nên biết để có thể hiểu code trong 1 vài trường hợp, chỉ cần 2 biến được đặt trong 2 khối lệnh lồng nhau thì hoàn toàn có thể dùng chung 1 tên biến.Việc đặt cùng tên sẽ làm cho ta không thể dùng giá trị của chính biến cùng tên được khai báo ở khối bên ngoài.
Ví dụ :
#include <iostream>
using namespace std;
int main(){
long long a = 10;
cout << a << '\n';
{
int a = 12;
cout << a;
}
return 0;
}
// kết quả là 10 \n 12
-
Khi code nên hạn chế dùng nhiều hiệu ứng side-effect: là hiệu ứng mà 1 biến có thể làm thêm nhiều tác vụ khác ngoài tác vụ chính.
Ví dụ:
#include <iostream>
using namespace std;
int main(){
int x = 10;
int y = 20;
int z = (x++, y--); // ở đây ngoài việc gán giá trị cho z bằng 20 còn thêm cả việc thay đổi giá trị của x và y,
// có thể gây ra khó hiểu nếu chương trình dài hơn và phức tạp hơn
cout << z << '\n' << x << '\n' << y;
return 0;
}
4. Cấu trúc rẽ nhánh if, if-else, if-else if-else và switch-case.
4.1. Cấu trúc if
Cấu trúc if (nếu) là cấu trúc điều khiển thực hiện một chức năng tương ứng với một điều kiện nếu điều kiện khi kiểm tra được thỏa mãn, tương tự nếu điều kiện chưa được thỏa mãn thì chức năng không được thực thi. Nếu viết nhiều lệnh if thì tất cả các lệnh if sẽ được kiểm tra dù đã tìm ra được điều kiện thỏa mãn.
Biểu thức điều kiện đúng có giá trị là 1 và biểu thức điều kiện sai có giá trị là 0.
Cú pháp của if:
if (biểu_thức_điều_kiện) {
// khối lệnh
}
- Ví dụ:
#include <iostream>
using namespace std;
int main() {
int x = 12;
int y = 11;
if (!(x < y)) { // Kiểm tra điều kiện ở đây đúng hay sai
int z = x + y; // vì x < y là kết quả sai
cout << z; // nên giá trị điều kiện là 0 nhưng có toán tử phủ định
return 0; // nên giá trị điều kiện là 1 đúng và thực hiện việc in giá trị x - y
}
}
4.2. Cấu trúc if-else:
Cấu trúc if-else là cấu trúc điều khiển sẽ thực thi chức năng nếu điều kiện của if thỏa, nếu điều kiện if không thỏa thì chức năng trong khối lệnh của else sẽ được thực thi.
Cú pháp của if-else:
- if(biểu thức điều kiện){
__khối lệnh__
}
else{
__khối lệnh__
}
- Ví dụ:
#include <iostream>
#include <cmath>
using namespace std;
int main(){
int a = 100;
if(a % 10){ // kiểm tra điều kiện a =100 khi chia dư cho 10 sẽ được 0 do đó lệnh trong if
cout << pow(a,1); // không được thực hiện mà sẽ thực thi lệnh trong else.
a *= 10;
}
else {
a /= 10;
cout << pow(a,2);
}
return 0;
}
- Lưu ý: trong cấu trúc điều khiển này có thể sử dụng nhiều if nhưng không được sử dụng nhiều else, vì trình biên dịch sẽ không biết else còn lại gắn cho điều kiện nào.
4.3. Cấu trúc khối lệnh if-else if-else:
- Cấu trúc if-else if-else là cấu trúc điều khiển thực chức năng tương tự như cấu trúc if-else nhưng việc kiểm tra điều kiện sẽ ngừng khi có 1 điều kiện được thỏa mãn mà không cần kiểm tra các điều kiện còn lại.
Cú pháp của if-else if-else:
if(biểu thức điều kiện){
__Khối lệnh__
}
else if(biểu thức điều kiện){
__Khối lệnh__
}
else{
__Khối lệnh__
}
- Ví dụ:
#include <iostream>
using namespace std;
int main(){
int khoa;
cin >> khoa;
if(khoa == 1){
cout << “ Khoa Công nghệ phần mềm”;
}
else if(khoa == 2){
cout << “ Đoàn khoa công nghệ phần mềm ”;
}
else{
cout << “Ban học tập công nghệ phần mềm”;
}
return 0;
}
- Lưu ý: ta có thể dùng nhiều khối lệnh else if để kiểm tra nhiều điều kiện và chỉ cần có 1 điều kiện thỏa thì nó sẽ ngay lập tức dừng lại. Nhưng chỉ được viết 1 lần else với lí do tương tự như if-else.
4.4. Cấu trúc rẽ nhánh Switch-case
- Cấu trúc switch-case 1 cấu trúc rẽ nhánh chia thành nhiều trường hợp, biểu thức trong switch sẽ cho ra kết quả tương ứng với tên của 1 case, case có tên tương ứng sẽ thực thi khối lệnh của case đó, và chỉ dừng khi gặp lệnh break. Trong trường hợp biểu thức của switch không có case thỏa mãn thì lệnh default nằm cuối cùng của switch-case sẽ được thực thi.
Lưu ý: Nếu case đó không kết thúc bằng từ khóa break, thì sau khi case tương ứng thực thi lệnh, case tiếp theo sẽ được thực thi cho đến khi gặp case có từ khóa break điều này tạo ra hiệu ứng fall through. Nếu không gặp case có từ khóa break thì chương trình tiếp tục chạy tới khi thực hiện luôn lệnh của default.
Cú pháp của switch-case:
- switch(biểu thức){
case Kết quả thứ nhất của biểu thức: Khối lệnh_1; Break;
case Kết quả thứ hai của biểu thức: Khối lệnh_2; Break;
....
case Kết quả thứ n của biểu thức : Khối lệnh_3; Break;
default:
__Khối lệnh_;
}
- Ví dụ 1:
#include <iostream>
using namespace std;
int main(){
int bhtcnpm;
cin >> bhtcnpm;
switch(bhtcnpm)
{
case 2: cout << “ BHT CNPM la so 1”;break;
case 11: cout << “Sharing is learning”;break;
case 2015: cout <<”Learning is sharing”;break;
default:
cout << “From BHT CNPM with love”;
}
return 0;
}
- Trong ví dụ nếu biểu thức có kết quả đúng các tên gọi của các case tương ứng thì sẽ chạy các khối lệnh trong case tương ứng đó.
- Nếu giá trị của switch không tương ứng với bất kì case nào thì lệnh trong default sẽ được thực thi.
- Ví dụ 2:
#include <iostream>
using namespace std;
int main(){
int denGT = 0;
cin >> denGT;
switch(denGT)
{
case 1: cout <<” Màu đỏ- dừng lại”;
case 2: cout << “Màu vàng- chạy chậm lại”;break;
default:
cout <<” Màu xanh- được phép chạy”;
}
return 0;
}
- Lúc này nếu rơi vào case 1 thì dòng lệnh case 1 được thực thi và sau đó sẽ tiếp tục do không có lệnh break tạo ra hiệu ứng fall through, rơi xuống và thực thi luôn lệnh của case 2.
5. Cấu trúc lặp
- Trong nhiều trường hợp, ta muốn một chương trình thực hiện đi thực hiện lại 1 hành động nào đó với các giá trị khác nhau để kiểm tra thì ta sẽ dùng cấu trúc lặp. Cấu trúc lặp được chia thành 2 loại: Cấu trúc lặp biết trước số lần lặp và cấu trúc lặp không biết trước số lần lặp.
5.1 Cấu trúc lặp for
- Cấu trúc lặp for là cấu trúc lặp được sử dụng trong trường hợp cần phải lặp đi lặp lại nhiều lần 1 hành động nào đó, số lần lặp phụ thuộc vào 1 điều kiện nhất định (bé hơn hoặc bằng số n bất kì, thỏa mãn 1 điều kiện logic,...). for được sử dụng khi ta biết trước được số lần lặp.
Cú pháp của for:
for( biến; điều kiện; cập nhật giá trị của biến){__Khối lệnh____}
- Biến: biến được khởi tạo để xác định số lần lặp lại
- Điều kiện: biến phải thỏa mãn điều kiện mới được phép thực hiện lần lặp, và việc lặp sẽ dừng lại khi biến không còn thỏa điều kiện
- Cập nhật giá trị của biến: Biến được cập nhật giá trị để giúp ta đạt được số lần lặp mong muốn và tránh trường hợp lặp vô hạn lần.
Lưu ý: Nếu trong vòng lặp for, ta có thể để trống việc khai báo biến điều kiện và biểu thức cập nhật nhưng phải có có 2 dấu “;”.
Ví dụ 1:
#include <iostream>
using namespace std;
int main(){
int sum = 0;
int n = 0;
cin >> n;
for(int i = 0; i < n; i++){
sum += i;
}
cout << sum
return 0;
}
Ví dụ 2:
#include <iostream>
using namespace std;
int main(){
int sum = 0;
int n = 0;
cin >> n;
int i = 0;
for(; ; ){
sum += i;
i++;
if(i > n)break;
}
cout << sum;
return 0;
}
5.2 Cấu trúc lặp while
- Cấu trúc lặp while được sử dụng khi cần thực hiện 1 hành động nào đó lặp nhiều lần cho đến khi đạt được yêu cầu thì dừng lại và cho ra kết quả mong đợi. while được sử dụng khi ta không biết trước được số lần lặp.
Cú pháp của while:
while(biểu thức điều kiện){__Khối lệnh__}
Ví dụ:
#include <iostream>
using namespace std;
int main(){
int sum = 0;
int n = 0;
cin >> n;
while(n > 0){
sum += n;
n--;
}
cout << sum;
return 0;
}
5.3. Cấu trúc lặp do-while
- Cấu trúc lặp do-while được sử dụng khi việc lặp cần lặp trước 1 hành động rồi sau đó mới kiểm tra điều kiện để quyết định có thực hiện lần lặp tiếp theo hay không.
Cú pháp của do-while:
do{
__Khối lệnh__
}while(biểu thức điều kiện)
- Lưu ý: Trong cấu trúc này thì luôn có 1 lần lặp được thực thi dù ngay từ ban đầu điều kiện sai.
Ví dụ:
#include <iostream>
using namespace std;
int main(){
int sum = 0;
int n = 0;
cin >> n;
do
{
sum += 1;
n--;
}while(n > 0);
cout << sum;
return 0;
}
5.4. Câu lệnh break, continue
- Câu lệnh break: là câu lệnh dùng để thoát khỏi vòng lặp ngay lặp tức và tiếp tục thực hiện các lệnh sau vòng lặp nếu có.
- Câu lệnh continue: là câu lệnh dùng để bỏ qua lần lặp này và tiếp tục thực hiện lần lặp kế tiếp nếu điều kiện còn thỏa.
Bài tập
-
Xếp loại học sinh Cho biết điểm kiểm tra Tin học của 1 em học sinh là a, b, c, d (2 điểm a, b hệ số 1, c là điểm hệ số 2, d là điểm hệ số 3). In ra Kết quả học tập môn Tin học của em đó. Nếu điểm tổng kết
>=8đạt kết quả Giỏi,<8và>=6.5đạt kết quả Khá,<6.5và>=5đạt kết quả Trung Bình,<5đạt kết quả Yếu. Điểm trung bình được tính bằng tổng hệ số nhân với điểm chia cho tổng hệ số. -
Tìm số lớn nhất và số nhỏ nhất Cho 4 số nguyên a,b,c,d hãy tìm số lớn nhất và số nhỏ nhất.Trong 4 số này.
-
Chúc mừng năm mới Năm mới sắp đến và bạn rất hào hứng muốn biết còn bao nhiêu phút nữa để gửi lời chúc mừng năm mới đến người thân. Bạn hãy viết chương trình xác định số phút còn lại khi nhập giá trị giờ h (
0 <= h < 24) và giá trị phút (0 <= p <= 60) -
Viết chương trình nhập số nguyên dương n >=0; sau đó hiển thị câu ”Cac so khong giam” nếu số ki đứng ngay trước nhỏ hơn hoặc bằng số k(i+1) đứng ngay sau hoặc n chỉ có 1 số ; ngược lại thì hiển thị câu “ Cac so tang giam”. Quá trình xét các ký số được thực hiện từ trái qua phải.
Ví dụ:
n = 125778 thi hiển thị câu "Cac so khong giam".
n = 125478 thì hiển thị câu "Cac so tang giam". -
Cho n là số nguyên dương và s là tổng các ước số của nó(kể cả số 1) Biết rằng n là deficient (nếu s < n) n là perfect (nếu s = n) n là abundant (nếu s > n) Viết chương trình nhập vào 2 số nguyên dương m và n sau đó hiện thị phân loại (deficient, perfect, abundant) của các số từ đến n. Ví dụ: Số 8 là deficient vì 1 + 2 + 4 < 8 Số 6 là perfect vì 1 + 2 + 3 = 6 Số 12 là abundant vì 1 + 2 + 4 + 6 > 12
-
Tìm số Harshad Viết chương trình tìm số Harshad trong khoảng từ m đến n.Nếu tìm thấy thì in ra số đó và nếu không tìm thấy thì in “Notfound” Định nghĩa : số Harshad là số chia hết cho tổng các chữ số tạo nên nó. Ví dụ 18 là số Harshad vì 1 + 8 = 9 và 18 chia 9 bằng 2
-
Tìm số Automorphic Viết chương trình tìm số Automorphic trong khoảng từ m đến n. Nếu tìm thấy in ra số đó và nếu không tìm thấy thì in “ NotFound” Định nghĩa: số Automorphic là số mà bình phương của nó kết thúc bằng chính nó. Ví dụ 5 bình phương = 25 6 bình phương = 36 25 bình phương = 625 76 bình phương = 5776