NMLT_C20_TapTin_#REF
Chia sẻ bởi Trần Tuấn Vũ |
Ngày 19/03/2024 |
14
Chia sẻ tài liệu: NMLT_C20_TapTin_#REF thuộc Công nghệ thông tin
Nội dung tài liệu:
NHẬP MÔN LẬP TRÌNH
TẬP TIN
Nội dung
Tập tin
Nhập xuất
Khái niệm
C lưu dữ liệu (biến, mảng, cấu trúc, …) trong bộ nhớ RAM.
Dữ liệu được nạp vào RAM và gửi ra ngoài chương trình thông qua các thiết bị (device)
Thiết bị nhập (input device): bàn phím, con chuột
Thiết bị xuất (output device): màn hình, máy in
Thiết bị vừa nhập vừa xuất: tập tin
Các thiết bị đều thực hiện mọi xử lý thông qua các dòng (stream).
Tập tin
Stream (dòng)
Khái niệm
Là môi trường trung gian để giao tiếp (nhận/ gửi thông tin) giữa chương trình và thiết bị.
Muốn nhận/gửi thông tin cho một thiết bị ta sẽ gửi thông tin cho stream nối với thiết bị đó (độc lập thiết bị).
Stream là dãy byte dữ liệu
“Chảy” vào chương trình gọi là stream nhập.
“Chảy” ra chương trình gọi là stream xuất.
Tập tin
Stream (dòng)
Phân loại
Stream văn bản (text)
Chỉ chứa các ký tự.
Tổ chức thành từng dòng, mỗi dòng tối đa 255 ký tự, kết thúc bởi ký tự cuối dòng ‘ ’ hoặc ký tự sang dòng mới ‘ ’.
Stream nhị phân (binary)
Chứa các byte.
Được đọc và ghi chính xác từng byte.
Xử lý dữ liệu bất kỳ, kể cả dữ liệu văn bản.
Được sử dụng chủ yếu với các tập tin trên đĩa.
Tập tin
Stream (dòng)
Các stream chuẩn định nghĩa sẵn
Ví dụ (hàm fprintf xuất ra stream xác định)
Xuất ra màn hình: fprintf(stdout, “Hello”);
Xuất ra máy in: fprintf(stdprn, “Hello”);
Xuất ra thiết bị báo lỗi: fprintf(stderr, “Hello”);
Xuất ra tập tin (stream fp): fprintf(fp, “Hello”);
Tập tin
Tập tin
Nhu cầu
Dữ liệu giới hạn và được lưu trữ tạm thời
Nhập: gõ từ bàn phím.
Xuất: hiển thị trên màn hình.
Lưu trữ dữ liệu: trong bộ nhớ RAM.
Mất thời gian, không giải quyết được bài toán với số dữ liệu lớn.
Cần một thiết bị lưu trữ sao cho dữ liệu vẫn còn khi kết thúc chương trình, có thể sử dụng nhiều lần và kích thước không hạn chế.
Tập tin
Tập tin
Khái niệm
Tập hợp thông tin (dữ liệu) được tổ chức theo một dạng nào đó với một tên xác định.
Một dãy byte liên tục (ở góc độ lưu trữ).
Được lưu trữ trong các thiết bị lưu trữ ngoài như đĩa mềm, đĩa cứng, USB…
Vẫn tồn tại khi chương trình kết thúc.
Kích thước không hạn chế (tùy vào thiết bị lưu trữ)
Cho phép đọc dữ liệu (thiết bị nhập) và ghi dữ liệu (thiết bị xuất).
Tập tin
Tập tin
Phân loại
Theo người sử dụng: quan tâm đến nội dung
tập tin nên sẽ phân loại theo phần mở rộng
.EXE, .COM, .CPP, .DOC, .PPT, …
Theo người lập trình: tự tạo các stream tường minh để kết nối với tập tin xác định nên sẽ
phân loại theo cách sử dụng stream trong C
tập tin kiểu văn bản (ứng với stream
văn bản) và tập tin kiểu nhị phân (ứng với stream nhị phân).
Tập tin
Phân loại tập tin
Tập tin kiểu văn bản (stream văn bản)
Dãy các dòng kế tiếp nhau.
Mỗi dòng dài tối đa 255 ký tự và kết thúc bằng ký hiệu cuối dòng (end_of_line).
Dòng không phải là một chuỗi vì không được kết thúc bởi ký tự ‘ ’.
Khi ghi ‘ ’ được chuyển thành cặp ký tự CR (về đầu dòng, mã ASCII 13) và LF (qua dòng, mã ASCII 10).
Khi đọc thì cặp CR-LF được chuyển thành ‘ ’.
Tập tin
Phân loại tập tin
Tập tin kiểu nhị phân (stream nhị phân)
Dữ liệu được đọc và ghi một cách chính xác, không có sự chuyển đổi nào cả.
Ký tự kết thúc chuỗi ‘ ’ và end_of_line không có ý nghĩa là cuối chuỗi và cuối dòng mà được xử lý như mọi ký tự khác.
Tập tin
Quy tắc đặt tên tập tin
Tập tin
Tên
(name)
.
Mở rộng
(extension)
Định vị tập tin
Đường dẫn
Chỉ đến một tập tin không nằm trong thư mục hiện hành. Ví dụ: c:datalist.txt chỉ tập tin list.txt nằm trong thư mục data của ổ đĩa C.
Trong chương trình, đường dẫn này được ghi trong chuỗi như sau: “c:\data\list.txt”
Dấu ‘’ biểu thị ký tự điều khiển nên để thể hiện nó ta phải thêm một dấu ‘’ ở trước. Nhưng nếu chương trình yêu cầu nhập đường dẫn từ bàn phím thì chỉ nhập một dấu ‘’.
Tập tin
Quy trình thao tác với tập tin
1. Mở tập tin: tạo một stream nối kết với tập tin cần mở, stream được quản lý bởi biến con trỏ đến cấu trúc FILE
Cấu trúc được định sẵn trong STDIO.H
Các thành phần của cấu trúc này được dùng trong các thao tác xử lý tập tin.
2. Sử dụng tập tin (sau khi đã mở được tập tin)
Đọc dữ liệu từ tập tin đưa vào chương trình.
Ghi dữ liệu từ chương trình lên tập tin.
3. Đóng tập tin (sau khi sử dụng xong).
Tập tin
Hàm mở tập tin
Tập tin
Mở tập tin có tên (đường dẫn) là chứa trong filename với kiểu mở mode (xem bảng).
Thành công: con trỏ kiểu cấu trúc FILE
Thất bại: NULL (sai quy tắc đặt tên tập tin, không tìm thấy ổ đĩa, không tìm thấy thư mục, mở tập tin chưa có để đọc, …)
FILE* fp = fopen(“taptin.txt”, “rt”);
if (fp == NULL)
printf(“Khong mo duoc tap tin!”);
Trả về
FILE *fopen(const char *filename, const char *mode)
Đối số mở tập tin (mode)
Tập tin
Đọc và ghi dữ liệu (stdio.h)
Thực hiện đọc/ghi dữ liệu theo các cách sau:
Nhập/xuất theo định dạng
Hàm: fscanf, fprintf
Chỉ dùng với tập tin kiểu văn bản.
Nhập/xuất từng ký tự hay dòng lên tập tin
Hàm: getc, fgetc, fgets, putc, fputs
Chỉ nên dùng với kiểu văn bản.
Đọc/ghi trực tiếp dữ liệu từ bộ nhớ lên tập tin
Hàm: fread, fwrite
Chỉ dùng với tập tin kiểu nhị phân.
Tập tin
Hàm xuất theo định dạng
Tập tin
Ghi dữ liệu có chuỗi định dạng fnt (giống hàm printf) vào stream fp.
Nếu fp là stdout thì hàm giống printf.
Thành công: trả về số byte ghi được.
Thất bại: trả về EOF (có giá trị là -1, được định nghĩa trong STDIO.H, sử dụng trong tập tin có kiểu văn bản)
int i = 2912; int c = ‘P’; float f = 17.06;
FILE* fp = fopen(“taptin.txt”, “wt”);
if (fp != NULL)
fprintf(fp, “%d %c %.2f ”, i, c, f);
Trả về
int fprintf(FILE *fp, char *fnt, …)
Hàm nhập theo định dạng
Tập tin
Đọc dữ liệu có chuỗi định dạng fnt (giống hàm scanf) từ stream fp.
Nếu fp là stdin thì hàm giống printf.
Thành công: trả về số thành phần đọc và lưu trữ được.
Thất bại: trả về EOF.
int i;
FILE* fp = fopen(“taptin.txt”, “rt”);
if (fp != NULL)
fscanf(fp, “%d”, &i);
Trả về
int fscanf(FILE *fp, char *fnt, …)
Hàm nhập theo định dạng
Ví dụ
Một tập tin chứa nhiều dòng, mỗi dòng là thông tin mỗi sinh viên theo định dạng sau:
-()tabtab<ĐTB>
Ví dụ: 0312078-H. P. Trang(Nu) 17/06/85 8.5
Đọc chuỗi thông tin phức hợp
%[chuỗi]: đọc cho đến khi không gặp ký tự nào trong chuỗi thì dừng.
%[^chuỗi]: đọc cho đến khi gặp một trong những ký tự trong chuỗi thì dừng.
Tập tin
Hàm Tách 2 Mảng
Tập tin
struct SINHVIEN {
char MSSV[8]; // 0312078
char HoTen[30]; // H. P. Trang
char GioiTinh[4]; // Nu
char NTNS[9]; // 17/06/85
float DiemTB; // 8.5
};
void main() {
SINHVIEN sv;
FILE *fp = fopen(“dssv.txt”, “rt”);
if (fp != NULL) {
fscanf(fp, “%[^-]-%[^(](%[^)]) %[^ ]
%f”, &sv.MSSV, &sv.HoTen,
&sv.GioiTinh, &sv.NTNS, &sv.DiemTB);
fclose(fp);
}
}
Hàm nhập ký tự
Tập tin
Đọc một ký tự từ stream fp.
getc là macro còn fgetc là phiên bản hàm của macro getc.
Thành công: trả về ký tự đọc được sau khi chuyển sang số nguyên không dấu.
Thất bại: trả về EOF khi kết thúc stream fp hoặc gặp lỗi.
char ch;
FILE* fp = fopen(“taptin.txt”, “rt”);
if (fp != NULL)
ch = getc(fp); // ch = fgetc(fp);
Trả về
int getc(FILE *fp) và int fgetc(FILE *fp)
Hàm nhập chuỗi
Tập tin
Đọc một dãy ký tự từ stream fp vào vùng nhớ str, kết thúc khi đủ n-1 ký tự hoặc gặp ký tự xuống dòng.
Thành công: trả về str.
Thất bại: trả về NULL khi gặp lỗi hoặc gặp ký tự EOF.
char s[20];
FILE* fp = fopen(“taptin.txt”, “rt”);
if (fp != NULL)
fgets(s, 20, fp);
Trả về
Int fgets(char *str, int n, FILE *fp)
Hàm xuất ký tự
Tập tin
Ghi ký tự ch vào stream fp.
putc là macro còn fputc là phiên bản hàm của macro putc.
Thành công: trả về ký tự ch.
Thất bại: trả về EOF.
FILE* fp = fopen(“taptin.txt”, “rt”);
if (fp != NULL)
putc(‘a’, fp); // hoặc fputc(‘a’, fp);
Trả về
int putc(int ch, FILE *fp) và int fputc(in ch, FILE *fp)
Hàm xuất chuỗi
Tập tin
Ghi chuỗi ký tự str vào stream fp. Nếu fp là stdout thì fputs giống hàm puts, nhưng puts ghi ký tự xuống dòng.
Thành công: trả về ký tự cuối cùng đã ghi.
Thất bại: trả về EOF.
char s[] = “Ky thuat lap trinh”;
FILE* fp = fopen(“taptin.txt”, “wt”);
if (fp != NULL)
fputs(s, fp);
Trả về
int fputs(const char *str, FILE *fp)
Hàm xuất trực tiếp
Tập tin
Ghi count mẫu tin có kích thước mỗi mẫu tin là size (byte) từ vùng nhớ buf vào stream fp (theo kiểu nhị phân).
Thành công: trả về số lượng mẫu tin (không phải số lượng byte) đã ghi.
Thất bại: số lượng nhỏ hơn count.
int a[] = {1, 2, 3};
FILE* fp = fopen(“taptin.dat”, “wb”);
if (fp != NULL)
fwrite(a, sizeof(int), 3, fp);
Trả về
int fwrite(void *buf, int size, int count, FILE *fp)
Hàm nhập trực tiếp
Tập tin
Đọc count mẫu tin có kích thước mỗi mẫu tin là size (byte) vào vùng nhớ buf từ stream fp (theo kiểu nhị phân).
Thành công: trả về số lượng mẫu tin (không phải số lượng byte) thật sự đã đọc.
Thất bại: số lượng nhỏ hơn count khi kết thúc stream fp hoặc gặp lỗi.
int a[5];
FILE* fp = fopen(“taptin.dat”, “wb”);
if (fp != NULL)
fread(a, sizeof(int), 3, fp);
Trả về
int fread(void *buf, int size, int count, FILE *fp)
Hàm đóng tập tin xác định
Tập tin
Đóng stream fp.
Dữ liệu trong stream fp sẽ được “vét” (ghi hết lên đĩa) trước khi đóng.
Thành công: trả về 0.
Thất bại: trả về EOF.
FILE* fp = fopen(“taptin.txt”, “rt”);
…
fclose(fp);
Trả về
int fclose(FILE *fp)
Hàm đóng tất cả stream
Tập tin
Đóng tất cả stream đang được mở ngoại trừ các stream chuẩn stdin, stdout, stdprn, stderr, stdaux.
Nên đóng từng stream thay vì đóng tất cả.
Thành công: trả về số lượng stream được đóng.
Thất bại: trả về EOF.
FILE* fp1 = fopen(“taptin1.txt”, “rt”);
FILE* fp2 = fopen(“taptin2.txt”, “wt”);
…
fcloseall();
Trả về
int fcloseall()
“Vét” dữ liệu trong stream
Khi chương trình kết thúc, các stream đang mở sẽ được “vét” (flush) và đóng lại. Tuy nhiên, ta nên đóng một các tường minh các stream sau khi sử dụng xong (nhất là các stream tập tin) để tránh các sự cố xảy ra trước khi chương trình kết thúc bình thường.
Ta có thể “vét” dữ liệu trong stream mà không cần đóng stream đó bằng một trong hai hàm:
Vét stream fp xác định: int fflush(FILE *fp);
Vét tất cả stream đang mở: int flushall();
Tập tin
Con trỏ chỉ vị (position indicator)
Khái niệm
Được tạo tự động khi mở tập tin.
Xác định nơi diễn ra việc đọc/ghi trong tập tin
Vị trí con trỏ chỉ vị
Khi tập tin chưa mở: ở đầu tập tin (giá trị 0).
Khi mở tập tin:
Ở cuối tập tin khi mở để chèn (mode a hay a+)
Ở đầu tập tin (hay giá trị 0) khi mở với các mode khác (w, w+, r, r+).
Tập tin
Truy xuất tuần tự & ngẫu nhiên
Truy xuất tuần tự (sequentially access)
Phải đọc/ghi dữ liệu từ vị trí con trỏ chỉ vị đến vị trí n-1 trước khi đọc dữ liệu tại vị trí n.
Không cần quan tâm đến con trỏ chỉ vị do con trỏ chỉ vị tự động chuyển sang vị trí kế tiếp sau thao tác đọc/ghi dữ liệu.
Truy xuất ngẫu nhiên (random access)
Có thể đọc/ghi tại vị trí bất kỳ trong tập tin mà không cần phải đọc/ghi toàn bộ dữ liệu trước đó quan tâm đến con trỏ chỉ vị.
Tập tin
Hàm đặt lại vị trí con trỏ chỉ vị
Tập tin
Đặt lại vị trí con trỏ chỉ vị về đầu (byte 0) tập tin fp.
Không
FILE* fp = fopen(“taptin.txt”, “w+”);
fprintf(fp, “0123456789”);
rewind(fp);
fprintf(fp, “*****”);
Trả về
void rewind(FILE *fp)
Hàm tái định vị con trỏ chỉ vị
Tập tin
Đặt vị trí con trỏ chỉ vị trong stream fp với vị trí offset so với cột mốc origin (SEEK_SET hay 0: đầu tập tin; SEEK_CUR hay 1: vị trí hiện tại; SEEK_END hay 2: cuối tập tin)
Thành công: trả về 0.
Thất bại: trả về giá trị khác 0.
FILE* fp = fopen(“taptin.txt”, “w+”);
fseek(fp, 0L, SEEK_SET); // rewind(fp);
fseek(fp, 0L, SEEK_END); // cuối tập tin
fseek(fp, -2L, SEEK_CUR);// lùi lại 2 vị trí
Trả về
int fseek(FILE *fp, long offset, ing origin)
Hàm xác định vị trí con trỏ chỉ vị
Tập tin
Hàm trả về vị trí hiện tại của con trỏ chị vị (tính từ vị trí đầu tiên của tập tin, tức là 0) của stream fp.
Thành công: trả về vị trí hiện tại của con trỏ chỉ vị.
Thất bại: trả về -1L.
FILE* fp = fopen(“taptin.txt”, “rb”);
fseek(fp, 0L, SEEK_END);
long size = ftell(fp);
printf(“Kich thuoc tap tin la %ld ”, size);
Trả về
long ftell(FILE *fp)
Dấu hiệu kết thúc tập tin
Khi đã biết kích thước tập tin
Sử dụng fwrite để lưu n mẫu tin
kích thước = n * sizeof(1 mẫu tin);
Sử dụng hàm fseek kết hợp hàm ftell
Khi chưa biết kích thước tập tin
Hằng số EOF (=-1) (chỉ cho tập tin văn bản)
while ((c = fgetc(fp)) != EOF) …
Hàm int feof(FILE *fp) (cho cả 2 kiểu tập tin)
trả về số 0 nếu chưa đến cuối tập tin
trả về số khác 0 nếu đã đến cuối tập tin.
Tập tin
Các hàm quản lý tập tin
Hàm nhập xuất tập tin (File I/O function) là các đã đề cập phần trước
Mở và đóng tập tin: fopen, fclose
Nhập/Xuất tập tin:
Theo định dạng: fprintf, fscanf
Từng ký tự hay chuỗi: fputc, fputs, fgetc, fgets
Trực tiếp từ bộ nhớ: fwrite, fread
Hàm quản lý tập tin (File-Management function)
Xóa tập tin: remove
Đổi tên tập tin: rename
Tập tin
Hàm xóa tập tin
Tập tin
Xóa tập tin xác định bởi filename.
Thành công: trả về 0.
Thất bại: trả về -1.
if (remove(“c:\vc.txt”) == 0)
printf(“Tap tin vc.txt da bi xoa!”);
else
printf(“Ko xoa duoc tap tin vc.txt!”);
Trả về
int remove(const char *filename)
Hàm đổi tên tập tin
Tập tin
Đổi tên tập tin oldname thành newname.
Hai tập tin phải cùng ổ đĩa nhưng không cần thiết phải cùng thư mục (có thể sử dụng để di chuyển hay sao chép tập tin).
Thành công: trả về 0.
Thất bại: trả về -1.
if (rename(“c:\a.txt”, “c:\BT.cpp”) == 0)
printf(“Doi ten tap tin thanh cong”);
else
printf(“Doi ten tap tin that bai”);
Trả về
int rename(const char *oldname, const char *newname)
Bài tập lý thuyết
Bài 1: Sự khác nhau giữa stream kiểu văn bản và stream kiểu nhị phân?
Stream văn bản tự động chuyển đổi ký tự ‘ ’ thành cặp ký tự CR-LF trong khi stream nhị phân không thực hiện việc chuyển đổi này (xem mọi ký tự đều như nhau).
Bài 2: Cần phải làm gì trước khi muốn truy xuất tập tin?
Mở tập tin (tạo stream kết nối với tập tin cần mở) bằng hàm fopen.
Tập tin
Bài tập lý thuyết
Bài 3: Khi mở tập tin bằng fopen, ta cần phải xác định thông tin nào và hàm sẽ trả về cái gì?
Cần xác định tên tập tin cần mở và mode mở tập tin này. Hàm sẽ trả về một con trỏ đến kiểu FILE, con trỏ này được dùng thay cho tập tin trong chương trình.
Bài 4: Ba phương pháp để truy xuất tập tin?
1. Theo định dạng.
2. Theo ký tự / chuỗi ký tự.
3. Trực tiếp từ bộ nhớ.
Tập tin
Bài tập lý thuyết
Bài 5: Hai phương pháp để đọc thông tin từ tập tin là gì?
1. Truy xuất tuần tự (theo thứ tự)
2. Truy xuất ngẫu nhiên (tại vị trí bất kỳ)
Bài 6: Giá trị của EOF?
-1 (định nghĩa trong STDIO.H)
Bài 7: Ta dùng hằng ký hiệu EOF để làm gì?
Được sử dụng với các tập tin kiểu văn bản nhằm xác định dấu hiệu cuối tập tin.
Tập tin
Bài tập lý thuyết
Bài 8: Cách xác định cuối tập tin trong kiểu văn bản và kiểu nhị phân?
Sử dụng hàm foef cho cả hai kiểu tập tin. Trong kiểu văn bản có thể sử dụng hằng EOF.
Bài 9: Con trỏ chỉ vị là gì và cách thay đổi nó?
Con trỏ chỉ vị đánh dấu vị trí trong của một tập tin, nơi diễn ra các thao tác đọc/ghi.
Thay đổi vị trí con trỏ chỉ vị bằng hàm rewind (về đầu tập tin) và fseek (về vị trí bất kỳ).
Tập tin
Bài tập lý thuyết
Bài 10: Nếu mở một tập tin chưa có (bằng mode w), cho biết giá trị của con trỏ chị vị lúc đầu?
Con trỏ chỉ vị chỉ đến ký tự đầu tiên của tập tin (vị trí 0).
Bài 11: Viết lệnh đóng tất cả các stream tập tin.
fcloseall();
Bài 12: Trình bày hai cách khác nhau để chuyển con trỏ chỉ vị về đầu tập tin fp.
1. rewind(fp);
2. fseek(fp, 0, SEEK_SET);
Tập tin
Bài tập lý thuyết
Bài 13: Đoạn chương trình sau có sai không?
Tập tin
void main()
{
FILE *fp;
int c;
if ((fp = fopen(“abc.xyz”, “rb”)) == NULL)
printf(“Khong mo duoc tap abc.xyz ”);
else
{
while ((c = fgetc(fp)) != EOF)
fprintf(stdout, “%c”, c);
fclose(fp);
}
}
Bài tập thực hành
Bài 14: Viết chương trình ghi 3 số nguyên a, b, c được nhập từ bàn phím vào một tập tin.
Bài 15: Viết chương trình đọc 3 số nguyên a, b, c từ một tập tin, sau đó giải phương trình ax2+ bx + c = 0 rồi ghi kết quả vào một tập tin khác.
Bài 16: Viết chương trình đọc n số nguyên từ một tập tin cho trước, sau đó sắp xếp tăng dần rồi ghi kết quả vào 1 tập tin khác. Ví dụ:
4 4
2 5 1 4 1 2 4 5
Tập tin
Bài tập thực hành
Bài 17: Viết chương trình ghi các dòng văn bản được nhập từ bàn phím lên tập tin.
Bài 18: Viết chương trình in nội dung một tập tin lên màn hình.
Bài 19: Viết chương trình đếm số ký tự chữ cái của tập tin và xuất kết quả ra một tập tin khác.
Bài 20: Viết chương trình đếm số từ của tập tin và xuất kết quả ra một tập tin khác.
Bài 21: Viết chương trình đếm số lần lặp lại của một từ trong một tập tin.
Tập tin
Bài tập thực hành
Bài 22: Viết chương trình mở tập tin văn bản đã có trên đĩa, sao chép nó thành một tập tin văn bản mới với điều kiện là các chữ thường đổi thành chữ hoa, tất cả các ký tự khác không đổi.
Bài 23: Viết chương trình ghép 2 tập tin văn bản, nội dung tập tin thứ hai được ghép sau tập tin thứ nhất.
Bài 24: Viết sao sao chép một tập tin cho trước.
Bài 25: Viết chương trình ghi một danh sách cấu trúc xuống tập tin sau đó đọc lên kiểm tra lại.
Tập tin
TẬP TIN
Nội dung
Tập tin
Nhập xuất
Khái niệm
C lưu dữ liệu (biến, mảng, cấu trúc, …) trong bộ nhớ RAM.
Dữ liệu được nạp vào RAM và gửi ra ngoài chương trình thông qua các thiết bị (device)
Thiết bị nhập (input device): bàn phím, con chuột
Thiết bị xuất (output device): màn hình, máy in
Thiết bị vừa nhập vừa xuất: tập tin
Các thiết bị đều thực hiện mọi xử lý thông qua các dòng (stream).
Tập tin
Stream (dòng)
Khái niệm
Là môi trường trung gian để giao tiếp (nhận/ gửi thông tin) giữa chương trình và thiết bị.
Muốn nhận/gửi thông tin cho một thiết bị ta sẽ gửi thông tin cho stream nối với thiết bị đó (độc lập thiết bị).
Stream là dãy byte dữ liệu
“Chảy” vào chương trình gọi là stream nhập.
“Chảy” ra chương trình gọi là stream xuất.
Tập tin
Stream (dòng)
Phân loại
Stream văn bản (text)
Chỉ chứa các ký tự.
Tổ chức thành từng dòng, mỗi dòng tối đa 255 ký tự, kết thúc bởi ký tự cuối dòng ‘ ’ hoặc ký tự sang dòng mới ‘ ’.
Stream nhị phân (binary)
Chứa các byte.
Được đọc và ghi chính xác từng byte.
Xử lý dữ liệu bất kỳ, kể cả dữ liệu văn bản.
Được sử dụng chủ yếu với các tập tin trên đĩa.
Tập tin
Stream (dòng)
Các stream chuẩn định nghĩa sẵn
Ví dụ (hàm fprintf xuất ra stream xác định)
Xuất ra màn hình: fprintf(stdout, “Hello”);
Xuất ra máy in: fprintf(stdprn, “Hello”);
Xuất ra thiết bị báo lỗi: fprintf(stderr, “Hello”);
Xuất ra tập tin (stream fp): fprintf(fp, “Hello”);
Tập tin
Tập tin
Nhu cầu
Dữ liệu giới hạn và được lưu trữ tạm thời
Nhập: gõ từ bàn phím.
Xuất: hiển thị trên màn hình.
Lưu trữ dữ liệu: trong bộ nhớ RAM.
Mất thời gian, không giải quyết được bài toán với số dữ liệu lớn.
Cần một thiết bị lưu trữ sao cho dữ liệu vẫn còn khi kết thúc chương trình, có thể sử dụng nhiều lần và kích thước không hạn chế.
Tập tin
Tập tin
Khái niệm
Tập hợp thông tin (dữ liệu) được tổ chức theo một dạng nào đó với một tên xác định.
Một dãy byte liên tục (ở góc độ lưu trữ).
Được lưu trữ trong các thiết bị lưu trữ ngoài như đĩa mềm, đĩa cứng, USB…
Vẫn tồn tại khi chương trình kết thúc.
Kích thước không hạn chế (tùy vào thiết bị lưu trữ)
Cho phép đọc dữ liệu (thiết bị nhập) và ghi dữ liệu (thiết bị xuất).
Tập tin
Tập tin
Phân loại
Theo người sử dụng: quan tâm đến nội dung
tập tin nên sẽ phân loại theo phần mở rộng
.EXE, .COM, .CPP, .DOC, .PPT, …
Theo người lập trình: tự tạo các stream tường minh để kết nối với tập tin xác định nên sẽ
phân loại theo cách sử dụng stream trong C
tập tin kiểu văn bản (ứng với stream
văn bản) và tập tin kiểu nhị phân (ứng với stream nhị phân).
Tập tin
Phân loại tập tin
Tập tin kiểu văn bản (stream văn bản)
Dãy các dòng kế tiếp nhau.
Mỗi dòng dài tối đa 255 ký tự và kết thúc bằng ký hiệu cuối dòng (end_of_line).
Dòng không phải là một chuỗi vì không được kết thúc bởi ký tự ‘ ’.
Khi ghi ‘ ’ được chuyển thành cặp ký tự CR (về đầu dòng, mã ASCII 13) và LF (qua dòng, mã ASCII 10).
Khi đọc thì cặp CR-LF được chuyển thành ‘ ’.
Tập tin
Phân loại tập tin
Tập tin kiểu nhị phân (stream nhị phân)
Dữ liệu được đọc và ghi một cách chính xác, không có sự chuyển đổi nào cả.
Ký tự kết thúc chuỗi ‘ ’ và end_of_line không có ý nghĩa là cuối chuỗi và cuối dòng mà được xử lý như mọi ký tự khác.
Tập tin
Quy tắc đặt tên tập tin
Tập tin
Tên
(name)
.
Mở rộng
(extension)
Định vị tập tin
Đường dẫn
Chỉ đến một tập tin không nằm trong thư mục hiện hành. Ví dụ: c:datalist.txt chỉ tập tin list.txt nằm trong thư mục data của ổ đĩa C.
Trong chương trình, đường dẫn này được ghi trong chuỗi như sau: “c:\data\list.txt”
Dấu ‘’ biểu thị ký tự điều khiển nên để thể hiện nó ta phải thêm một dấu ‘’ ở trước. Nhưng nếu chương trình yêu cầu nhập đường dẫn từ bàn phím thì chỉ nhập một dấu ‘’.
Tập tin
Quy trình thao tác với tập tin
1. Mở tập tin: tạo một stream nối kết với tập tin cần mở, stream được quản lý bởi biến con trỏ đến cấu trúc FILE
Cấu trúc được định sẵn trong STDIO.H
Các thành phần của cấu trúc này được dùng trong các thao tác xử lý tập tin.
2. Sử dụng tập tin (sau khi đã mở được tập tin)
Đọc dữ liệu từ tập tin đưa vào chương trình.
Ghi dữ liệu từ chương trình lên tập tin.
3. Đóng tập tin (sau khi sử dụng xong).
Tập tin
Hàm mở tập tin
Tập tin
Mở tập tin có tên (đường dẫn) là chứa trong filename với kiểu mở mode (xem bảng).
Thành công: con trỏ kiểu cấu trúc FILE
Thất bại: NULL (sai quy tắc đặt tên tập tin, không tìm thấy ổ đĩa, không tìm thấy thư mục, mở tập tin chưa có để đọc, …)
FILE* fp = fopen(“taptin.txt”, “rt”);
if (fp == NULL)
printf(“Khong mo duoc tap tin!”);
Trả về
FILE *fopen(const char *filename, const char *mode)
Đối số mở tập tin (mode)
Tập tin
Đọc và ghi dữ liệu (stdio.h)
Thực hiện đọc/ghi dữ liệu theo các cách sau:
Nhập/xuất theo định dạng
Hàm: fscanf, fprintf
Chỉ dùng với tập tin kiểu văn bản.
Nhập/xuất từng ký tự hay dòng lên tập tin
Hàm: getc, fgetc, fgets, putc, fputs
Chỉ nên dùng với kiểu văn bản.
Đọc/ghi trực tiếp dữ liệu từ bộ nhớ lên tập tin
Hàm: fread, fwrite
Chỉ dùng với tập tin kiểu nhị phân.
Tập tin
Hàm xuất theo định dạng
Tập tin
Ghi dữ liệu có chuỗi định dạng fnt (giống hàm printf) vào stream fp.
Nếu fp là stdout thì hàm giống printf.
Thành công: trả về số byte ghi được.
Thất bại: trả về EOF (có giá trị là -1, được định nghĩa trong STDIO.H, sử dụng trong tập tin có kiểu văn bản)
int i = 2912; int c = ‘P’; float f = 17.06;
FILE* fp = fopen(“taptin.txt”, “wt”);
if (fp != NULL)
fprintf(fp, “%d %c %.2f ”, i, c, f);
Trả về
int fprintf(FILE *fp, char *fnt, …)
Hàm nhập theo định dạng
Tập tin
Đọc dữ liệu có chuỗi định dạng fnt (giống hàm scanf) từ stream fp.
Nếu fp là stdin thì hàm giống printf.
Thành công: trả về số thành phần đọc và lưu trữ được.
Thất bại: trả về EOF.
int i;
FILE* fp = fopen(“taptin.txt”, “rt”);
if (fp != NULL)
fscanf(fp, “%d”, &i);
Trả về
int fscanf(FILE *fp, char *fnt, …)
Hàm nhập theo định dạng
Ví dụ
Một tập tin chứa nhiều dòng, mỗi dòng là thông tin mỗi sinh viên theo định dạng sau:
Ví dụ: 0312078-H. P. Trang(Nu) 17/06/85 8.5
Đọc chuỗi thông tin phức hợp
%[chuỗi]: đọc cho đến khi không gặp ký tự nào trong chuỗi thì dừng.
%[^chuỗi]: đọc cho đến khi gặp một trong những ký tự trong chuỗi thì dừng.
Tập tin
Hàm Tách 2 Mảng
Tập tin
struct SINHVIEN {
char MSSV[8]; // 0312078
char HoTen[30]; // H. P. Trang
char GioiTinh[4]; // Nu
char NTNS[9]; // 17/06/85
float DiemTB; // 8.5
};
void main() {
SINHVIEN sv;
FILE *fp = fopen(“dssv.txt”, “rt”);
if (fp != NULL) {
fscanf(fp, “%[^-]-%[^(](%[^)]) %[^ ]
%f”, &sv.MSSV, &sv.HoTen,
&sv.GioiTinh, &sv.NTNS, &sv.DiemTB);
fclose(fp);
}
}
Hàm nhập ký tự
Tập tin
Đọc một ký tự từ stream fp.
getc là macro còn fgetc là phiên bản hàm của macro getc.
Thành công: trả về ký tự đọc được sau khi chuyển sang số nguyên không dấu.
Thất bại: trả về EOF khi kết thúc stream fp hoặc gặp lỗi.
char ch;
FILE* fp = fopen(“taptin.txt”, “rt”);
if (fp != NULL)
ch = getc(fp); // ch = fgetc(fp);
Trả về
int getc(FILE *fp) và int fgetc(FILE *fp)
Hàm nhập chuỗi
Tập tin
Đọc một dãy ký tự từ stream fp vào vùng nhớ str, kết thúc khi đủ n-1 ký tự hoặc gặp ký tự xuống dòng.
Thành công: trả về str.
Thất bại: trả về NULL khi gặp lỗi hoặc gặp ký tự EOF.
char s[20];
FILE* fp = fopen(“taptin.txt”, “rt”);
if (fp != NULL)
fgets(s, 20, fp);
Trả về
Int fgets(char *str, int n, FILE *fp)
Hàm xuất ký tự
Tập tin
Ghi ký tự ch vào stream fp.
putc là macro còn fputc là phiên bản hàm của macro putc.
Thành công: trả về ký tự ch.
Thất bại: trả về EOF.
FILE* fp = fopen(“taptin.txt”, “rt”);
if (fp != NULL)
putc(‘a’, fp); // hoặc fputc(‘a’, fp);
Trả về
int putc(int ch, FILE *fp) và int fputc(in ch, FILE *fp)
Hàm xuất chuỗi
Tập tin
Ghi chuỗi ký tự str vào stream fp. Nếu fp là stdout thì fputs giống hàm puts, nhưng puts ghi ký tự xuống dòng.
Thành công: trả về ký tự cuối cùng đã ghi.
Thất bại: trả về EOF.
char s[] = “Ky thuat lap trinh”;
FILE* fp = fopen(“taptin.txt”, “wt”);
if (fp != NULL)
fputs(s, fp);
Trả về
int fputs(const char *str, FILE *fp)
Hàm xuất trực tiếp
Tập tin
Ghi count mẫu tin có kích thước mỗi mẫu tin là size (byte) từ vùng nhớ buf vào stream fp (theo kiểu nhị phân).
Thành công: trả về số lượng mẫu tin (không phải số lượng byte) đã ghi.
Thất bại: số lượng nhỏ hơn count.
int a[] = {1, 2, 3};
FILE* fp = fopen(“taptin.dat”, “wb”);
if (fp != NULL)
fwrite(a, sizeof(int), 3, fp);
Trả về
int fwrite(void *buf, int size, int count, FILE *fp)
Hàm nhập trực tiếp
Tập tin
Đọc count mẫu tin có kích thước mỗi mẫu tin là size (byte) vào vùng nhớ buf từ stream fp (theo kiểu nhị phân).
Thành công: trả về số lượng mẫu tin (không phải số lượng byte) thật sự đã đọc.
Thất bại: số lượng nhỏ hơn count khi kết thúc stream fp hoặc gặp lỗi.
int a[5];
FILE* fp = fopen(“taptin.dat”, “wb”);
if (fp != NULL)
fread(a, sizeof(int), 3, fp);
Trả về
int fread(void *buf, int size, int count, FILE *fp)
Hàm đóng tập tin xác định
Tập tin
Đóng stream fp.
Dữ liệu trong stream fp sẽ được “vét” (ghi hết lên đĩa) trước khi đóng.
Thành công: trả về 0.
Thất bại: trả về EOF.
FILE* fp = fopen(“taptin.txt”, “rt”);
…
fclose(fp);
Trả về
int fclose(FILE *fp)
Hàm đóng tất cả stream
Tập tin
Đóng tất cả stream đang được mở ngoại trừ các stream chuẩn stdin, stdout, stdprn, stderr, stdaux.
Nên đóng từng stream thay vì đóng tất cả.
Thành công: trả về số lượng stream được đóng.
Thất bại: trả về EOF.
FILE* fp1 = fopen(“taptin1.txt”, “rt”);
FILE* fp2 = fopen(“taptin2.txt”, “wt”);
…
fcloseall();
Trả về
int fcloseall()
“Vét” dữ liệu trong stream
Khi chương trình kết thúc, các stream đang mở sẽ được “vét” (flush) và đóng lại. Tuy nhiên, ta nên đóng một các tường minh các stream sau khi sử dụng xong (nhất là các stream tập tin) để tránh các sự cố xảy ra trước khi chương trình kết thúc bình thường.
Ta có thể “vét” dữ liệu trong stream mà không cần đóng stream đó bằng một trong hai hàm:
Vét stream fp xác định: int fflush(FILE *fp);
Vét tất cả stream đang mở: int flushall();
Tập tin
Con trỏ chỉ vị (position indicator)
Khái niệm
Được tạo tự động khi mở tập tin.
Xác định nơi diễn ra việc đọc/ghi trong tập tin
Vị trí con trỏ chỉ vị
Khi tập tin chưa mở: ở đầu tập tin (giá trị 0).
Khi mở tập tin:
Ở cuối tập tin khi mở để chèn (mode a hay a+)
Ở đầu tập tin (hay giá trị 0) khi mở với các mode khác (w, w+, r, r+).
Tập tin
Truy xuất tuần tự & ngẫu nhiên
Truy xuất tuần tự (sequentially access)
Phải đọc/ghi dữ liệu từ vị trí con trỏ chỉ vị đến vị trí n-1 trước khi đọc dữ liệu tại vị trí n.
Không cần quan tâm đến con trỏ chỉ vị do con trỏ chỉ vị tự động chuyển sang vị trí kế tiếp sau thao tác đọc/ghi dữ liệu.
Truy xuất ngẫu nhiên (random access)
Có thể đọc/ghi tại vị trí bất kỳ trong tập tin mà không cần phải đọc/ghi toàn bộ dữ liệu trước đó quan tâm đến con trỏ chỉ vị.
Tập tin
Hàm đặt lại vị trí con trỏ chỉ vị
Tập tin
Đặt lại vị trí con trỏ chỉ vị về đầu (byte 0) tập tin fp.
Không
FILE* fp = fopen(“taptin.txt”, “w+”);
fprintf(fp, “0123456789”);
rewind(fp);
fprintf(fp, “*****”);
Trả về
void rewind(FILE *fp)
Hàm tái định vị con trỏ chỉ vị
Tập tin
Đặt vị trí con trỏ chỉ vị trong stream fp với vị trí offset so với cột mốc origin (SEEK_SET hay 0: đầu tập tin; SEEK_CUR hay 1: vị trí hiện tại; SEEK_END hay 2: cuối tập tin)
Thành công: trả về 0.
Thất bại: trả về giá trị khác 0.
FILE* fp = fopen(“taptin.txt”, “w+”);
fseek(fp, 0L, SEEK_SET); // rewind(fp);
fseek(fp, 0L, SEEK_END); // cuối tập tin
fseek(fp, -2L, SEEK_CUR);// lùi lại 2 vị trí
Trả về
int fseek(FILE *fp, long offset, ing origin)
Hàm xác định vị trí con trỏ chỉ vị
Tập tin
Hàm trả về vị trí hiện tại của con trỏ chị vị (tính từ vị trí đầu tiên của tập tin, tức là 0) của stream fp.
Thành công: trả về vị trí hiện tại của con trỏ chỉ vị.
Thất bại: trả về -1L.
FILE* fp = fopen(“taptin.txt”, “rb”);
fseek(fp, 0L, SEEK_END);
long size = ftell(fp);
printf(“Kich thuoc tap tin la %ld ”, size);
Trả về
long ftell(FILE *fp)
Dấu hiệu kết thúc tập tin
Khi đã biết kích thước tập tin
Sử dụng fwrite để lưu n mẫu tin
kích thước = n * sizeof(1 mẫu tin);
Sử dụng hàm fseek kết hợp hàm ftell
Khi chưa biết kích thước tập tin
Hằng số EOF (=-1) (chỉ cho tập tin văn bản)
while ((c = fgetc(fp)) != EOF) …
Hàm int feof(FILE *fp) (cho cả 2 kiểu tập tin)
trả về số 0 nếu chưa đến cuối tập tin
trả về số khác 0 nếu đã đến cuối tập tin.
Tập tin
Các hàm quản lý tập tin
Hàm nhập xuất tập tin (File I/O function) là các đã đề cập phần trước
Mở và đóng tập tin: fopen, fclose
Nhập/Xuất tập tin:
Theo định dạng: fprintf, fscanf
Từng ký tự hay chuỗi: fputc, fputs, fgetc, fgets
Trực tiếp từ bộ nhớ: fwrite, fread
Hàm quản lý tập tin (File-Management function)
Xóa tập tin: remove
Đổi tên tập tin: rename
Tập tin
Hàm xóa tập tin
Tập tin
Xóa tập tin xác định bởi filename.
Thành công: trả về 0.
Thất bại: trả về -1.
if (remove(“c:\vc.txt”) == 0)
printf(“Tap tin vc.txt da bi xoa!”);
else
printf(“Ko xoa duoc tap tin vc.txt!”);
Trả về
int remove(const char *filename)
Hàm đổi tên tập tin
Tập tin
Đổi tên tập tin oldname thành newname.
Hai tập tin phải cùng ổ đĩa nhưng không cần thiết phải cùng thư mục (có thể sử dụng để di chuyển hay sao chép tập tin).
Thành công: trả về 0.
Thất bại: trả về -1.
if (rename(“c:\a.txt”, “c:\BT.cpp”) == 0)
printf(“Doi ten tap tin thanh cong”);
else
printf(“Doi ten tap tin that bai”);
Trả về
int rename(const char *oldname, const char *newname)
Bài tập lý thuyết
Bài 1: Sự khác nhau giữa stream kiểu văn bản và stream kiểu nhị phân?
Stream văn bản tự động chuyển đổi ký tự ‘ ’ thành cặp ký tự CR-LF trong khi stream nhị phân không thực hiện việc chuyển đổi này (xem mọi ký tự đều như nhau).
Bài 2: Cần phải làm gì trước khi muốn truy xuất tập tin?
Mở tập tin (tạo stream kết nối với tập tin cần mở) bằng hàm fopen.
Tập tin
Bài tập lý thuyết
Bài 3: Khi mở tập tin bằng fopen, ta cần phải xác định thông tin nào và hàm sẽ trả về cái gì?
Cần xác định tên tập tin cần mở và mode mở tập tin này. Hàm sẽ trả về một con trỏ đến kiểu FILE, con trỏ này được dùng thay cho tập tin trong chương trình.
Bài 4: Ba phương pháp để truy xuất tập tin?
1. Theo định dạng.
2. Theo ký tự / chuỗi ký tự.
3. Trực tiếp từ bộ nhớ.
Tập tin
Bài tập lý thuyết
Bài 5: Hai phương pháp để đọc thông tin từ tập tin là gì?
1. Truy xuất tuần tự (theo thứ tự)
2. Truy xuất ngẫu nhiên (tại vị trí bất kỳ)
Bài 6: Giá trị của EOF?
-1 (định nghĩa trong STDIO.H)
Bài 7: Ta dùng hằng ký hiệu EOF để làm gì?
Được sử dụng với các tập tin kiểu văn bản nhằm xác định dấu hiệu cuối tập tin.
Tập tin
Bài tập lý thuyết
Bài 8: Cách xác định cuối tập tin trong kiểu văn bản và kiểu nhị phân?
Sử dụng hàm foef cho cả hai kiểu tập tin. Trong kiểu văn bản có thể sử dụng hằng EOF.
Bài 9: Con trỏ chỉ vị là gì và cách thay đổi nó?
Con trỏ chỉ vị đánh dấu vị trí trong của một tập tin, nơi diễn ra các thao tác đọc/ghi.
Thay đổi vị trí con trỏ chỉ vị bằng hàm rewind (về đầu tập tin) và fseek (về vị trí bất kỳ).
Tập tin
Bài tập lý thuyết
Bài 10: Nếu mở một tập tin chưa có (bằng mode w), cho biết giá trị của con trỏ chị vị lúc đầu?
Con trỏ chỉ vị chỉ đến ký tự đầu tiên của tập tin (vị trí 0).
Bài 11: Viết lệnh đóng tất cả các stream tập tin.
fcloseall();
Bài 12: Trình bày hai cách khác nhau để chuyển con trỏ chỉ vị về đầu tập tin fp.
1. rewind(fp);
2. fseek(fp, 0, SEEK_SET);
Tập tin
Bài tập lý thuyết
Bài 13: Đoạn chương trình sau có sai không?
Tập tin
void main()
{
FILE *fp;
int c;
if ((fp = fopen(“abc.xyz”, “rb”)) == NULL)
printf(“Khong mo duoc tap abc.xyz ”);
else
{
while ((c = fgetc(fp)) != EOF)
fprintf(stdout, “%c”, c);
fclose(fp);
}
}
Bài tập thực hành
Bài 14: Viết chương trình ghi 3 số nguyên a, b, c được nhập từ bàn phím vào một tập tin.
Bài 15: Viết chương trình đọc 3 số nguyên a, b, c từ một tập tin, sau đó giải phương trình ax2+ bx + c = 0 rồi ghi kết quả vào một tập tin khác.
Bài 16: Viết chương trình đọc n số nguyên từ một tập tin cho trước, sau đó sắp xếp tăng dần rồi ghi kết quả vào 1 tập tin khác. Ví dụ:
4 4
2 5 1 4 1 2 4 5
Tập tin
Bài tập thực hành
Bài 17: Viết chương trình ghi các dòng văn bản được nhập từ bàn phím lên tập tin.
Bài 18: Viết chương trình in nội dung một tập tin lên màn hình.
Bài 19: Viết chương trình đếm số ký tự chữ cái của tập tin và xuất kết quả ra một tập tin khác.
Bài 20: Viết chương trình đếm số từ của tập tin và xuất kết quả ra một tập tin khác.
Bài 21: Viết chương trình đếm số lần lặp lại của một từ trong một tập tin.
Tập tin
Bài tập thực hành
Bài 22: Viết chương trình mở tập tin văn bản đã có trên đĩa, sao chép nó thành một tập tin văn bản mới với điều kiện là các chữ thường đổi thành chữ hoa, tất cả các ký tự khác không đổi.
Bài 23: Viết chương trình ghép 2 tập tin văn bản, nội dung tập tin thứ hai được ghép sau tập tin thứ nhất.
Bài 24: Viết sao sao chép một tập tin cho trước.
Bài 25: Viết chương trình ghi một danh sách cấu trúc xuống tập tin sau đó đọc lên kiểm tra lại.
Tập tin
* Một số tài liệu cũ có thể bị lỗi font khi hiển thị do dùng bộ mã không phải Unikey ...
Người chia sẻ: Trần Tuấn Vũ
Dung lượng: |
Lượt tài: 1
Loại file:
Nguồn : Chưa rõ
(Tài liệu chưa được thẩm định)