Câu lệnh while là câu lệnh đơn giản nhất trong bốn câu lệnh vòng lặp mà C++ cung cấp và nó có một định nghĩa rất giống với câu lệnh if:
while (expression)
statement;
Một câu lệnh while được khai báo bằng từ khóa while. Khi một câu lệnh while được thực thi, biểu thức(expression) được ước tính. Nếu biểu thức ước lượng là true (khác không), câu lệnh(statement) sẽ thực thi.
Tuy nhiên, không giống như một câu lệnh if, một khi câu lệnh đã thực thi xong, luồng thực thị sẽ trở về đầu câu lệnh while và quá trình được lặp lại.
Hãy cùng xem một vòng lặp đơn giản. Chương trình sau đây in tất cả các số từ 0 đến 9:
/**
* Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
*
* @author cafedevn
* Contact: cafedevn@gmail.com
* Fanpage: https://www.facebook.com/cafedevn
* Instagram: https://instagram.com/cafedevn
* Twitter: https://twitter.com/CafedeVn
* Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
*/
#include <iostream>
int main()
{
int count{ 0 };
while (count < 10)
{
std::cout << count << ' ';
++count;
}
std::cout << "done!";
return 0;
}
Kết quả như sau:
0 1 2 3 4 5 6 7 8 9 done!
Hãy cùng xem xét kỹ hơn những gì chương trình này đang làm. Đầu tiên, count được khởi tạo bằng 0. 0<10 được đánh giá là đúng, do đó, khối lệnh thực thi. Câu lệnh đầu tiên in 0 và count tăng thêm 1. Luồng điều khiển sau đó quay trở lại đầu câu lệnh while. 1<10 được đánh giá là đúng, do đó, khối code được thực thi lại. Khối code sẽ liên tục thực thi cho đến khi count bằng 10, tại đó điểm 10 <10 sẽ được đánh giá là sai và vòng lặp sẽ thoát.
Có thể là một câu lệnh while thực thi 0 lần. Hãy xem xét chương trình sau:
#include <iostream>
int main()
{
int count{ 15 };
while (count < 10)
{
std::cout << count << ' ';
++count;
}
std::cout << "done!";
return 0;
}
Điều kiện 15 <10 ngay lập tức đánh giá thành sai, vì vậy câu lệnh while bị bỏ qua. Điều duy nhất chương trình này được in là done!.
Nội dung chính
1. Vòng lặp vô hạn
Mặt khác, nếu biểu thức luôn luôn đánh giá là đúng, vòng lặp while sẽ thực thi mãi mãi. Đây được gọi là một vòng lặp vô hạn. Dưới đây là một ví dụ về một vòng lặp vô hạn:
/**
* Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
*
* @author cafedevn
* Contact: cafedevn@gmail.com
* Fanpage: https://www.facebook.com/cafedevn
* Instagram: https://instagram.com/cafedevn
* Twitter: https://twitter.com/CafedeVn
* Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
*/
#include <iostream>
int main()
{
int count{ 0 };
while (count < 10) // this condition will never be false
{
std::cout << count << ' '; // so this line will repeatedly execute
}
return 0; // this line will never execute
}
Vì số lượng không bao giờ tăng trong chương trình này, nên count <10 sẽ luôn đúng. Do đó, vòng lặp sẽ không bao giờ chấm dứt và chương trình sẽ in “0 0 0 0 0 …” mãi mãi.
Chúng ta có thể khai báo một vòng lặp vô hạn có chủ ý như thế này:
while (true)
{
// this loop will execute forever
}
Cách duy nhất để thoát khỏi một vòng lặp vô hạn là thông qua câu lệnh return, câu lệnh break, câu lệnh exit, câu lệnh goto, một ngoại lệ được ném hoặc người dùng kill chương trình.
Các chương trình chạy cho đến khi người dùng quyết định dừng chúng đôi khi cố tình sử dụng một vòng lặp vô hạn cùng với câu lệnh return, break hoặc exit để chấm dứt vòng lặp. Người ta thường thấy loại vòng lặp này trong các ứng dụng máy chủ web chạy liên tục và các yêu cầu web dịch vụ.
2. Biến vòng lặp
Thông thường, chúng ta muốn một vòng lặp để thực hiện một số lần nhất định. Để làm điều này, người ta thường sử dụng một biến vòng lặp, thường được gọi là bộ đếm. Biến vòng lặp là biến số nguyên được khai báo cho mục đích duy nhất là đếm số lần vòng lặp đã thực hiện. Trong các ví dụ trên, số lượng biến là một biến vòng lặp.
Các biến vòng lặp thường được đặt tên đơn giản, chẳng hạn như i, j hoặc k. Tuy nhiên, việc đặt tên biến i, j hoặc k có một vấn đề. Nếu bạn muốn biết nơi nào trong chương trình của bạn sử dụng một biến vòng lặp(i,j,k) và bạn sử dụng chức năng tìm kiếm các ký tự i, j hoặc k, chức năng tìm kiếm sẽ trả về cho bạn khá là nhiều kết quả! Nhiều từ có i, j hoặc k trong đó. Do đó, một ý tưởng tốt hơn là sử dụng iii, jjj hoặc kkk làm tên biến vòng lặp của bạn. Bởi vì các tên này là duy nhất, điều này làm cho việc tìm kiếm các biến vòng lặp dễ dàng hơn nhiều và giúp chúng nổi bật như các biến vòng lặp. Một ý tưởng tốt hơn nữa là sử dụng tên biến với ý nghĩa thực, chẳng hạn như count hoặc tên cung cấp chi tiết hơn về những gì bạn đang đếm.
Cách tốt nhất là sử dụng số nguyên có dấu cho các biến vòng lặp. Sử dụng số nguyên không dấu có thể dẫn đến các vấn đề không mong muốn. Hãy xem xét các mã sau đây:
/**
* Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
*
* @author cafedevn
* Contact: cafedevn@gmail.com
* Fanpage: https://www.facebook.com/cafedevn
* Instagram: https://instagram.com/cafedevn
* Twitter: https://twitter.com/CafedeVn
* Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
*/
#include <iostream>
int main()
{
unsigned int count{ 10 };
// count from 10 down to 0
while (count >= 0)
{
if (count == 0)
{
std::cout << "blastoff!";
}
else
{
std::cout << count << ' ';
}
--count;
}
return 0;
}
Hãy xem ví dụ trên và xem bạn có thể phát hiện ra lỗi không. Nó không rõ ràng lắm.
Hóa ra, chương trình này là một vòng lặp vô hạn. Nó bắt đầu bằng cách in “10 9 8 7 6 5 4 3 2 1 blastoff!” như mong muốn, nhưng sau đó đi ra khỏi đường ray và bắt đầu đếm ngược từ 4294967295. Tại sao? Bởi vì điều kiện vòng lặp count >= 0 sẽ không bao giờ sai! Khi đếm bằng 0, 0>= 0 là đúng. Sau đó –count được thực thi và đếm tràn về 4294967295. Và vì 4294967295 > = 0, chương trình tiếp tục. Vì số ciunt không không có dấu nên nó không bao giờ có thể âm và vì không bao giờ có thể âm, nên vòng lặp sẽ không chấm dứt.
3. Lặp lại
Mỗi khi một vòng lặp thực thi, nó được gọi là một phép lặp.
Bởi vì thân vòng lặp thường là một khối và bởi vì khối đó được nhập và thoát với mỗi lần lặp, nên bất kỳ biến nào được khai báo bên trong thân vòng lặp đều được tạo và sau đó bị hủy với mỗi lần lặp. Trong ví dụ sau, biến x sẽ được tạo và hủy 5 lần:
#include <iostream>
int main()
{
int count{ 1 };
int sum{ 0 }; // sum is declared up here because we need it later (beyond the loop)
while (count <= 5) // iterate 5 times
{
int x{}; // x is created here with each iteration
std::cout << "Enter integer #" << count << ':';
std::cin >> x;
sum += x;
// increment the loop counter
++count;
} // x is destroyed here with each iteration
std::cout << "The sum of all numbers entered is: " << sum << '\n';
return 0;
}
Đối với các biến cơ bản, điều này là tốt. Đối với các biến không cơ bản (như structs và class), điều này có thể gây ra vấn đề về hiệu năng. Do đó, bạn có thể muốn xem xét việc xác định các biến không cơ bản trước vòng lặp. Đây là một trong những trường hợp bạn có thể khai báo một biến trước khi sử dụng lần đầu tiên.
Lưu ý rằng số lượng biến được khai báo bên ngoài vòng lặp. Điều này là cần thiết bởi vì chúng ta cần giá trị để duy trì trên các lần lặp (không bị hủy với mỗi lần lặp).
Thông thường, chúng ta muốn làm một cái gì đó mỗi lần lặp, chẳng hạn như in một dòng mới. Điều này có thể dễ dàng được thực hiện bằng cách sử dụng toán tử ++ trên bộ đếm của chúng ta:
/**
* Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
*
* @author cafedevn
* Contact: cafedevn@gmail.com
* Fanpage: https://www.facebook.com/cafedevn
* Instagram: https://instagram.com/cafedevn
* Twitter: https://twitter.com/CafedeVn
* Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
*/
#include <iostream>
// Iterate through every number between 1 and 50
int main()
{
int count{ 1 };
while (count <= 50)
{
// print the number (pad numbers under 10 with a leading 0 for formatting purposes)
if (count < 10)
{
std::cout << "0" << count << ' ';
}
else
{
std::cout << count << ' ';
}
// if the loop variable is divisible by 10, print a newline
if (count % 10 == 0)
{
std::cout << '\n';
}
// increment the loop counter
++count;
}
return 0;
}
Chương trình này tạo ra kết quả:
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50
4. Vòng lặp lồng nhau
Cũng có thể lồng các vòng lặp bên trong các vòng khác. Trong ví dụ sau, mỗi vòng lặp bên trong và vòng lặp bên ngoài đều có bộ đếm riêng. Tuy nhiên, lưu ý rằng biểu thức vòng lặp bên trong cũng sử dụng bộ đếm của vòng lặp bên ngoài!
/**
* Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
*
* @author cafedevn
* Contact: cafedevn@gmail.com
* Fanpage: https://www.facebook.com/cafedevn
* Instagram: https://instagram.com/cafedevn
* Twitter: https://twitter.com/CafedeVn
* Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
*/
#include <iostream>
// Loop between 1 and 5
int main()
{
int outer{ 1 };
while (outer <= 5)
{
// loop between 1 and outer
int inner{ 1 };
while (inner <= outer)
{
std::cout << inner++ << ' ';
}
// print a newline at the end of each row
std::cout << '\n';
++outer;
}
return 0;
}
Chương trình này in ra:
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5