Thực tế khi cho học sinh được làm quen với ngôn ngữ lậptrình C++ là một ngôn ngữ lập trình có tính cấu trúc chặt chẽ từcấu trúc dữ liệu, cấu trúc các câu lệnh đến cấu trúc một chươngtrìn
Trang 11 MỞ ĐẦU
1.1 Lí do chọn đề tài.
Xuất phát từ thực tiễn dạy học tại trường THPT Mai AnhTuấn Thực tế khi cho học sinh được làm quen với ngôn ngữ lậptrình C++ là một ngôn ngữ lập trình có tính cấu trúc chặt chẽ từcấu trúc dữ liệu, cấu trúc các câu lệnh đến cấu trúc một chươngtrình Tuy nhiên do mới là bước đầu học sinh được biết đến lậptrình và ngôn ngữ lập trình, hầu hết học sinh rất khó khăn vìnhiều lý do như: Phải có tư duy thuật toán tốt, đòi hỏi tư duynhiều, có nhiều thuật ngữ bằng tiếng Anh… nên việc vận dụngcác câu lệnh, các cấu trúc điều khiển làm sao để từ các thuậttoán có thể xây dựng được chương trình thì đa phần học sinhcòn gặp không ít khó khăn Cấu trúc lặp là một cấu trúc quantrọng trong các cấu trúc cơ bản của ngôn ngữ lập trình mà họcsinh bắt buộc phải nắm được Với những lý do trên tôi chọn đề
tài cho sáng kiến kinh nghiệm là “Rèn luyện kỹ năng sử dụng cấu trúc lặp trong các bài toán lập trình tin học lớp 11” nhằm cung cấp cho học sinh những kiến thức khái quát hơn
về cấu trúc lặp và rèn luyện kỹ năng lập trình cho học sinhthông qua một số bài toán cụ thể Bồi dưỡng học sinh tham gia
kì thi chọn học sinh giỏi các cấp môn Tin học Qua đó giúp các
em yêu thích và hứng thú học tập môn Tin học hơn
1.2 Mục đích nghiên cứu.
- Để làm tốt công tác giảng dạy trên lớp và luyện thi họcsinh giỏi môn tin học cấp trung học phổ thông Góp phần đổimới phương pháp dạy học sinh giỏi môn Tin học theo hướngphát huy tính tích cực, chủ động và sáng tạo của học sinh giúphọc sinh tiếp thu tri thức một cách có hiệu quả
- Góp phần gây hứng thú học tập môn Tin học cho học sinhtham gia thi chọn học sinh giỏi, tránh việc học thụ động, họcvẹt Giúp học sinh lĩnh hội tri thức một cách khoa học, củng cố
và khắc sâu kiến thức
Trang 2- Qua đề tài này tôi mong muốn cung cấp cho học sinhnhững vấn đề mà các em đang gặp phải về kĩ năng sử dụng cấutrúc lặp trong khi lập trình giúp các em chủ động hơn trong họctập, tích luỹ kiến thức, kỹ năng lập trình
1.3 Đối tượng nghiên cứu.
Học sinh các lớp 11 trường trung học phổ thông Mai AnhTuấn
1.4 Phương pháp nghiên cứu.
- Nghiên cứu các tài liệu, bài giảng về phương pháp dạyhọc Tin học Nghiên cứu các tài liệu về ngôn ngữ lập trình C++.Kiểm chứng bằng cách tiến hành giảng dạy ở các lớp nhằmkiểm tra giả thuyết khoa học, minh họa tính khả thi và tính hiệuquả của giải pháp đề xuất
- Trao đổi với đồng nghiệp, tham khảo ý kiến giáo viêncùng bộ môn Liên hệ thực tế trong nhà trường, áp dụng và đúcrút kinh nghiệm qua quá trình giảng dạy Thông qua việc giảngdạy trực tiếp học sinh lớp 11 và học sinh tham gia thi chọn họcsinh giỏi môn Tin học tại trường THPT Mai Anh Tuấn năm học2021-2022
2 NỘI DUNG SÁNG KIẾN KINH NGHIỆM
2.1 Cơ sở lí luận của sáng kiến kinh nghiệm.
Cấu trúc lặp là một trong ba cấu trúc cơ bản trong lậptrình có cấu trúc Tuy nhiên trước một bài toán lập trình tin học
có các thao tác lặp đi lặp lại nhiều học sinh thường lúng túng,không biết nên lựa chọn và sử dụng câu lệnh lặp nào cho phùhợp với yêu cầu bài toán và tối ưu hóa thuật toán? Một số họcsinh khá, giỏi có thể sử dụng cấu trúc lặp để mô tả nhưng đa sốchưa biết tối ưu hóa thuật toán để giảm số lần lặp và điều đógây tâm lý chán nản cho các em Với tình hình ấy để giúp họcsinh có kĩ năng tốt hơn trong việc sử dụng cấu trúc lặp để mô tảthuật toán, thì người giáo viên cần tăng cường rèn luyện cho
Trang 3học sinh kĩ năng sử dụng cấu trúc lặp từ các các bài toán cơbản quen thuộc mà các em đã biết, khai thác các yếu tố đặctrưng của một số bài toán cơ bản để tìm thuật toán cho các bàitoán mới, dựa vào đặc điểm cụ thể của từng bài toán để tối ưuhóa thuật toán Việc rèn luyện kĩ năng lập trình cho học sinh từnhững bài toán cơ bản để xây dựng thuật toán cho các bài toántương tự hoặc các bài toán mở rộng từ các bài toán cơ bản đó làmột quá trình giúp học sinh rèn luyện kỹ năng lập trình
2.2 Thực trạng vấn đề trước khi áp dụng sáng kiến kinh nghiệm
Trong quá trình giảng dạy, khi đưa ra ví dụ áp dụng cho
các câu lệnh for và câu lệnh while, tương ứng với các ví dụtrong sách giáo khoa đã giới thiệu, tôi nhận thấy học sinh khóphân biệt như thế nào là lặp, cái gì cần lặp và khi nào thì kếtthúc việc lặp, do đó khi gặp các bài toán cần sử dụng cấu trúclặp để giải quyết đa số học sinh không biết cách làm, hoặc tìm
ra cách làm nhưng không biết làm thế nào để chuyển từ thuậttoán thành chương trình Những điều này một phần tác độnglàm cho học sinh ngại học lập trình
2.3 Giải quyết vấn đề
2.3.1 Khái niệm lặp và phân biệt 2 cấu trúc lặp.
Giáo viên đặt vấn đề cho ví dụ có liên hệ thực tế: Cần đổđầy một bình chứa 50 lít nước bằng một cái ca có dung tích là 1lít thì ta phải thực hiện lặp lại việc múc nước rồi đổ vào bình baonhiêu lần?
- Học sinh trả lời: Cần lặp lại 50 lần công việc múc đầy canước đổ vào bình
- Giáo viên hỏi: Nếu đổ với các ca không biết dung tích thìcác e có biết được số lần thực hiện công việc đổ nước không?
Đổ nước đến khi nào thì dừng việc đổ nước
Trang 4- Học sinh trả lời: Chưa biết được số lần đổ và thực hiệncông việc đổ nước cho đến khi bình đầy thì dừng việc đổ nướclại.
→ Từ ví dụ đơn giản này chúng ta có thể giúp cho các emhiểu và biết được như thế nào là lặp với số lần biết trước và sốlần chưa biết trước
Nói chung, trong một số thuật toán có những thao tác
phải thực hiện lặp đi lặp lại một số lần Một trong các đặc trưng
của máy tính là có khả năng thực hiện hiệu quả các thao tác
lặp Cấu trúc lặp mô tả thao tác lặp và được phân biệt hai loại là
lặp với số lần biết trước và lặp với số lần chưa biết trước
Các ngôn ngữ lập trình đều có các câu lệnh để mô tả cấu trúc điều khiển lặp
2.3.2 Lặp với số lần biết trước và câu lệnh For.
Ví dụ: Viết ra màn hình các số nguyên từ 1 đến 10 Mỗi số được
Trang 5- Chương trình này học sinh có thể viết được vì nó không
có gì khó khăn Tuy nhiên nếu yêu cầu đề bài là viết ra mànhình các số từ 1 đến 100 thì nếu sử dụng theo cách như trên sẽmất nhiều thời gian và gây nhàm chán.Vậy có cách nào đểchương trình viết ngắn gọn hơn mà vẫn thực hiện đúng yêu cầu
đề ra
Giải quyết vấn đề :
- Giáo viên giới thiệu cú pháp và hoạt động của câu lệnhlặp với số lần biết trước sau đó đưa ra chương trình vận dụng
câu lệnh for để giải quyết bài toán này.
Để mô tả cấu trúc lặp với số lần biết trước, C++ dùng
câu lệnh for như sau:
for (<biểu thức khởi tạo>; <biểu thức giới hạn>; <biểu thức tăng giảm>)
{
<Dãy lệnh>;
}
Trang 6Giải thích: Thực hiện vòng lặp, với số vòng lặp từ biểu thức
khởi tạo cho đến biểu thức giới hạn theo mức tăng là biểu thức tăng giảm
Lưu ý: khi sử dụng vòng lặp for cần lưu ý các điểm sau đây:
• Các tham số trong vòng lặp for có thể khuyết một hoặc vài (thậm chí là tất cả) tham số Tuy nhiên, dấu chấm phẩy là luôn bắt buộc Số bước lặp của vòng lặp for sẽ được tính như sau:
Bi
ểu thức giới hạn – Biểu thức khởi tạo
Biểu thức tăng giảm
• Nếu có nhiều lệnh chịu sự chi phối của for, thì chúng cần được đặt trong dấu khối lệnh.
• Ta có thể thực hiện việc khai báo biến trực tiếp bên trong dấu ngoặc đơn của vòng lặp for.
Chương trình được viết như sau:
Trang 7Bài 1: Tính và đưa kết quả ra màn hình tổng
S = 1+2+3+…+100
a. Ý tưởng:
- Ban đầu khởi tạo gán tổng S ← 0
- Tiếp theo ta cho tổng S lần lượt cộng với 1,2,3…100 Hay nóicách khác S←S+i, trong đó i sẽ chạy lần lượt từ 1 đến 100.Sau khi i nhận giá trị bằng 100, vòng lặp sẽ kết thúc
b Chương trình được cài đặt như sau:
Trang 8- Dùng 1 biến đếm kiểu nguyên (dem) để đếm số lượng số lẻ.Ban đầu khởi tạo dem=0;
- Sử dụng vòng lặp for tiến với biến đếm i chạy từ 20 đến 100( vì xét trong đoạn từ 20 đến 100 ( KH:[20,100] nên ta phải xét
cả 2 đầu mút: i=20 và i=100)
- Nếu i lẻ ( i % 2 != 0) thì tăng biến đếm dem lên 1 đơn vị
b Chương trình được cài đặt như sau:
Bài 3: Viết chương trình đếm xem có bao nhiêu số chẵn, bao
nhiêu số lẻ trong khoảng từ n đến m (0<n<m<=106)
a Ý tưởng
- Dùng 2 biến đếm kiểu nguyên (d_chan, d_le) để đếm số lượng
số chẵn và số lượng số lẻ Ban đầu khởi tạo d_chan=0; d_le=0;
- Sử dụng vòng lặp for tiến hoặc lùi với biến đếm i chạy từ n+1đến m-1
- Nếu i chẵn ( i % 2 = 0) thì tăng biến d_chan lên 1 đơn vị Nếu i
lẻ ( i % 2 != 0) thì tăng biến d_le lên 1 đơn vị
b, Chương trình được cài đặt như sau:
Trang 9Bài 4: Một số có tổng các ước thực sự (là các ước không kể
chính nó) bằng chính nó được gọi là số hoàn chỉnh
Ví dụ: Số nguyên 6 có các ước thực sự là 1, 2, 3 Tổng là 1 + 2+ 3 = 6
Viết chương trình xét xem một số n (n<1012) được nhập từ bànphím có phải là số hoàn chỉnh không
a Ý tưởng
- Dùng biến n lưu số cần xét
- Biến S lưu trữ tổng các ước thực sự, khởi tạo S= 0;
- Sử dụng vòng lặp for với biến đếm i chạy từ 1 đến n-1 nếu i làước của n thì cộng thêm i vào S
- Nếu S = n thì đưa ra thông báo n là số hoàn chỉnh, ngược lạiđưa ra thông báo n không là số hoàn chỉnh
b Chương trình được cài đặt như sau:
if(s==n) cout<<n<<" la so hoan chinh";
else cout<<n<<" khong la so hoan chinh";
Trang 10n/i Nhưng giải thuật này còn có 1 trường hợp ngoại lệ là : ví dụn=9, căn của n=3 , vì ta duyệt i từ 2 đến căn của n , nghĩa i sẽ
đi từ 2 đến 3, và 9 chia hết cho 3, và 9 cũng chia hết cho 9/3 ,lúc này ước 3 sẽ bị lặp lại 2 lần Vậy nên ta phải trừ đi 3
Chương trình giải bài toán trên có thể được cài đặt lại như sau:
if(s==n) cout<<n<<" la so hoan chinh";
else cout<<n<<" khong la so hoan chinh";
return 0;
}
Bài 5:
Dãy số fibonaci được định nghĩa như sau:
Viết chương trình in ra số fibonaci thứ n (n <= 1000);
a Ý tưởng
- Nếu n <= 2, ta có f1 = f2 = 1;
- Nếu n > 2: Dựa vào công thức truy hồi của dãy fibonaci ta cóthể dẽ dàng tính được fn dựa vào fn-1 và fn-2 Sử dụng biến f đểtính fi ứng với mỗi giá trị của i (i= 3 n) , theo công thức truy hồi
ta có f = f1+f2, sau đó f1 và f2 được thay đổi giá trị để tính phần
tử tiếp theo của dãy
b Chương trình được cài đặt như sau:
Trang 11long long f,f1=1,f2=1; int n;
Bài 6: Viết chương trình xét xem một số n có phải là số nguyên
tố không (0<n<=1012) Số nguyên tố là số chỉ có 2 ước là 1 và
chính nó
a Ý tưởng:
Mọi số nguyên N nếu có ước khác 1 và chính nó thì chắc chắn
có ước trong đoạn từ 2 đến phần nguyên căn bậc 2 của N Vìvậy thay vì kiểm tra n có chia hết cho số nào trong đoạn từ 2đến n -1 hay không, ta chỉ cần kiểm tra n có chia hết cho số nàotrong đoạn từ 2 đến sqrt(n) hay không, việc làm này sẽ giúpgiảm đáng kể số lần lặp, giúp tiết kiệm thời gian thực hiệnchương trình
b Chương trình được cài đặt như sau:
for(int i=2; i<=m; i++)
if(n%i==0) return false;
return true;
}
int main(){
cout<<"Nhap n="; cin>>n;
Trang 12if(nt(n)) cout<<n<<" la so nguyen to";
else cout<<n<<" khong la so nguyen to";
return 0;
}
Kết luận: Những bài toán có tính chất thực hiện lặp lại một câu
lệnh nào đó nhiều lần, với số lần biết trước người ta gọi đây lànhững bài toán có cấu trúc lặp biết trước số lần Để giải quyết
các bài toán dạng này ta có thể sử dụng câu lệnh for để cài đặt
thuật toán
2.3.3 Lặp với số lần chưa biết trước và câu lệnh While.
Ví dụ: Xét bài toán tính tổng sau:
S=1+2+3+ +n+ cho đến khi S >200
Tình huống có vấn đề:
Ví dụ này tương tự bài tính tổng S=1+2+3+…+100 đãđược xét đến ở dạng cấu trúc lặp với số lần biết trước Nhưngđọc kĩ thì đây là một dạng khác của bài toán Ở bài toán nàycũng thực hiện việc lặp lại công việc cộng dồn vào tổng S, cónghĩa là tương tự thuật toán ở ví dụ trước
- Xuất phát, S được gán giá trị 0;
- Tiếp theo công vào tổng S một giá trị i với i = 1,2,3,4,5,
…
- Sau mỗi lần tăng i câu lệnh lặp lại là S=S+i Việc cộngnày được lặp lại một số lần Đối với bài toán này số lần lặp chưabiết trước nhưng việc cộng vào tổng S sẽ kết thúc khi điều kiện
S > 200 được thỏa mãn Nhưng ta chưa biết được câu lệnh này
sẽ được thực hiện bao nhiêu lần Vì vậy các ngôn ngữ lập trìnhcung cấp thêm câu lệnh lặp chưa biết trước số lần lặp
Giải quyết vấn đề:
Trang 13Trong c++ sử dụng câu lệnh while để giải quyết vấn đề này Cấu trúc câu lệnh while như sau:
while (<Điều kiện>)
{
<Dãy lệnh >;
}
Giáo viên giải thích: Nếu điều kiện đúng, các lệnh bên trong
vòng lặp sẽ được thực hiện cho đến khi nó nhận giá trị sai
Học sinh cần lưu ý: khi sử dụng vòng lặp while cần lưu ý các
điểm sau đây:
- Vòng lặp phải có tính dừng Nghĩa là điều kiện phải có trườnghợp sai Trong một số tình huống, người ta vẫn sử dụng vòng lặp
vô hạn, nhưng cần có cơ chế để thoát khỏi vòng lặp khi cầnthiết
- Nếu có nhiều lệnh chịu sự chi phối của while, thì chúng cần
được đặt trong dấu khối lệnh
Ở ví dụ này vòng lặp được thể hiện theo cách liệt kê nhưsau:
Bước 1 S ← 0; i ← 1;
Bước 2 Nếu S>200 thì chuyển đến bước 5;
Bước 3 S ← S + i;
Bước 4 i← i + 1 rồi quay lại bước 2.
Bước 5 Đưa S ra màn hình, rồi kết thúc.
Dựa vào thuật toán này giáo viên có thể yêu cầu học sinh
áp dụng vòng lặp while để cài đặt thuật toán
#include <bits/stdc++.h>
Trang 14i++;
} cout<<"\n Tong S= "<<s;
return 0;
}
Một số bài toán áp dụng:
Bài 1: Viết chương trình tìm ước chung lớn nhất của hai số
nguyên dương M và N Viết chương trình tìm ước chung lớn nhất
(UCLN) của hai số với yêu cầu sử dụng thuật toán Euclid.
Thuật toán Euclid:
- Nếu a chia hết cho b (a chia b dư 0) thì UCLN(a,b) bằng 0
- Nếu a chia b dư r thì UCLN(a,b) = UCLN(b,r)
a Ý tưởng
- Nhập a, b
- Lặp với điều kiện b != 0: r = a % , a=b, b=r
b Chương trình được cài đặt như sau:
#include<bits/stdc++.h>
using namespace std;
int a,b,r;
Trang 15- Tăng biến c lên 1 đơn vị
b Chương trình được cài đặt như sau:
Trang 16- Dùng 1 mảng để lưu các các bit 0 và 1 của n
- Dùng while lặp với điều kiện n>0:
- Mỗi lần lặp ta thực hiện : thêm n%2 vào mảng và n=n/2
- Duyệt từ phần tử cuối của mảng về phần tử đầu tiên của mảng
ta được hệ nhị phân của số n
b Chương trình được cài đặt như sau:
Bài 4: Hãy viết chương trình yêu cầu người dùng nhập vào một
số nằm trong khoảng từ 1 đến 100 Nếu người dùng nhập số khác thì yêu cầu nhập lại
a Ý tưởng:
- Khởi tạo n bằng 1 giá trị ngoài khoảng [1,100] mục đích là
để vòng while luôn lặp ít nhất 1 lần
- Dùng while với điều kiện (n<1 hoặc n>100)
b Chương trình được cài đặt như sau:
Trang 17Bài 5: Hãy viết chương trình yêu cầu người dùng nhập vào một
số bất kì và in số đó lên màn hình Nếu người dùng nhập vào số
0 thì thoát chương trình, ngược lại thì nhập liên tục
cout<<"Nhap 1 so bat ki :"; cin>>n;
cout<<"So vua nhap la: "; cout<<n<<endl;
Trang 18b Chương trình được cài đặt như sau:
Kết luận: Khi gặp trường hợp cần lặp lại một câu lệnh tương tự
nhau nhiều lần mà chưa biết trước số lần lặp chỉ biết điều kiện
để thực hiện câu lệnh lặp đó ta sẽ sử dụng câu lệnh while để
cài đặt thuật toán
2.3.4 So sánh giữa lệnh lặp for và while
Sau khi được tìm hiểu về 2 dạng lệnh lặp for và while.
Giáo viên yêu cầu học sinh so sánh những điểm giống nhau vàkhác nhau giữa 2 vòng lặp trong C++ Kết quả mong muốn làhọc sinh so sánh được như sau:
Vòng lặp for và vòng lặp while có những điểm giống và khác
nhau như sau:
- Giống nhau: Cả 2 vòng lặp đều sử dụng để lặp lại một
đoạn code nào đó khi điều kiện đúng Nếu điều kiện sai sẽkhông có đoạn code nào bên trong thân vòng lặp được thựchiện
- Khác nhau:
Điểm khác
nhau