CHƯƠNG 3: LẬP TRÌNH CẤU TRÚC TRONG C++
Tổng quan về cấu trúc điều khiển trong C++
Như bạn đã biết, khi một chương trình C++ được chạy, CPU sẽ bắt đầu thực thi các câu lệnh ở vị trí đầu hàm main(), thực thi các câu lệnh tuần tự từ trên xuống dưới, kết thúc chương trình ở cuối hàm main().
Trong thực tế, nếu thực thi một cách tuần tự như vậy, sẽ có rất nhiều vấn đề không thể giải quyết.
Ví dụ về chương trình thực hiện một chức năng nào đó dựa trên dữ liệu của người dùng, hoặc chương trình yêu cầu thực hiện lặp lại một công việc nào đó. Lúc này, chúng ta cần can thiệp và thay đổi luồng xử lý của chương trình
Vì vậy, ngôn ngữ C++ cung cấp các câu lệnh điều khiển (control flow statements) cho phép lập trình viên thay đổi luồng xử lý của chương trình. Bài học này, mình sẽ giới thiệu một cách tổng quan về các câu lệnh điều khiển trong C++.
Câu lệnh dừng (halt)
Câu lệnh điều khiển dừng (halt) là một cấu trúc cơ bản nhất, nó yêu cầu chương trình ngừng làm việc ngay lập tức.
Trong C++, câu lệnh dừng được thực hiện thông qua hàm exit() trong thư viện cstdlib. Hàm exit() nhận vào một số nguyên và nó sẽ được trả về cho hệ điều hành như một mã kết thúc chương trình, tương tự như giá trị trả về của hàm main.
Ví dụ chương trình sử dụng hàm exit():
#include <cstdlib> // needed for exit()
#include <iostream>
using namespace std;
int main()
{
cout << 1;
exit(0); // terminate and return 0 to operating system
// The following statements never execute
cout << 2;
return 0;
}
1234567891011121314
Khi gặp câu lệnh exit(0); chương trình sẽ dừng ngay lập tức và trả về giá trị 0 cho hệ điều hành.
Câu lệnh nhảy (Jumps)
Câu lệnh nhảy (jumps) giúp CPU nhảy đến thực thi một dòng lệnh khác. Các từ khóa sử dụng cho cấu trúc nhảy: goto, break, continue. Những từ khóa này sẽ được giới thiệu trong những bài học tiếp theo.
Lời gọi hàm cũng hoạt động như một câu lệnh nhảy. Khi một hàm được gọi, CPU nhảy lên câu lệnh đầu tiên của hàm được gọi. Khi hàm được gọi kết thúc, CPU quay lại câu lệnh sau lời gọi hàm.
Cấu trúc rẽ nhánh có điều kiện (Conditional branches)
Cấu trúc rẽ nhánh có điều kiện (Conditional branches) làm chương trình thay đổi hướng thực thi dựa trên giá trị của biểu thức điều kiện (hoặc các mệnh đề).
Tiêu biểu cho cấu trúc rẽ nhánh là câu lệnh if:
int main()
{
// do A
if (expression)
// do B
else
// do C
// do D
}
1234567891011
Nếu expression là đúng (true), thứ tự thực thi của chương trình sẽ là A – B – D. Nếu expression là sai (false), thứ tự sẽ là A – C – D.
Từ khóa switch…case… cũng là một cấu trúc rẽ nhánh có điều kiện.
Cấu trúc vòng lặp (Loops)
Cấu trúc vòng lặp (loops) giúp chương trình thực hiện lặp lại một khối lệnh, đến khi không còn thỏa mãn điều kiện lặp.
int main()
{
//do A
//do B 0 or more times
//do C
}
1234567
Chương trình trên có thể thực hiện theo hướng ABC, ABBC, ABBBC, ABBB...BBBC, hoặc cũng có thể là AC, tùy vào điều kiện lặp của chương trình.
Ngôn ngữ C++ cung cấp 4 loại vòng lặp: while, do while, for và for each (C++ 11). Mình sẽ nói rõ về nó trong những bài tiếp theo.
Xử lý ngoại lệ (Exceptions handling)
Ngoại lệ (exceptions) là một cơ chế xử lý lỗi xảy ra bên trong hàm. Nếu một lỗi xảy ra bên trong hàm, hàm đó sẽ ném ra một ngoại lệ (exception). Lúc này, chương trình sẽ nhảy đến khối lệnh chuyên dùng để xử lý ngoại lệ có kiểu tương ứng với ngoại lệ được hàm ném ra.
Exception Handling (xử lý ngoại lệ) trong C++ được xây dựng dựa trên 3 từ khóa là: try, catch, và throw. Nó là một tính năng cao cấp của ngôn ngữ C++, nên nó sẽ được đề cập ở những bài nâng cao về sau.
Câu điều kiện If
Câu điều kiện If là loại cơ bản nhất trong cấu trúc rẽ nhánh có điều kiện. Cấu trúc câu điều kiện If được mô tả bên dưới:
If thiếu:
if (condition) // nếu condition là true
statement; // thực thi câu lệnh này
If đủ:
if (condition) // nếu condition là true
statement1; // thực thi câu lệnh này
else
statement2; // nếu condition là false, thực thi câu lệnh này
Xét cú pháp câu điều kiện If bên trên, nếu condition là một mệnh đề true, statement1 sẽ được thực thi, ngược lại thì statement2 sẽ được thực thi.
Ví dụ về chương trình kiểm tra đăng nhập đơn giản sử dụng câu điều kiện if:
#include <iostream>
#include <string>
using namespace std;
int main()
{
const string PASSWORD("howkteam.com");
string password;
cout << "Enter password: ";
getline(cin, password);
if (password == PASSWORD)
cout << "Login succeed!" << endl;
else
cout << "Login failed!" << endl;
return 0;
}
1234567891011121314151617181920
Outputs:
Nếu bạn không nhập đúng password là “howkteam.com”, chương trình sẽ thông báo “Login failed!”. Ngược lại sẽ thông báo "Login succeed!".
Câu điều kiện If với nhiều dòng lệnh (If with multiple statements)
Lưu ý rằng dưới câu lệnh if hoặc else chỉ có duy nhất một câu lệnh được thực thi. Nếu bạn muốn thực thi nhiều câu lệnh ở dưới if hoặc else bạn phải sử dụng khối lệnh (block).
#include <iostream>
#include <string>
using namespace std;
int main()
{
const string PASSWORD("howkteam.com");
string password;
cout << "Enter password: ";
getline(cin, password);
if (password == PASSWORD)
{
cout << "Login succeed!" << endl;
cout << "Hello howkteam.com!" << endl;
cout << "Free education!" << endl;
// ...
}
else
{
cout << "Login failed!" << endl;
cout << "Hello howkteam.com!" << endl;
cout << "Free education!" << endl;
// ...
}
return 0;
}
123456789101112131415161718192021222324252627282930
Outputs:
Kinh nghiệm: Nên đặt các câu lệnh của câu điều kiện If bên trong cặp dấu ngoặc nhọn {}, dù nó chỉ có một dòng lệnh. Điều này giúp chương trình rõ ràng hơn, dễ hiểu hơn.
Chuỗi các câu điều kiện If (Chaining if statements)
Nếu muốn kiểm tra nhiều hơn 2 trường hợp trong một câu điều kiện If, bạn có thể sử dụng cấu cú pháp “if … else if …”:
if (condition)
{
// do A
}
else if (another_condition)
{
// do B
}
else if (one_more_condition)
{
// do C
}
else
{
// do D
}
1234567891011121314151617
Ví dụ về chương trình sử dụng chuỗi các câu điều kiện if:
#include <iostream>
using namespace std;
int main()
{
cout << "Nhap so ban yeu thich (1, 2, 3): ";
int n;
cin >> n;
if (n == 1)
cout << "Ban that dep trai!" << endl;
else if (n == 2)
cout << "Ban qua dep trai!" << endl;
else if (n == 3)
cout << "Ban dep trai vo dich vu tru!" << endl;
else
cout << "Du lieu chua chinh xac!" << endl;
return 0;
}
123456789101112131415161718192021
Outputs:
Toán tử logic với câu điều kiện If (Using logical operators with if statements)
Bạn có thể sử dụng toán tử logic (AND, OR, NOT, …) vào mệnh đề so sánh để kiểm tra nhiều điều kiện cùng một lúc. Toán tử logic đã được hướng dẫn chi tiết trong bài TOÁN TỬ QUAN HỆ, LOGIC, BITWISE, MISC & ĐỘ ƯU TIÊN TOÁN TỬ TRONG C++ (Operators).
Ví dụ:
#include <iostream>
#include <string>
using namespace std;
int main()
{
const string USERNAME("kteam");
const string PASSWORD("howkteam.com");
string userName;
string password;
cout << "Enter username: ";
getline(cin, userName);
cout << "Enter password: ";
getline(cin, password);
if ((userName == USERNAME) && (password == PASSWORD))
{
cout << "Login succeed!" << endl;
}
else
{
cout << "Login failed!" << endl;
}
return 0;
}
1234567891011121314151617181920212223242526272829
Outputs:
Bạn có thể xem lại bài TOÁN TỬ QUAN HỆ, LOGIC, BITWISE, MISC & ĐỘ ƯU TIÊN TOÁN TỬ TRONG C++ (Operators).để biết được cách thức hoạt động các toán tử logic.
Toán tử điều kiện (Conditional operator)
Cấu trúc câu điều kiện if/else:
if (condition) // nếu condition là true
expression1; // thực thi câu lệnh này
else
expression2; // nếu condition là false, thực thi câu lệnh này
Hoặc :
if (condition) // nếu condition là true
x = value1; // x = value 1
else
x = value2; // nếu condition là false, x = value 2
Viết lại dưới dạng toán tử điều kiện ( ?: ):
(condition) ? expression1 : expression2;
Hoặc:
x = (condition) ? value1 : value2;
Toán tử điều kiện “?:” là toán tử 3 ngôi duy nhất trong C++ (vì nó chứa 3 toán hạng). Có thể dùng để thay thế câu lệnh if/else cơ bản.
Chú ý: Các toán hạng của toán tử điều kiện không phải là một câu lệnh, nên sẽ không chứa dấu chấm phẩy “;”.
Ví dụ 1:
int a(10), b(20), max;
if (a > b)
{
max = a;
}
else
{
max = b;
}
12345678910
Bạn có thể viết lại ở dạng toán tử điều kiện:
int a(10, b(20);
int max = (a > b) ? a : b;
123
Ví dụ 2:
if (1 > 0)
{
cout << 1 << endl;
}
else
{
cout << 0 << endl;
}
123456789
Bạn có thể viết lại ở dạng toán tử điều kiện:
// Cách 1
(1 > 0) ? (cout << 1 << endl) : (cout << 0 << endl);
// Cách 2
cout << ((1 > 0) ? 1 : 0) << endl;
12345
Kinh nghiệm: Khi viết các câu lệnh có nhiều toán tử, luôn sử dụng dấu ngoặc tròn để hạn chế sai sót về độ ưu tiên của toán tử.
Bạn có thể xem lại bài TOÁN TỬ QUAN HỆ, LOGIC, BITWISE, MISC & ĐỘ ƯU TIÊN TOÁN TỬ TRONG C++ (Operators) để nắm rõ hơn về độ ưu tiên toán tử.
Toán tử điều kiện tương đương với một biểu thức
Toán tử điều kiện “?:“ có thể là một biểu thức (expression), trong khi câu điều kiện if/else chỉ là một câu lệnh (statements).
Ví dụ:
bool bIsVip = true;
// Initializing a const variable
const double dPrice = bIsVip ? 1000 : 500;
12345
Trong ví dụ trên, không thể dùng câu điều kiện if/else để thay thế. Vì một hằng số phải được khởi tạo giá trị tại thời điểm khai báo.
Câu điều kiện Switch (Switch statements)
Bên dưới là chương trình sử dụng chuỗi các câu điều kiện If (Chaining if statements) để kiểm tra giá trị của một biến, khá dài và khó đọc:
#include <iostream>
using namespace std;
const int SUNDAY = 1;
const int MONDAY = 2;
const int TUESDAY = 3;
const int WEDNESDAY = 4;
const int THURSDAY = 5;
const int FRIDAY = 6;
const int SATURDAY = 7;
int main()
{
int dayOfWeek(TUESDAY);
if (dayOfWeek == SUNDAY)
cout << "Sunday" << endl;
else if (dayOfWeek == MONDAY)
cout << "Monday" << endl;
else if (dayOfWeek == TUESDAY)
cout << "Tuesday" << endl;
else if (dayOfWeek == WEDNESDAY)
cout << "Wednesday" << endl;
else if (dayOfWeek == THURSDAY)
cout << "Thursday" << endl;
else if (dayOfWeek == FRIDAY)
cout << "Friday" << endl;
else if (dayOfWeek == SATURDAY)
cout << "Saturday" << endl;
else
cout << "Unknown" << endl;
return 0;
}
1234567891011121314151617181920212223242526272829303132333435
Outputs:
Câu điều kiện if/else trong chương trình trên có thể viết lại dưới dạng câu điều kiện switch:
#include <iostream>
using namespace std;
const int SUNDAY = 1;
const int MONDAY = 2;
const int TUESDAY = 3;
const int WEDNESDAY = 4;
const int THURSDAY = 5;
const int FRIDAY = 6;
const int SATURDAY = 7;
int main()
{
int dayOfWeek(TUESDAY);
switch (dayOfWeek)
{
case SUNDAY:
cout << "Sunday" << endl;
break;
case MONDAY:
cout << "Monday" << endl;
break;
case TUESDAY:
cout << "Tuesday" << endl;
break;
case WEDNESDAY:
cout << "Wednesday" << endl;
break;
case THURSDAY:
cout << "Thursday" << endl;
break;
case FRIDAY:
cout << "Friday" << endl;
break;
case SATURDAY:
cout << "Saturday" << endl;
break;
default:
cout << "Unknown" << endl;
break;
}
return 0;
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546
Kết quả cho ra từ 2 cách viết trên là như nhau. Bây giờ, chúng ta sẽ cùng tìm hiểu chi tiết hơn về câu điều kiện switch.
Tổng quan
Switch statements so sánh một biến (hoặc biểu thức) kiểu số nguyên với một danh sách giá trị các số nguyên, các hằng kí tự hoặc biểu thức hằng. Mỗi giá trị trong danh sách chính là một case label (nhãn trường hợp) trong khối codes của switch. Trong khối code switch còn có thể có một default label (nhãn mặc định) có thể có hoặc không. Trong mỗi label còn chứa các khối code tương ứng.
Cấu trúc câu điều kiện switch
switch (expression)
{
case constant_1:
{
Statements;
break;
}
case constant_2:
{
Statements;
break;
}
// ...
case constant_n:
{
Statements;
break;
}
default:
{
Statements;
}
}
Nguyên tắc trong câu điều kiện switch
- Expression là một biến (hoặc biểu thức) có giá trị kiểu số nguyên (char, short, int, long, int32_t, enum, ...).
- Case labels (nhãn trường hợp) sử dụng từ khóa case, đi sau nó là một hằng số (số nguyên, các hằng kí tự hoặc biểu thức hằng). Số lượng các case labels là không giới hạn, và không có trường hợp trùng nhau giữa các case.
Ví dụ:
switch (dayOfWeek)
{
case 1:
case 1: // Không hợp lệ, vì case 1 đã tồn tại
case SUNDAY: // Không hợp lệ, vì SUNDAY tương đương với 1
};
1234567
- Default label (nhãn mặc định) sử dụng từ khóa default. Nếu không có case label nào tương ứng với giá trị của expression của switch, default label sẽ được thực thi. Default label có thể không có hoặc chỉ có 1.
- Từ khóa break có thể sử dụng hoặc không. Nếu không được sử dụng thì chương trình sẽ không kết thúc cấu trúc switch…case khi đã thực hiện hết khối code của case label có giá trị bằng với biểu thức nguyên. Thay vào đó, nó sẽ thực hiện tiếp các khối codes tiếp theo cho đến khi gặp từ khoá break hoặc dấu “}“ cuối cùng của cấu trúc switch…case.
Ví dụ:
#include <iostream>
using namespace std;
int main()
{
int month, day;
cout << "Month: ";
cin >> month;
switch (month)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
day = 30;
break;
case 4:
case 6:
case 9:
case 11:
day = 31;
break;
default:
day = 28;
}
cout << day << endl;
return 0;
}
1234567891011121314151617181920212223242526272829303132333435
Outputs:
Khai báo và khởi tạo biến bên trong case statement
Bạn có thể khai báo các biến bên trong các case statement, các biến được khai báo trong một case có thể sử dụng trong các case bên dưới.
Thông thường, bạn không thể khởi tạo biến bên trong một case. Trừ trường hợp đó là case cuối cùng, hoặc bạn đang khởi tạo bên trong một khối lệnh (block).
Ví dụ bên dưới mô tả các vấn đề về khai báo và khởi tạo biến bên trong case statements:
#include <iostream>
using namespace std;
int main()
{
int month;
cout << "Month: ";
cin >> month;
switch (month)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
// Lỗi: không được phép khởi tạo biến khi vẫn còn case bên dưới.
// int year = 2017;
int day; // Okay, có thể khai báo biến tại đây
day = 30; // Okay, có thể gán giá trị cho biến
cout << day << endl;
break;
case 4:
case 6:
case 9:
case 11:
{
int year = 2017; // Okay: có thể khởi tạo biến nếu sử dụng khối lệnh
day = 31; // Okay, có thể sử dụng biến ở những case bên dưới
cout << day << endl;
break;
}
default:
day = 28;
cout << day << endl;
}
return 0;
}
12345678910111213141516171819202122232425262728293031323334353637383940414243
Không có nhận xét nào:
Đăng nhận xét