[Lập trình C] Vòng lặp - loop

Posted on December 30th, 2020

Khi lập trình, có những trường hợp bạn phải viết một đoạn code lặp đi lặp lại nhiều lần. Để tránh phải viết những đoạn code lặp lại đó, ngôn ngữ lập trình C đưa ra một khái niệm, đó là Vòng lặp.

Và bài viết này sẽ giới thiệu với bạn kiến thức cơ bản về vòng lặp. Cách sử dụng vòng lặp for, while, do while và một số từ khóa để kết thúc vòng lặp như break hoặc tiếp tục vòng lặp continue.

Lý thuyết cơ bản về vòng lặp trong lập trình C

Vòng lặp là gì?

Vòng lặp là một đoạn chương trình được thực hiện lặp đi lặp lại khi một điều kiện cho trước thỏa mãn.

Có 3 cấu trúc vòng lặp cơ bản:

  • Vòng lặp for
  • Vòng lặp while
  • Vòng lặp do-while

Vòng lặp for

Cú pháp cơ bản

Vòng lặp for sẽ có cú pháp cơ bản như sau:

for (khởi tạo vòng lặp; điều kiện thực hiện vòng lặp; thay đổi cuối vòng lặp) {
	// Nội dung thực thi
}

Trong đó:

  • Khởi tạo vòng lặp: sử dụng câu lệnh gán, dùng để gán giá trị ban đầu cho các biến trong vòng lặp.
  • Kiểm tra điều kiện thực hiện vòng lặp: sử dụng biểu thức với toán tử quan hệ để kiểm tra xem khi nào vòng lặp được thực hiện.
  • Thay đổi cuối vòng lặp: tính toán lại giá trị của các biến sau mỗi lần thực thi của vòng lặp.
  • Nội dung thực thi: là một hay nhiều câu lệnh thực thi trong mỗi vòng lặp.

Ba phần của vòng lặp for được phân cách nhau bởi dấu chấm phẩy (;)

Vòng lặp sẽ được thực hiện mãi, cho đến khi điều kiện thực hiện vòng lặp không thỏa mãn mới thôi.

Ví dụ: nhập vào số tự nhiên N, in ra từ Hello world đúng N lần. Mỗi từ in trên 1 dòng.

#include <stdio.h>

int main() {
	int n, i;
	
	printf("Nhap n: ");
	scanf("%d", &n);
	
	for (i = 0; i < n; i += 1) {
		printf("Hello world\n");
	}
	
	return 0;
}

Trong ví dụ trên:

  • Khởi tạo vòng lặp: khởi tạo giá trị của biến i = 0
  • Điều kiện thực hiện vòng lặp là: i < n
  • Sau mỗi vòng lặp: thực hiện tăng i lên một đơn vị
  • Trong vòng lặp: in ra từ Hello world

Toán tử phẩy (,) trong vòng lặp

Cú pháp cơ bản:

expression1, expression2;

Ví dụ trường hợp khởi tạo biến dữ liệu:

#include <stdio.h>

int main() {
	int x, y, z;
	z = (x = 3, y = 4);
	printf("x=%d, y=%d, z=%d", x, y, z);
	// x = 3, y=4, z=4
	return 0;
}

Ví dụ này có sử dụng toán tử phẩy z = (x = 3, y = 4).

Khi dùng toán tử phẩy, mỗi biểu thức sẽ được thực hiện từ trái sang phải. Trường hợp có sử dụng toán tử gán, thì kết quả sẽ được gán bằng kết quả của biểu thức cuối cùng. Như vậy, câu lệnh trên được hiểu là gán x = 3, gán y = 4 rồi cuối cùng gán z = y.

Quay lại trường hợp vòng lặp for, mỗi một phần trong cấu trúc của vòng lặp for có thể được mở rộng thành nhiều câu lệnh bằng cách sử dụng toán tử (,).

Ví dụ:

#include <stdio.h>
main() {
	int i, j , max;
	printf("Nhập vào số lớn nhất \n");
	printf("cho bảng được in sau đây: ");
	scanf("%d", &max);

	for(i = 0, j = max; i <= max ; i++, j--)
		printf("\n%d  +  %d  =  %d", i, j, i + j);
}

Trong ví dụ trên, phần khởi tạo vòng lặp sử dụng toán tử phẩy để thực hiện 2 lệnh: gán i = 0 và gán j = max. Phần kiểm tra điều kiện thực hiện vòng lặp thực hiện việc so sánh i với max, nếu i nhỏ hơn hoặc bằng max thì vòng lặp sẽ tiếp tục thực hiện. Phần thực hiện sau mỗi vòng lặp tiếp tục sử dụng toán tử phẩy để tăng i lên 1 và giảm j đi 1 đơn vị.

Vòng lặp lồng nhau

Bạn có thể sử dụng vòng lặp bên trong một vòng lặp khác, khi đó người ta gọi là đó là vòng lặp lồng nhau.

Cú pháp cơ bản:

for(i = 1; i < max1; i++) {
	// do something
	for(j = 0; j < = max2; j++) {
		// do something
	}
	// do something
}

Ví dụ:

#include <stdio.h>

int main()
{
    int i, j, k;
    i = 0;
    printf("Enter no. of rows: ");
    scanf("%d", &i);
    printf("\n");
    for (j = 0; j < i ; j++) {
        printf("\n");
        for (k = 0; k <= j; k++) /*inner for loop*/
            printf("*");
    }
}

Vòng lặp while

Vòng lặp while có cú pháp cơ bản như sau:

while (condition is TRUE) {
	statement;
}

Nghĩa là vòng lặp trên sẽ được thực hiện khi điều kiện condition vẫn là TRUE.

Ví dụ:

#include <stdio.h>

int main()
{
    int count = 1;
    while (count <= 10) {
        printf("\n This is iteration %d\n", count);
        count++;
    }

    printf("\n The loop is completed. \n");
    return 0;
}

Vòng lặp do-while

Vòng lặp do-while có cú pháp cơ bản là:

do {
	statements;
} while (condition);

Ngược lại với vòng lặp while, vòng lặp do while sẽ thực hiện các câu lệnh trước rồi sau đó mới kiểm tra điều kiện để có tiếp tục vòng lặp hay không.

Khi condition trả về giá trị FALSE, vòng lặp do-while sẽ kết thúc.

Ví dụ:

#include <stdio.h>

int main () {
	int num1, num2;
	num2 = 0;
	do {
		printf("\nEnter a number: ");
		scanf("%d", &num1);
		printf("No. is %d", num1);
		num2++;
	} while (num1 != 0);

	printf ("\nThe total numbers entered were %d", --num2);
	return 0;
}

Một số từ khóa hay sử dụng trong vòng lặp

Từ khóa break

Từ khóa break thường được sử dụng ở trong một số trường hợp:

  • Để kết thúc 1 case trong trường hợp dùng switch
  • Để kết thúc 1 vòng lặp

Đối với vòng lặp, khi gặp từ khóa break, vòng lặp sẽ dừng lại ngay và tiếp tục với câu lệnh bên dưới vòng lặp.

Ví dụ:

#include <stdio.h>

int main()
{
    int count1, count2;
    for(count1 = 1, count2 = 0; count1 <= 100; count1++) {
        printf("Enter %d count2: ", count1);
        scanf("%d", &count2);
        if (count2 == 100) break;
    }
    return 0;
}

Trong ví dụ trên, nếu người dùng nhập vào giá trị của count2 khác 100 thì vòng lặp sẽ tiếp tục thực hiện. Cho đến khi giá trị của count2 là 100. Lúc này mệnh đề điều kiện bên trong if sẽ TRUE, nên break sẽ được thực thi. Khi đó, vòng lặp kết thúc.

Ví dụ trên tương đương với cách sử dụng vòng lặp for như sau:

#include <stdio.h>

int main()
{
    int count1, count2;
    for(count1 = 1, count2 = 0; count1 <= 100 && count2 != 100; count1++) {
        printf("Enter %d count2: ",count1);
        scanf("%d", &count2);
    }
    return 0;
}

Từ khóa continue

Từ khóa continue được dùng để bỏ qua phần còn lại bên trong vòng lặp (sau từ khóa continue), để tiếp tục với lượt lặp tiếp theo của vòng lặp.

Ví dụ:

#include <stdio.h>

int main () {
	int num;
	for(num = 1; num <= 100; num++) {
		if (num % 9 == 0)
			continue;
		printf("%d\t", num);
	}
	return 0;
}

Trong ví dụ trên, ta tạo một vòng lặp chạy từ 1 đến 100. Mỗi vòng lặp sẽ kiểm tra điều kiện nếu số num chia hết cho 9 thì sẽ continue. Hay nói cách khác là tiếp tục vòng lặp tiếp theo mà không thực hiện lệnh printf.

Từ khóa return

Từ khóa return thường được sử dụng để trả về giá trị của một hàm và kết thúc hàm đó.

Trong vòng lặp, nếu gặp từ khóa return thì vòng lặp cũng kết thúc.

Ví dụ:

#include <stdio.h>

int main() {
	int count1, count2;
	for(count1 = 1, count2 = 0; count1 <= 100; count1++) {
		printf("Enter %d count2: ",count1);
		scanf("%d", &count2);

		if (count2 == 100)
			return 0;
	}
	return 0;
}

Từ khóa goto

Cú pháp cơ bản:

goto label;

Từ khóa label dùng để nhảy ngay đến vị trí định nghĩa từ khóa label

Ví dụ:

#include <stdio.h>

int main() {
	int x;

RESTART:
	printf("Nhap x: ");
	scanf("%d", &x);

	for ( ; x < 10 ; x++) {
		if (x == 0) goto RESTART;
		if (x == 1) goto TH1;
		if (x == 2) goto TH2;
		printf("Other x=%d\n", x);
	}

TH1:
	printf("TH1\n");

TH2:
	printf("TH2\n");

	return 0;
}

Từ khóa exit

Hàm exit() dùng để kết thúc chương trình ngay lập tức. Khác với return ở chỗ là return chỉ là kết thúc 1 hàm.

Ví dụ:

#include <stdio.h>
#include <stdlib.h>

void printHello() {
	printf("Hello\n");
	exit(1);
	return;
	printf("Bye");
}

int main() {
	int x;

	for (x = 1; x < 20; x++) {
		if (x == 10)
			printHello();
		else
			printf("x=%d\n", x);
	}

	return 0;
}

Trong ví dụ trên, khi vòng lặp được thực hiện, nếu x bằng 10 thì hàm printHello() sẽ được gọi. Trong hàm printHello(), ngay sau khi lệnh printf() đầu tiên thực hiện, hàm exit(1) được gọi ngay nên chương trình kết thúc.

Bài tập thực hành về vòng lặp trong lập trình C

Bài 1

Nhập vào số tự nhiên N bất kỳ thỏa mãn (1 <= N <= 20)

  • In ra dãy các số từ 1 đến N (sử dụng vòng lặp for)
  • In ra dãy các số từ N đến 1 (sử dụng vòng lặp for)
  • In ra dãy các số tự nhiên chẵn từ 1 đến N (sử dụng vòng lặp while)
  • In ra dãy các số tự nhiên lẻ từ 1 đến N (sử dụng vòng lặp do-while)

Ví dụ: nhập vào N = 6

  • Dãy các số từ 1 đến N là: 1 2 3 4 5 6
  • Dãy các số từ N đến 1 là: 6 5 4 3 2 1
  • Dãy các số chẵn từ 1 đến N là: 2 4 6
  • Dãy các số lẻ từ 1 đến N là: 1 3 5

Phân tích bài toán

  • Số chẵn chia 2 dư 0
  • Số lẻ chia 2 dư 1

Code

#include <stdio.h>

int main() {
	int n, i;
	
	// Nhap n
	printf("Nhap vao n: ");
	scanf("%d", &n);
	
	// Kiem tra dieu kien cua n
	if (n < 1 || n > 20) {
		printf("Ban da nhap sai");
		return 0;
	}
	
	// In ra cac so tu 1 den n
	printf("\nDay cac so tu 1 den %d la:\t", n);
	for (i = 1; i <= n; i += 1) {
		printf("%d ", i);
	}
	
	// In ra cac so tu n den 1
	printf("\nDay cac so tu %d den 1 la:\t", n);
	for (i = n; i >= 1; i -= 1) {
		printf("%d ", i);
	}
	
	// In ra cac so tu nhien chan tu 1 den n
	printf("\nDay cac so chan 1 den %d la:\t", n);
	i = 1;
	while(i <= n) {
		if (i % 2 == 0)
			printf("%d ", i);
		i += 1;
	}

	// In ra cac so tu nhien le tu 1 den n
	printf("\nDay cac so le tu 1 den %d la:\t", n);
	i = 1;
	do {
		if (i % 2 == 1)
			printf("%d ", i);
		i += 1;
	} while(i <= n);
	
	return 0;
}

Bài 2

Nhập vào số tự nhiên bất kỳ thỏa mãn (1 <= N <= 50)

In ra một bảng các số từ 1 đến N với điều kiện:

  • Số cột tối đa là 5, số hàng tùy ý
  • Các hàng, các cột thẳng nhau
  • Trong mỗi ô, các số được căn lề bên phải

Ví dụ: nhập vào N = 4, kết quả là:

1 2 3 4

Ví dụ: nhập vào N = 8, kết quả là:

1 2 3 4 5
6 7 8

Ví dụ: nhập N = 20, kết quả là:

 1  2  3  4  5
 6  7  8  9 10
11 12 13 14 15
16 17 18 19 20

Phân tích bài toán

  • Để in ra 1 dãy các số thì cần dùng vòng lặp (ví dụ: for)
  • Để số cột tối đa là 5 thì sau khi in ra được 1 số chia hết cho 5 (ví dụ: 5, 10,...) thì ta sẽ in ra kí tự xuống dòng (\n)
  • Để các hàng, cột thẳng nhau và mỗi ô căn lề bên phải thì ta sẽ dùng format %2d (số chữ số tối đa là 2)

Code

#include <stdio.h>

int main() {
	int n, i;
	
	// Nhap n
	printf("Nhap vao n: ");
	scanf("%d", &n);
	
	// Kiem tra dieu kien cua n
	if (n < 1 || n > 50) {
		printf("Ban da nhap sai");
		return 0;
	}

	// In ra 1 bang tu 1 den N voi so cot toi da la 5
	for (i = 1; i <= n; i += 1) {
		printf("%2d ", i);
		if (i % 5 == 0) printf("\n");
	}
	
	return 0;
}

Bài 3

Nhập vào số tự nhiên N bất kỳ thỏa mãn (1 <= N <= 50000)

  • Tính tổng các số chẵn từ 1 đến N, rồi in ra màn hình.
  • Tính tổng các số lẻ từ 1 đến N, rồi in ra màn hình.

Ví dụ: nhập vào N = 6

  • Tổng các số chẵn từ 1 đến N là: 2 + 4 + 6 = 12
  • Tổng các số lẻ từ 1 đến N là: 1 + 3 + 5 = 9

Phân tích bài toán

  • Để duyệt hết tất cả các số thì ta sẽ dùng vòng lặp (for)
  • Kiểm tra từng số, nếu nó là chẵn thì cộng dồn vào biến ứng với tổng chẵn. Ngược lại, nếu số đó lẻ thì cộng dồn vào biến ứng với tổng lẻ
  • Với chú ý: số chẵn chia 2 dư 0, số lẻ chia 2 dư 1

Code

#include <stdio.h>

int main() {
	int n, i, tongChan = 0, tongLe = 0;
	
	// Nhap n
	printf("Nhap vao n: ");
	scanf("%d", &n);
	
	// Kiem tra dieu kien cua n
	if (n < 1 || n > 50000) {
		printf("Ban da nhap sai");
		return 0;
	}

	// Tinh tong 
	for (i = 1; i <= n; i += 1) {
		if (i % 2 == 0)
			tongChan += i;
		else 
			tongLe += i;
	}
	
	// In ket qua
	printf("Tong chan la: %d\n", tongChan);
	printf("Tong le la: %d\n", tongLe);
	
	return 0;
}

Bài 4

Nhập vào số tự nhiên N bất kỳ thỏa mãn (1 <= N <= 100000)

  • Kiểm tra xem N có phải là số nguyên tố hay không.
  • Nếu đúng thì in ra YES, ngược lại thì in ra NO.

Ví dụ, nhập vào số 9:

  • Kết quả in ra là NO vì 9 không phải là số nguyên tố

Ví dụ, nhập vào số 13:

  • Kết quả in ra là YES vì 13 là số nguyên tố

Phân tích bài toán

  • Số nguyên tố là số tự nhiên lớn hơn 1, chỉ chia hết cho 1 và chính nó.
  • Do đó, nếu số đó bằng 1 thì suy ra không phải số nguyên tố
  • Nếu số đó bằng 2 thì là số nguyên tố
  • Các trường hợp còn lại, cần phải kiểm tra xem trong các số từ 1 đến n. Liệu n có chia hết cho số nào hay không. Nếu tìm thấy thì chứng tỏ, n không phải số nguyên tố. Ngược lại n là số nguyên tố.

Code

Cách 1: sử dụng vòng lặp, if-else và break

#include <stdio.h>

int main() {
	int n, i, laSoNguyenTo;

	// Nhap n
	printf("Nhap vao n: ");
	scanf("%d", &n);

	// Kiem tra dieu kien cua n
	if (n < 1 || n > 100000) {
		printf("Ban da nhap sai");
	}
	else if (n == 1) {
		printf("NO");
	} 
	else if (n == 2) {
		printf("YES");
	} 
	else {
		laSoNguyenTo = 1;
		for (i = 2; i < n; i += 1) {
			if (n % i == 0) {
				laSoNguyenTo = 0;
			}
		}
		if (laSoNguyenTo)
			printf("YES");
		else
			printf("NO");
	}

	return 0;
}

Cách 2: sử dụng vòng lặp, if và return

#include <stdio.h>

int main() {
	int n, i;

	// Nhap n
	printf("Nhap vao n: ");
	scanf("%d", &n);

	// Kiem tra dieu kien cua n
	if (n < 1 || n > 100000) {
		printf("Ban da nhap sai");
		return 0;
	}

	// Kiem tra
	if (n == 1) {
		printf("NO");
		return 0;
	}

	if (n == 2) {
		printf("YES");
		return 0;
	}

	for (i = 2; i < n; i += 1) {
		if (n % i == 0) {
			printf("NO");
			return 0;
		}
	}

	printf("YES");
	return 0;
}