Bài giảng Lập trình nâng cao: Thao tác với tệp cung cấp cho người học các kiến thức: Nhập liệu từ tệp văn bản, xử lý lỗi với tệp, kỹ thuật giới thiệu các thư viện, kỹ thuật xử lý lỗi đơn giản. Mời các bạn cùng tham khảo.
File operations - Thao tác với tệp https://github.com/tqlong/advprogram Nội dung ● ● ● Nhập liệu từ tệp văn Xử lý lỗi với tệp Kỹ thuật ○ Giới thiệu thư viện , , ○ Xử lý lỗi đơn giản Nhập liệu từ tệp (file) ● Hangman thời sử dụng danh sách từ cố định ○ ○ Khơng cho phép đổi từ vựng (ví dụ: chọn lĩnh vực) Mã nguồn chương trình chứa danh sách từ ■ ● Phải dịch lại chương trình thay đổi từ Giải pháp: Tách mã nguồn liệu ○ ○ Dữ liệu lưu tệp Chương trình có mã lệnh đọc tệp, đưa liệu vào nhớ (biến) Top-down: Sửa main để dùng file const int M AX_BAD _G U ESSES = 7; st ch ar D ATA _FILE[] = "d ata/O g d en _P ictu rab le_200.txt"; - Yêu cầu chooseWord chọn từ file int m ain () { - Báo lỗi dừng game file có lỗi srand(tim e(0)); strin g w ord = ch ooseW ord (D ATA _FILE); if (w ord len g th () < 1) { cou t < < "Error read in g vocab u lary f i le " < < D ATA _FILE; retu rn -1; } string guessedW ord = string(w ord.length(), '-'); Thư viện fstream ● Thư viện C++ làm việc với file ○ ● Làm việc với file ○ ○ ○ ● http://www.cplusplus.com/reference/fstream/fstream/ Phổ biến phần mềm Phức tạp, tỉ mỉ Có nhiều lỗi “khơng ngờ” Học cách sử dụng ○ ○ Cách nhanh nhất: làm theo hướng dẫn (tutorials) Ví dụ: http://www.cplusplus.com/doc/tutorial/files/ Tạo file, ghi vào file với ofstream ● Biến kiểu ofstream (out file stream) ○ ○ ○ // thư viện fstream # include < fstream > Đại diện cho tệp ghi Phương thức open: mở file để ghi Ghi văn giống dùng cout u sin g n am esp ace std; in t m ain () { ofstream m yfi le; // khaibáo biếế n kiếể u ofstream m yfi le.open("exam ple.txt"); //M ể fi le exam ple.txt m yfi le < < "W riting this to a fi le.\n "; //G hivăn ba ển vào fi le m yfi le.close(); retu rn 0; } //Đ óng fi le lại: gia ểiphóng tàinguyến, ghivào đĩa Tạo file, ghi vào file với ofstream # include < iostream > # include < fstream > u sin g n am esp ace std; in t m ain () { ofstream m yfi le ("exam ple.txt"); if (m yf i le.is_op en ()) { // Kiếể m tra việc m ể tệp có thành cơng? m yfi le < < "This is a line.\n "; m yfi le < < "This is another line.\n "; m yfi le.close(); } else cou t < < "U n ab le to op en f i le"; retu rn 0; } Đọc file với ifstream # include < fstream > //Thư viện fstream chứa ifstream u sin g n am esp ace std; in t m ain () { string line; ifstream m yfi le ("exam ple.txt"); //Mở file example.txt ghi ví dụ trước if (m yfi le.is_open()) { //Kiểm tra việc mở tệp có thành cơng ? w h ile ( getline (m yfi le,line) ) { //Hàm getline đọc dòng tệp vào biến line cout < < line < < '\n'; } m yfi le.close(); // chuyển vị trí đọc xuống dịng // Lặp đến getline trả “false” (tức khơng cịn để đọc, hết tệp) //Đóng tệp, giải phóng tài nguyên hệ thống } else cout < < "U nable to open fi le"; retu rn 0; } Đọc từ vựng Hangman từ tệp Từ vựng Hangman lưu tệp văn bản: ● Tệp nằm thư mục “data” với chương trình (quyết định nơi gọi chooseWord, main()) ● Mỗi từ dòng chooseWord (thử đọc từ file) string chooseW ord(const char* fi leN am e) { ifstream fi le(fi leN am e); //Mở tệp có đường dẫn tham số if (fi le.is_open()) { //Kiểm tra tệp mở thành công string w ord; w hile (fi le > > w ord) { //Đọc từ đến không đọc cout < < w ord < < endl; //ghi tạm hình để xem thử } fi le.close(); } else cout < < "Error opening " < < fi leN am e; return "book"; } // return tạm để chạy với main Ghi liệu từ file vào đâu? Từ vựng Hangman lưu tệp văn bản: ● Mỗi từ dòng ○ Số dòng (số từ) chưa biết trước → Cần kiểu liệu lưu trữ số lượng từ “tùy ý” dùng mảng thông thường ta phải đọc lần để đếm số dòng trước khai báo mảng, sau đọc vào mảng Thư viện vector ● Cho phép lưu trữ dãy giá trị kiểu ○ ○ ● Ví dụ: x[i] Cho phép thay đổi kích thước (số phần tử) ○ ○ ● Truy xuất giống mảng tĩnh Có thể coi mảng “động” Khơng cần tự lập trình xin cấp phát nhớ Nhiều tiện ích thao tác với mảng ■ ■ Thêm, chèn, xóa, sửa Kết hợp với : tìm kiếm, xếp … http://www.cplusplus.com/reference/vector/vector/ Thư viện vector Chèn vào cuối vector // push_back // push_back # include < iostream > # include < vector> Sưểdụng thư viện vector usin g n am esp ace std; in t m ain () { vector< in t> m yvector; Khaibáo m yvector vector sôếnguyến in t m yint; cout < < "Please enter som e integers (Ctrl-D to end):\n "; w h ile (cin > > m yint) { m yvector.push_back (m yint); Lặp đếế n khikhơng cịn liệu m ới Phưởng thức push_back: Thếm m yint vào cuôế im yvector } cout < < "m yvector stores " < < in t(m yvector.size()) < < " num bers.\n "; return 0; } In sôếphầầ n tưểcu ể a m yvector Thư viện vector Truy xuất phần tử vector vector< in t> m yvector (10 ); // 10 zero-initialized ints Khaibáo vector có 10 phầầ n tưể // assign som e values: u n sig n e d sz = m yvector.size(); Lưu kích thước vector for (u n sig n ed i= ; i< sz; i+ + ) m yvector.at(i)= i; G án giá trịtạivịtríthứ i(tính từ 0) qua phưởng thức at cout < < "m yvector contains:"; for (u n sig n ed i= ; i< sz; i+ + ) cout < < ''< < m yvector.at(i); In giá trịtạivịtríthứ iqua phưởng thức at cout < < '\n'; // reverse vector using operator[]: for (u n sig n ed i= ; i< sz/2 ; i+ + ) { in t tem p; tem p = m yvector[sz-1 -i]; Sưểdụng toán tưể[] truy xuầế t gán giá trịphầầ n tưểcu ể a vector m yvector[sz-1-i]= m yvector[i]; giôế n g m a ểng tĩnh m yvector[i]= tem p; } cout < < "m yvector contains:"; for (u n sig n ed i= ; i< sz; i+ + ) cout < < ''< < m yvector[i]; cout < < '\n'; In giá trịtạivịtríthứ iqua phưởng thức at chooseWord (đọc vào vector) string chooseW ord(const char* fi leN am e) { vector< strin g > w ord List; ifstream fi le(fi leN am e); if (fi le.is_open()) { //Khai báo vector chứa từ đọc //Mở tệp có đường dẫn tham số //Kiểm tra tệp mở thành công string w ord; w hile (fi le > > w ord) { //Đọc từ (giống cin) đến không đọc w ord List.p u sh _b ack(w ord ); //đưa từ vừa đọc vào vector } fi le.close(); Cẩn thận trường hợp file mở thành công rỗng } if (w ordList.size() > 0) { // có liệu đọc thành công in t ran dom In dex = ran d() % w ordList.size(); retu rn w ordList[random In dex]; } else retu rn ""; } // trả từ ngẫu nhiên vector // không đọc gì, trả từ rỗng Hồn thành Hangman 2.0 ● Đọc liệu từ tệp ○ ● Sử dụng , Lựa chọn phần tử ngẫu nhiên vector Chuẩn hóa liệu Dữ liệu từ tệp, đặc biệt liệu tải từ Internet cần chuẩn hóa ● ● Đảm bảo chương trình hoạt động với liệu ý định ban đầu Sửa lỗi liệu, loại bỏ liệu “xấu” Với Hangman 2.1, cần chuyển từ dạng chữ thường để phép tốn so sánh (==, !=) hoạt động xác chooseWord (chuẩn hóa liệu) string chooseW ord(const char* fi leN am e) { vector< string> w ordList; ifstream fi le(fi leN am e); if (fi le.is_open()) { string w ord; w hile (fi le > > w ord) { Chuyển từ chọn sang chữ thường trước trả w ordList.push_back(w ord); } fi le.close(); } if (w ordList.size() > 0) { int random Index = rand() % w ordList.size(); return g etLow erC aseS trin g (w ord List[ran d om In d ex]); } else return ""; } Chuyển từ sang chữ thường string chooseW ord(const char* fi leN am e) { string g etLow erC aseS trin g (con st string& s) vector< string> w ordList; { ifstream fi le(fi leN am e); string res = s; if (fi le.is_open()) { string w ord; in t sz = s.size(); w hile (fi le > > w ord) { for (in t i= 0; i< sz; i+ + ) w ordList.push_back(w ord); res[i] = tolow er(s[i]); } retu rn res; fi le.close(); } } if (w ordList.size() > 0) { int random Index = rand() % w ordList.size(); return g etLow erC aseS trin g (w ord List[ran d om In d ex]); } else return ""; } Giới thiệu thư viện algorithm string getLow erC aseS tring ( # include < algorithm > const string& s) { string g etLo w erC aseS trin g (con st string& s) string res = s; { int sz = s.size(); string res = s; for (in t i= ; i< sz; i+ + ) transform (s.begin(), s.end(),res.begin(),::tolow er); res[i] = tolow er(s[i]); return res; } retu rn res; } Duyệt từ đầu đến cuối s, biến đổi hàm tolower(), đặt kết vào ký tự tính từ đầu Duyệt mảng res thao tác phổ biến lập trình http://stackoverflow.com/questions/313970/how-to-convert-stdstring-to-lower-case Con trỏ duyệt (Iterator) s.begin(), s.end() trả iterator # include < algorithm > string getLow erC aseS tring(const string& s) { string res = s; khái niệm khái quát hóa transform (s.begin(),s.end(),res.begin(),::tolow er); return res; } số mảng ● ● Sẽ học kỹ buổi sau http://www.cplusplus.com/reference/iterator/ Hoàn thành Hangman 2.1 ● Chuẩn hóa từ dạng chữ thường ○ Duyệt mảng, biến đổi sử dụng Bài tập: Hangman 2.2 - Chọn tệp liệu ● ● Từ tham số dòng lệnh Từ lựa chọn người chơi Nội dung ● ● ● Nhập liệu từ tệp văn Xử lý lỗi với tệp Kỹ thuật ○ Thư viện , , Các phiên sau Bạn tự làm tiếp 2.2 Cho chơi nhiều lần 2.3 Hoạt hình: giá treo cổ lắc lư sau thua, thắng có người đứng nhảy múa Đồ họa? Đợi học thư viện đồ họa ... đặt kết vào ký tự tính từ đầu Duyệt mảng res thao tác phổ biến lập trình http://stackoverflow.com/questions/313970/how-to-convert-stdstring-to-lower-case Con trỏ duyệt (Iterator) s.begin(), s.end()... chương trình chứa danh sách từ ■ ● Phải dịch lại chương trình thay đổi từ Giải pháp: Tách mã nguồn liệu ○ ○ Dữ liệu lưu tệp Chương trình có mã lệnh đọc tệp, đưa liệu vào nhớ (biến) Top-down:... giống mảng tĩnh Có thể coi mảng “động” Khơng cần tự lập trình xin cấp phát nhớ Nhiều tiện ích thao tác với mảng ■ ■ Thêm, chèn, xóa, sửa Kết hợp với : tìm kiếm, xếp … http://www.cplusplus.com/reference/vector/vector/