1. Trang chủ
  2. » Giáo Dục - Đào Tạo

(SKKN 2022) giúp học sinh tạo dữ liệu đầu vào, cài đặt chương trình tối ưu và khắc phục những sai lầm thường gặp khi làm việc với kiểu dữ liệu xâu trong ngôn ngữ lập trình c++

20 6 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 20
Dung lượng 265,52 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

SỞ GIÁO DỤC VÀ ĐÀO TẠO THANH HOÁ TRƯỜNG THPT THỌ XUÂN 5 SÁNG KIẾN KINH NGHIỆM TÊN ĐỀ TÀI GIÚP HỌC SINH TẠO DỮ LIỆU ĐẦU VÀO, CÀI ĐẶT CHƯƠNG TRÌNH TỐI ƯU VÀ KHẮC PHỤC NHỮNG SAI LẦM THƯỜNG

Trang 1

SỞ GIÁO DỤC VÀ ĐÀO TẠO THANH HOÁ

TRƯỜNG THPT THỌ XUÂN 5

SÁNG KIẾN KINH NGHIỆM

TÊN ĐỀ TÀI GIÚP HỌC SINH TẠO DỮ LIỆU ĐẦU VÀO, CÀI ĐẶT CHƯƠNG TRÌNH TỐI ƯU VÀ KHẮC PHỤC NHỮNG SAI LẦM THƯỜNG GẶP KHI LÀM VIỆC VỚI KIỂU DỮ LIỆU

XÂU TRONG NGÔN NGỮ LẬP TRÌNH C++.

Người thực hiện: Lê Thị Hạnh

Chức vụ: Giáo viên SKKN thuộc lĩnh vực (môn): Tin học

THANH HOÁ NĂM 2022

Trang 2

Mục lục

Trang 3

Ở ĐẦU

1.1 Lý do chọn đề tài

C++ là ngôn ngữ lập trình khá phổ biến, có kiểu dữ liệu tĩnh và hỗ trợ hầu hết các phương pháp lập trình Dữ liệu kiểu xâu trong C++ phức tạp hơn khá nhiều so với dữ liệu kiểu xâu trong Pascal, việc vận dụng linh hoạt các thao tác

xử lí kiểu dữ liệu này vào giải quyết các bài toán liên quan không phải dễ Bên cạnh đó một số thói quen sử dụng các thao tác xử lý kiểu xâu trong ngôn ngữ lập trình pascal đã làm cho các em vận dụng sai khi giải các bài tập trong C++ một cách đáng tiếc, cùng với đó là tài liệu tham khảo phổ thông chính thống về ngôn ngữ lập trình C++ còn khá hạn chế

Với mong muốn giúp học sinh giải quyết tốt hơn các bài tập về xâu và hiểu biết sâu sắc kiểu dữ liệu xâu trong ngôn ngữ lập trình C++, tôi mạnh dạn trình

bày sáng kiến kinh nghiệm: “ Giúp học sinh tạo dữ liệu đầu vào, cài đặt chương trình tối ưu và khắc phục những sai lầm thường gặp khi làm việc với kiểu dữ liệu xâu trong ngôn ngữ lập trình C++ ” để trao đổi cùng đồng nghiệp.

1.2 Mục đích nghiên cứu

Trong phạm vi đề tài của mình tôi muốn đưa ra ý tưởng giải quyết, cài đặt chương trình tối ưu giải quyết một số bài toán cụ thể, qua đó chỉ ra những sai lầm học sinh thường mắc phải khi sử dụng một số thao tác xử lý xâu và định hướng một số bài tập về kiểu xâu Các thao tác và bài tập tuy không phải mới nhưng khi hiểu đúng về kiểu xâu trong C++ thì hiệu quả thuật toán nâng lên rõ rệt Từ đó học sinh có thể phân dạng được các bài tập về xâu và sử dụng các thao tác xử lý xâu một cách nhuần nhuyễn Cài đặt được các chương trình tối ưu cho các bài tập xâu, rèn luyện tư duy và phong cách lập trình Cũng qua đề tài, tôi muốn cùng đồng nghiệp trao đổi, trau dồi chuyên môn nhằm góp phần nâng cao trình độ chuyên môn nghiệp vụ và khả năng mở rộng kiến thức

1.3 Đối tượng nghiên cứu

Đề tài này được áp dụng đối với học sinh khá và giỏi với nhiệm vụ chủ yếu

là ôn thi học sinh giỏi và bồi dưỡng kiến thức cho học sinh yêu thích môn tin

1.4 Phương pháp nghiên cứu.

Để hoàn thành đề tài này, tôi đã tiến hành áp dụng một số phương pháp nghiên cứu sau: Phương pháp đặt vấn đề - giải quyết vấn đề, Phương pháp phân tích tổng hợp,Phương pháp so sánh đối chiếu, Phương pháp thực nghiệm

2 NỘI DUNG CỦA SÁNG KIẾN KINH NGHIỆM

2.1 Cơ sở lí luận của sáng kiến kinh nghiệm.

Giáo dục tin học đóng vai trò chủ đạo trong việc chuẩn bị cho học sinh khả năng tìm kiếm, tiếp nhận, mở rộng tri thức và sáng tạo trong thời đại cách mạng công nghiệp lần thứ tư và toàn cầu hoá Tin học có ảnh hưởng lớn đến

Trang 4

cách sống, cách suy nghĩ và hành động của con người, là công cụ hiệu quả hỗ trợ biến việc học thành tự học suốt đời.[1]

Căn cứ vào những quan điểm, định hướng trên mục tiêu của môn Tin học,

là phải cung cấp những tri thức cơ bản, làm nền tảng để học sinh có thể tiếp tục

đi sâu vào tìm hiểu và xây dựng khoa học Tin học hoặc tiếp thu những tri thức của các lĩnh vực kĩ thuật công nghệ tiên tiến, nhất là các lĩnh vực của công nghệ thông tin

2.2 Thực trạng vấn đề trước khi áp dụng sáng kiến kinh nghiệm.

2.2.1 Về phía Phụ huynh học sinh.

Môn Tin học là môn học không được đưa vào thi tốt nghiệp hoặc xét các trường Cao đẳng, Đại học Chính vì vậy đa phần không được phụ huynh đồng tình khi con mình được lựa chọn vào đội tuyển Tin học phải đầu tư thời gian để tìm hiểu nó

2.2.2 Về phía Giáo viên.

Tin học 11 là một lĩnh vực khó truyền tải, Không phải Giáo viên có chuyên môn tốt sẽ đào tạo được học sinh Giỏi, mà Giáo viên có chuyên môn tốt phải đồng hành với việc có phương pháp giảng dạy lập trình tốt Có sự đánh giá đúng

về điểm mạnh, điểm yếu lập trình của từng học sinh, những sai lầm về lập trình từng em hay mắc phải

2.2.3 Về phía học sinh.

Các em thường quen với việc giải toán đó là tìm cách giải sao cho ra được một đáp án theo đề là được Chính vì vậy nhiều em đi thi học sinh giỏi về tự tin

là mình làm bài tốt mà không kiểm tra cách giải của mình đã tối ưu chưa? Đã bao quát được tất cả trường hợp xảy ra chưa? Đã chạy được test với dữ liệu lớn hay chưa? Dẫn đến kết quả kỳ thi thấp

2.2.4 Một số tài liệu hiện có.

Trên thực tế đã có một số tài liệu đề cập đến các bài tập về xâu, nhưng các tài liệu này mới chỉ đưa ra thuật toán và chương trình giải một số bài tập cụ thể làm ví dụ minh họa cho một kỹ thuật lập trình nào đó khi nghiên cứu mà chưa khái quát, nhấn mạnh được những điểm cần lưu ý với kiểu xâu trong C++

2.3 Các sáng kiến kinh nghiệm hoặc các giải pháp đã sử dụng để giải quyết vấn đề.

Từ thực trạng trên, qua 5 năm đứng đội tuyển từ 2017- 2022, nhất là khi chuyển đổi ngôn ngữ lập trình từ pascal sang C++ , khi dạy về kiểu dữ liệu xâu tôi đã tập hợp những lỗi sai thường gặp của học sinh, đưa ra cách khắc phục, hướng dẫn các em tạo dữ liệu đầu vào để kiểm tra độ phức tạp, thời gian thuật

Trang 5

toán, hướng các em tới thuật toán tối ưu khi giải quyết bài tập về kiểu dữ liệu xâu

2.3.1 Những sai lầm học sinh thường gặp

2.3.1.1 Vân dụng sai : cin và getline

a) Nhập xâu

Học sinh cần linh động trong cách nhập xâu tùy vào yêu cầu đề bài để tránh làm chậm chương trình hoặc mất test

+ Xâu không chứa dấu cách hoặc dấu cách ở cuối xâu chúng ta dùng cin:

cin>>tên biến xâu;

Với cách nhập này nó chỉ nhập được xâu từ đầu đến trước vị trí cách trống đầu tiên khi gặp các kí tự trắng (như dấu cách, kí tự xuống dòng, ….) sẽ coi là kết thúc việc nhập dữ liệu

+ xâu chứa dấu cách chúng ta dùng getline: getline(cin,tên biến xâu);

+ xâu có chứa dấu cách hoặc không có dấu cách ta có thể lựa chọn cách

đọc mảng kí tự

Lưu ý: khi dùng getline thời gian chạy chương trình sẽ lâu hơn cin

Ứng dụng linh hoạt cin, getline, mảng xâu, mảng kí tự

Để thấy được sự linh hoạt, hiệu quả khi hiểu rõ bản chất về cin, getline

ta giới thiệu cho học sinh ví dụ sau:

Cho file XAUDEP.INP gồm các dấu cách và các kí tự Một từ là các kí tự liên tiếp không chứa dấu cách, hãy tối ưu xâu trên để giữa hai từ chỉ có một dấu cách in kết quả xâu tìm được vào file XAUDEP.OUT

#include <iostream>

using namespace std;

string s,st;

int main()

{

freopen("xaudep.inp","r",stdin);

freopen("xaudep.out","w",stdout);

getline(cin,s); // sử dụng getline để đọc xâu đầu vào

s=s+' '; st="";

for(int i=0;i<s.size();i++)

if (s[i]!=' ' || s[i]==' ' &&s[i+1]!=' ') st=st+s[i];

if (st[0]==' ') st.erase(0,1);

cout<< st;

return 0;

}

Trang 6

Ở ví dụ này nếu học sinh hiểu rõ về cin sẽ giải quyết bài toán nhanh hơn như sau:

#include <iostream>

using namespace std;

string s,st;

int main()

{

freopen("xaudep.inp","r",stdin);

freopen("xaudep.out","w",stdout);

st="";

while (cin>> s) {st=st+s+' ';}

cout<< st;

return 0;

}

Để giải quyết ví dụ trên, ngoài cách đọc xâu bằng cin hoặc getline chúng ta cũng có thể đọc vào theo kiểu mảng kí tự hoặc mảng xâu như sau:

#include <iostream>

using namespace std;

string s,st;

string a[10000];

int main()

{

freopen("xaudep.inp","r",stdin);

freopen("xaudep.out","w",stdout);

st=""; int i=0;

while (cin>> s) {i++; a[i]=s;}

int n=i;

for (i=1; i<=n; i++)

cout<< a[i]<< ' ';

return 0;

}

b) Hiện tượng trôi lệnh

Khi chúng ta nhập lệnh bằng cin>> biến 1 và câu lệnh nhập sau bằng lệnh getline(cin,biến 2) thì chương trình không dừng lại cho chúng ta nhập dữ liệu cho biến 2

Ta xét chương trình sau:

#include <iostream>

#include <string>

Trang 7

using namespace std;

int main(){

int n;

string s2;

cout << " nhap so la=";

cin >> n; cout << n << endl;

cout << "nhap xau s2="; getline(cin,s2); cout << s2 << endl;

cout << "ket thuc" << endl;

return 0;

}

Bạn chạy chương trình trên sẽ thấy ngay Sau khi nhập dữ liệu cho biến

n, chương trình không dừng lại cho ta nhập dữ liệu cho s2 Mà in ngay ra thông báo “Ket thuc” Nguyên nhân là do sau khi nhập dữ liệu cho biến n ta

gõ phím Enter Mã của Enter được lưu trong bộ đệm (chính là ký tự xuống

dòng “\n”) và do đó khi chương trình gặp câu lệnh: getline(cin,s2); nó sẽ đọc

ngay ký tự này và nhận thấy đây là ký tự kết thúc nên nó sẽ loại bỏ ký tự này

ra khỏi bộ đệm mà không đọc vào xâu s2 Sau đó nó sẽ chạy thẳng đến câu lệnh tiếp theo là: cout << "ket thuc" << endl;

Để khắc phục hiện tượng trôi lệnh này thì trước mỗi lệnh getline ta nên

đặt câu lệnh: fflush(stdin);

Câu lệnh này có tác dụng xóa bộ đệm và do đó ta có thể yên tâm là sẽ không bị trôi lệnh nữa

#include <iostream>

#include <string>

using namespace std;

int main(){

int n;

string s2;

cout << " nhap so la=";

cin >> n; cout << n << endl; fflush(stdin);

cout << "nhap xau s2="; getline(cin,s2); cout << s2 << endl;

cout << "ket thuc" << endl;

return 0;

}

2.3.1.2 Sai lầm khi sử dụng các thao tác xử lý trong xâu

a) Lấy chỉ số: Dùng chỉ số của xâu mà không có trong xâu

Lưu ý: Chỉ số trong xâu được đánh từ 0

Trang 8

Ví dụ: xâu có n kí tự khi tham chiếu tới phần tử s[n] // trong code block vẫn chạy nhưng khi đưa vào temis chương trình báo lỗi

b) Ghép xâu: Chúng ta có thể ghép 2 xâu hoặc kí tự vào xâu nhưng không được

ghép 2 hằng xâu với nhau

Ví dụ: string s= ‘b’; // kí tự b được gán cho xâu s, lúc này s là xâu “b”;

s1= “123”; s2= “456”; s3= s1+s2; // lúc này s3= “123456”

Lỗi thường gặp: s3= “123”+ “456”; // Báo lỗi

Do hằng xâu+ hằng xâu thì sẽ trả về hằng xâu mà hằng là giá trị không thay đổi

Khắc phục: ta có thể viết

s3= s3+ “123”+ “456”;

s3= “123”+ s3+ “456”;

c) Chèn xâu: s1.insert(vt,s2); // ý nghĩa: Chèn xâu s2 vào xâu s1 bắt đầu từ vị

trí vt( vị trí trong xâu bắt đầu được tính từ 0)

Lỗi thường gặp: s1.insert(0, 'a'); // lỗi vì 'a' là kí tự không phải xâu “a”

d) Tìm kiếm: s1.find(s2); // s2 có thể là xâu hoặc kí tự

Lưu ý: Nếu không tìm thấy thì kết quả trả về giá trị lớn nhất của kiểu unsigned

long long nếu máy tính 64 bit thì kết quả trả về 264 -1 (chú ý vị trí của xâu trong C++ bắt đầu từ 0)

Chính vì vậy trong một số bài toán học sinh viết trực tiếp s1.find(s2) // nếu không tìm thấy s2 trong s1 kết quả trả về rất lớn và số này dương dẫn đến kết quả biên dịch thành công nhưng không cho kết quả hoặc kết quả sai.

Ví dụ: Cho xâu ST chứa các kí tự liên tiếp có độ dài <= 255 ký tự gồm các chữ cái la tinh (gồm cả ký tự in hoa và thường) Yêu cầu hãy xóa tất cả các ký tự ‘a’ hoặc ‘A’ trong xâu ST rồi ghi kết quả xâu sau khi xóa ra màn hình

Khi làm bài toán này học sinh thường hay viết chương trình như sau

#include<bits/stdc++.h>

#include<string>

using namespace std;

string s,s2,s3;

int main()

{

cin>> s; //cout<<s.length();

while ((s.find('a')>=0)||(s.find('A'))>=0)

{s.erase(s.find('a'),1); s.erase(s.find('A'),1);}

cout<<s;

return 0;

}

Trang 9

Chương trình cho kết quả như sau:

Khắc phục lỗi trên: ta nên ép kiểu

unsigned long long về int, trong kiểu int không có 264 -1 nên khi ép kiểu nó

sẽ trả về -1 Code minh họa

#include<bits/stdc++.h>

#include<string>

using namespace std;

string s,s2,s3;

int main()

{

cin>> s;

while ((int(s.find('a'))>=0)|| (int(s.find('A'))>=0))

{ s.erase(int(s.find('a')),1); s.erase(int(s.find('A')),1);

} cout<<s;

return 0;

}

2.3.1.3 Sai lầm trong lựa chọn và đánh giá độ phức tạp thuật toán.

Bài toán 1: Cho một xâu chỉ gồm các kí tự liên tiếp từ a đến z Hãy xóa tất cả

các kí tự a trong xâu, biết độ dài xâu <=106

Sai lầm thường gặp: Học sinh thường làm trực tiếp là duyệt tất cả các kí tự trong xâu, nếu gặp kí tự a thì xóa Với yêu cầu 1s cho ra output cần tìm thì cách làm này không hiệu quả, thí sinh chỉ lấy được 1/3 số điểm của bài

Lý do: int main()

{

cin>> s;

while ( int(s.find('a')) >= 0) // độ phức tạp O(n)

{ s.erase(int(s.find('a')),1); // độ phức tạp O(n) }

cout<<s;

return 0;

}

=> độ phức tạp thuật toán là O(n2)

Cách khắc phục:

Trang 10

int main() {

cin >>s;

for (i=0; i< s.size(); i++)// độ phức tạp O(n)

if (s[i]!= 'a') st=st+s[i];

cout<< st;

return 0;

}

=> độ phức tạp thuật toán O(n)

Các bài toán tương tự:

Bài 1 Xoá Số (DELNUM.PAS | DELNUM.CPP) [2]

Các bạn nhỏ Trung tâm Anh ngữ ABC Smart đang làm quen với bảng chữ cái và chữ số Tiếng Anh Sau một ngày học về bảng chữ cái và chữ số tiếng Anh thì các bạn nhỏ đã thuộc vanh vách Các bạn liền nghĩ ngay ra một bài toán để đố

các anh chị: Cho một xâuST gồm các chữ cái Latin in thường (‘a’ đến ‘z’) hoặc các chữ số (‘0’ đến ‘9’) Hãy xoá đi tất cả các chữ số trong xâu ST

Dữ liệu: vào từ file DELNUM.INP gồm 1 dòng là xâu ST có độ dài không quá

105 ký tự

Kết quả: ghi ra file DELNUM.OUTlà xâu sau khi xoá tất cả các chữ số.

Ví dụ:

laptrinhccongcongtap1 2

laptrinhccongcongta p

Giới hạn:

+ Có 80% số điểm tương ứng với xâu có độ dài không qua 103

+ 20% số điểm còn lại, không có ràng buộc gì thêm

Code tham khảo

#include <bits/stdc++.h>

using namespace std;

string st, res;

int n;

int main(){

freopen("delnum.inp", "r",stdin);

freopen("delnum.out","w", stdout);

cin >> st;

n = st.size();

res = "";

for(int i = 0; i< n; i++)

if(st[i]>= 'a') res = res + st[i];

Trang 11

cout << res;

return 0;

}

Bài 2: Đếm xâu (COUNTST.PAS |COUNTST.CPP)[2]

Các bạn nhỏ Trung tâm Anh ngữ ABC Smart đang làm quen với bảng chữ cái Tiếng Anh Sau một ngày học về bảng chữ cái tiếng Anh thì các bạn nhỏ đã thuộc vanh vách bảng chữ cái Các bạn liền nghĩ ngay ra một bài toán về đếm xâu, ngày mai đi học

để đố các bạn khác trên lớp: Cho một xâu ký tự ST chỉ chứa các chữ cái Latin in thường (‘a’ đến ‘z’), hãy đếm xem trong xâu trên có bao nhiêu xâu “abc” là xâu con của xâu trên (xâu con liên tiếp)

Dữ liệu: vào từ file COUNTST.INP gồm 1 dòng là xâu ST có độ

dài không quá 106 ký tự

Kết quả: ghi ra file COUNTST.OUT một số nguyên là kết quả

của bải toán

Ví dụ:

COUNTST.IN P

COUNTST.OU T

aabcbcabaabc 2

Lưu ý: với bài toán này nhiều học sinh đã nghĩ ngay đến hàm tìm kiếm xự xuất

hiện xâu “abc” nếu tìm thấy thì tăng biến đếm và dồng thời xóa khỏi xâu ban

đầu

Code tham khảo:

#include <bits/stdc++.h>

using namespace std;

string st;

int res, n;

int main()

{

ios_base::sync_with_stdio(0);

cin.tie(0); cout.tie(0);

freopen("countst.inp","r",stdin);

freopen("countst.out","w",stdout);

cin >> st;

n= st.length();

Trang 12

res = 0;

for (int i=0; i<= n-3; i++)

if ((st[i]=='a')&&(st[i+1]=='b')&&(st[i+2]=='c')) res++;

cout << res;

return 0;

}

Bài 3 Biến đổi xâu [2]

Cho một xâu S có độ dài tối đa là 106 ký tự Trong xâu S người ta loại bỏ

sự xuất hiện của một xâu con T có độ dài ≤ 100 ký tự Để làm điều này, người ta tìm sự xuất hiện của T lần đầu tiên trong S và xóa nó Sau đó cứ lặp đi lặp lại quá trình này cho đến khi không còn sự xuất hiện của T trong S Lưu ý rằng việc xóa một lần xuất hiện có thể tạo ra một sự xuất hiện mới của T chưa từng tồn tại trước đó Hãy xác định nội dung cuối cùng của xâu S

Dữ liệu: Vào từ file văn bản BAI3.INP:

- Dòng đầu tiên chứa xâu S

- Dòng thứ hai chứa xâu T Chiều dài của xâu T bé hơn chiều dài của S, và tất cả các kí tự của S và T đều là ký tự thường (trong phạm vi từ a z)

Kết quả: Ghi ra file văn bản BAI3.OUT chỉ một dòng chứa xâu S sau khi đã

xóa bỏ hết T Đảm bảo rằng S sẽ không trở nên xâu rỗng trong quá trình xóa

Ví dụ

Whatthemomooofun Moo

Whatthefun

Ý tưởng: Tao một xâu mới (s1) lần lượt từ các kí tự từ xâu s Nếu

s1.length()>=t.length() thì so sánh s1.copy(s1.length() - t.length(), t.length()) với xâu t Nếu bằng nhau thì thực hiện xóa s1 ngược lại thì tiếp tục tao xâu s1 từ s Kết quả tìm được là xâu s1

Code tham khảo:

#include <iostream>

using namespace std;

string s,st,t,tg;

int main()

{

freopen("bai3.inp","r",stdin);

freopen("bai3.out","w",stdout);

cin>>s;

cin>>t;

st="";

Ngày đăng: 06/06/2022, 19:20

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w