ự ậ
Ậ
Ậ
Ỹ
Th c t p K THU T L P TRÌNH
ữ ệ
ự
ứ
ấ
ầ Tu n 46
: Xây d ng c u trúc d li u và các ch c năng
ấ ữ ệ
ậ
nh p/xu t d li u
Yêu cầu:
- Xây dựng cấu trúc dữ liệu phù hợp để quản lý đối tượng sinh viên,
gồm các thông tin:
Mã l pớ
Mã sinh viên
H và tên ọ
Ngày sinh
ể Đi m trung bình tích lũy
- Dữ liệu (hồ sơ sinh viên) được ghi trên file.
- Xây dựng các chức năng cho phép nhập hồ sơ, in danh sách đã
nhập.
- Tự động chỉnh sửa chính tả khi nhập họ tên sinh viên.
- Kiểm tra tính hợp lệ của ngày sinh khi nhập. Ngày sinh có dạng dd/mm/yyyy, dd là ngày có giá trị trong khoảng từ 1 đến 31, mm là tháng có giá trị trọng khoảng 1 đến 12 và yyyy là năm có giá trị từ 1900 đến 2016; và dd/mm/yyyy phải là ngày hợp hệ (có trên lịch), ví dụ ngày 30/2/2016 là không hợp lệ.
- Kiểm tra tính hợp lệ của điểm trung bình tích lũy, điểm trung bình
tích lũy >=0 và <=10.
- Các chức năng này được kết hợp trong chương trình đã xây dựng
ở các tuần trước.
Kiến thức liên quan:
A. KIỂU BẢN GHI
ấ ả ộ ớ m t SINH VIÊN v i các thông tin:
1 Khái niệm ể ế ề V n đ : Làm th nào đ mô t ố - Mã s sinh viên;
ỉ ườ ể ng trú ả ặ ồ ọ - H tên; - Ngày tháng năm sinh; ớ - Gi i tính; ị - Đ a ch th ế Ho c làm th nào đ mô t NGÀY THÁNG bao g m các thông tin:
- Ngày; - Tháng; - Năm ế ầ
ấ ừ ầ ử ụ ườ ậ ữ ệ ữ ể i l p trình nh ng ki u d li u đã có
ướ
ấ ầ
ầ ượ ọ ộ ườ ồ ề ng (field).
ể ữ ệ c g i là m t tr ể ầ ử ủ ệ ả ả
ự ể ể ể ả
ể ấ ủ ữ ậ => H u h t các ngôn ng l p trình trong đó có C/C++ cho phép ng ớ ự ị đ nh nghĩa ra c u trúc m i theo nhu c u s d ng t t ị ặ ho c đã đ nh nghĩa tr c đó. ể ể Ki u c u trúc (Structure) là ki u d li u bao g m nhi u thành ph n có ki u ỗ khác nhau, m i thành ph n đ ữ S khác bi t gi a ki u c u trúc và ki u m ng là: các ph n t ầ ử ủ ki u còn các ph n t là c a ki u c u trúc v i 7
ể ấ c a m ng là cùng c a ki u c u trúc có th có ki u khác nhau. Hình nh sau ớ tr 1 ể ấ ngườ 3 2 4 5 7 6
ể ạ ả còn ki u m ng có d ng:
0 1 2 3 4 5 6 7 8 9 1 1 1 1 14
0 1 2 3
Cú pháp 1:
ấ struct
{
ể ườ
ể ườ
……..
ể ườ
};
Cú pháp 2:
typedef struct
{
ể ườ
ể ườ
……..
2
ể ườ
ấ
}
Trong đó:
ấ ộ ượ ặ ắ ặ ủ ể
c đ t theo quy t c đ t tên c a danh bi u; -
ể ấ ẽ tên này mang ý nghĩa s là tên ki u c u trúc;
ườ ỗ ườ ữ ệ ấ ng i> (i=1..n): m i tr ộ
ng trong c u trúc có d li u thu c ể
- ủ ể ườ ả ộ ượ ặ ắ ặ ki u gì (tên c a tr ng ph i là m t tên đ c đ t theo quy t c đ t tên ể ủ
c a danh bi u). ể ể ả ộ ủ
Ví d 1ụ : Đ qu n lý ngày, tháng, năm c a m t ngày trong năm ta có th khai báo ể ấ ồ ki u c u trúc g m 3 thông tin: ngày, tháng, năm. struct KieuNgayThang
{ unsigned char Ngay;
unsigned char Thang;
unsigned int Nam; };
typedef struct
{ unsigned char Ngay;
unsigned char Thang;
unsigned int Nam; ầ ỗ ượ ả ở ố } KieuNgayThang;
Ví d 2ụ : M i sinh viên c n đ c qu n lý b i các thông tin: Mã s sinh viên, h ọ ớ ỉ ườ ể tên, ngày tháng năm sinh, gi ị
i tính, đ a ch th ng trú. Lúc này ta có th khai báo ộ ồ m t struct g m các thông tin trên. struct KieuSinhVien
{
char MSSV[10];
char HoTen[40];
struct KieuNgayThang NgaySinh;
int Phai;
char DiaChi[40]; }; typedef struct
{
char MSSV[10];
char HoTen[40];
KieuNgayThang NgaySinh;
int Phai;
char DiaChi[40];
} KieuSinhVien; ỗ ầ ộ o ồ
ế
M i thành ph n gi ng là m t bi n riêng thu c c u trúc, nó g m
ầ ấ
ộ
ượ ọ ườ ể ầ ộ ố
ki u và tên thành ph n. M t thành ph n cũng còn đ c g i là tr ng. ầ ủ ể ấ o ể
ả ố ầ
ặ
ế
Ph n tên c a ki u c u trúc và ph n danh sách bi n có th có ho c
ấ
ự ế
k t thúc cu i cùng ph i là d u ẩ ấ không. Tuy nhiên trong khai báo kí t
ch m ph y (;). ượ c phép khai báo l ng nhau, nghĩa là m t thành o ầ ủ ể ạ ồ
ộ ườ ể ấ
Các ki u c u trúc đ
ể ấ
ph n c a ki u c u trúc có th l ộ
ể ấ
ng có ki u c u trúc. i là m t tr ẽ ượ o ấ
ể
M t bi n có ki u c u trúc s đ
ượ ắ ứ ự ấ ộ
ệ ự ộ
ế
ệ ủ
th c hi n c a nó đ ấ
ụ
c s p liên t c theo th t ớ
c c p phát b nh sao cho các
xu t hi n trong khai báo. ế ấ ệ ươ ự ư ế ộ 2. Khai báo biến cấu trúc
Vi c khai báo bi n c u trúc cũng t ng t ể ữ ệ
nh khai báo bi n thu c ki u d li u chu n. ẩ Cú pháp: ố ớ ấ ượ ị c đ nh nghĩa theo cách 1: - Đ i v i c u trúc đ ế ế ấ struct ố ớ ấ ượ ị c đ nh nghĩa theo cách 2: - Đ i v i các c u trúc đ ế ấ ế
ế ế ấ ể
Ví dụ: Khai báo bi n NgaySinh có ki u c u trúc KieuNgayThang; bi n SV có ể ấ ki u c u trúc KieuSinhVien. struct KieuNgayThang NgaySinh;
struct KieuSinhVien SV;
KieuNgayThang NgaySinh;
KieuSinhVien SV; ấ ế ừ ế ấ ủ ng c a bi n c u trúc 3. Các thao tác trên biến kiểu cấu trúc
ườ
Truy xu t đ n t ng tr
Cú pháp: ế ấ ườ ử ụ ế ể ấ Khi s ấ
d ng cách truy xu t theo ki u này, các thao tác trên ườ ữ ệ ủ ư ế ể ố trúc>. ườ ế ươ ữ ệ ừ ọ ế ẩ Ví d 1ụ : Vi t ch ng trình cho phép đ c d li u t bàn phím cho bi n m u tin ế ẩ
SinhVien và in bi n m u tin đó lên màn hình: #include void InSV(KieuSinhVien s)
{
printf(“MSSV: | Ho va ten | Ngay Sinh | Dia chi\n”); printf(“%s | %s | %d%d%d | %s\n”,s.MSSV,s.HoTen, s.NgaySinh.Ngay,s.NgaySinh.Thang,s.NgaySinh.Nam,s.DiaChi); }
int main()
{
KieuSinhVien SV, s;
printf(“Nhap MSSV: “);gets(SV.MSSV);
printf(“Nhap Ho va ten: “);gets(SV.HoTen);
printf(“Sinh ngay: “);scanf(“%d”,&SV.NgaySinh.Ngay);
printf(“Thang: “);scanf(“%d”,&SV.NgaySinh.Thang);
printf(“Nam: “);scanf(“%d”,&SV.NgaySinh.Nam);
printf(“Gioi tinh (0: Nu), (1: Nam): “);scanf(“%d”,&SV.Phai);
fflush(stdin);
printf(“Dia chi: “);gets(SV.DiaChi);
InSV(SV);
s=SV;
InSV(s);
getch();
return 0;
}
L u ýư : ự ể ế ấ ấ - Các bi n c u trúc có th gán cho nhau. Th c ch t đây là thao tác trên ộ ấ ả ộ ườ ẽ toàn b c u trúc không ph i trên m t tr ng riêng r nào. Ch ươ
ng ộ ụ
trình trên dòng s=SV là m t ví d ; ể ự ệ ế ể ấ ớ ượ c các thao tác - V i các bi n ki u c u trúc ta không th th c hi n đ sau đây: ế ấ ử ụ ậ S d ng các hàm xu t nh p trên bi n c u trúc;
ấ ố ọ ệ Các phép toán quan h , các phép toán s h c và logic. ủ ứ ậ ố ổ ế ằ ứ Ví d 2ụ : Nh p vào hai s ph c và tính t ng c a chúng. Ta bi ố
t r ng s ph c là ố ự ộ ặ ầ ả ự ầ ọ m t c p (a,b) trong đó a, b là các s th c, a g i là ph n th c, b là ph n o. (Đôi ườ ế ố ứ ướ ạ ộ ơ ị ả khi ng i ta cũng vi t s ph c d i d ng a + ib trong đó i là m t đ n v o có ọ ố ủ ứ ổ tính ch t iấ 2=1). G i s ph c c1=(a1, b1) và c2=(a2,b2) khi đó t ng c a hai s ố ộ ố ứ ứ ể ớ ế ph c c1 và c2 là m t s ph c c3 mà c3=(a1+a2, b1+b2). V i hi u bi ư ậ
t nh v y ộ ấ ỗ ố ể ườ ộ ườ ứ
ta có th xem m i s ph c là m t c u trúc có hai tr ng, m t tr ễ
ể
ng bi u di n ộ ườ ự ầ ầ ả ủ ệ ễ ể ổ cho ph n th c, m t tr ng bi u di n cho ph n o. Vi c tính t ng c a hai s ố ứ ượ ự ộ ầ ả ự ấ ằ ầ ầ ớ ph c đ ộ
c tính b ng cách l y ph n th c c ng v i ph n th c và ph n o c ng ầ ả ớ
v i ph n o. #include return 0;
}
ở ạ ấ
ở ạ
ệ ể ượ ự ệ ế ấ Kh i t o c u trúc
ấ
Vi c kh i t o c u trúc có th đ c th c hi n trong lúc khai báo bi n c u trúc. ườ ủ ấ ượ ượ ạ ữ ấ Các tr ng c a c u trúc đ ở ạ
c kh i t o đ c đ t gi a 2 d u { và }, chúng đ ượ
c ở ấ ẩ phân cách nhau b i d u ph y (,). ở ạ ụ ế ấ
Ví d : Kh i t o bi n c u trúc NgaySinh: struct KieuNgayThang NgaySinh ={29, 8, 1986}; ỏ ể ế ệ ấ ộ ươ ự ư 4. Con trỏ cấu trúc
Khai báo
Vi c khai báo m t bi n con tr ki u c u trúc cũng t ng t nh khi khai báo ế ặ ấ ỏ ộ ướ ế m t bi n con tr khác, nghĩa là đ t thêm d u * vào phía tr c tên bi n. Cú pháp: ế ấ ỏ struct ỏ ấ ư ể ể ộ Ví dụ: Ta có th khai báo m t con tr c u trúc ki u NgayThang nh sau: struct NgayThang *p; /* NgayThang *p; // Nếu có định nghĩa kiểu */ ỏ ể ấ
ỏ ấ ỉ ụ ể ỏ ư ế ế ị ử ụ
S d ng các con tr ki u c u trúc
Khi khai báo bi n con tr c u trúc, bi n con tr ch a có đ a ch c th . Lúc này ỉ ớ ượ ấ ể ư ữ ị ượ nó ch m i đ c c p phát 2 byte đ l u gi ỉ
đ a ch và đ ậ
c ghi nh n là con tr ỏ ỉ ế ỉ ế ố ượ ư ấ ụ ể ư
ch đ n 1 c u trúc, nh ng ch a ch đ n 1 đ i t ố
ng c th . Mu n thao tác trên ỏ ấ ợ ệ ươ ự ư ả con tr c u trúc h p l , cũng t ng t ỏ
nh các con tr khác, ta ph i: ử ụ ấ ộ ớ - C p phát m t vùng nh cho nó (s d ng hàm malloc() hay calloc); ế ấ ỉ ủ ả ặ ộ ị - Ho c, cho nó qu n lý đ a ch c a m t bi n c u trúc nào đó. ị ủ ấ ở ạ Ví dụ: Sau khi kh i t o giá tr c a c u trúc: struct NgayThang Ngay = {29,8,1986}; p = &Ngay; ứ ị ỉ ủ ế ỏ lúc này bi n con tr p đã ch a đ a ch c a Ngay. ầ ủ ấ ậ ượ ả Truy c p các thành ph n c a c u trúc đang đ ỏ
ở
c qu n lý b i con tr ế ừ ể ậ ườ ủ ấ ỏ ủ Đ truy c p đ n t ng tr ng c a 1 c u trúc thông qua con tr c a nó, ta s ử ử ấ ấ ấ ẫ ụ
d ng toán t ể ử ụ
d u mũi tên (>: d u và d u >). Ngoài ra, ta v n có th s d ng ữ ệ ể ậ ượ ả ế
đ n phép toán * đ truy c p vùng d li u đang đ ỏ ấ
ở
c qu n lý b i con tr c u ể ấ ầ ế trúc đ l y thông tin c n thi t. ử ụ ỏ ấ Ví dụ: S d ng con tr c u trúc. #include ấ ử ụ ố ố ủ ư ế ể ấ ả ề ự ớ ố ố ử ụ ấ ử ạ
ỏ ấ
Cho phép s d ng c u trúc, con tr c u trúc là đ i s c a hàm nh các lo i
bi n khác
Cho phép hàm xây d ng tr v là ki u c u trúc
Ví d : X lý danh sách sinh viên, s d ng hàm v i đ i s là c u trúc ụ
#include struct Ngaythang {
int ng ;
int th ;
int nam ;
};
//Sinh vien
struct Sinhvien {
char hoten[25] ;
Ngaythang ns;
int gt;
float diem ;
} ;
//cac ham xu ly
int sua(Sinhvien &r) ;
int in(Sinhvien x) ;
int nhap(Sinhvien *p) ;
int nhapds(Sinhvien *a, int n) ;
int suads(Sinhvien *a, int n) ;
int inds(const Sinhvien *a, int n) ;
//
struct Sinhvien a[10]; int main()
{ nhap(a);
in(a[1]);
//
// sua(a[1]); nhapds(a,9);
suads(a,9);
inds(a,9);
getch();
return 0; }
///trien khai cac ham
int sua(Sinhvien &r) {
int chon;
do { printf("1: Sua ho ten\n2: Sua ngay sinh\n3:Sua gioi tinh\n4:Sua diem\n5:In\n0: Ket thuc\n"); scanf("%d",&chon);
switch (chon)
{ case 1: printf("Nhap ho ten:");
scanf("%s",r.hoten);
break; case 2: printf("Nhap ngay thang nam sinh:");
scanf("%d%d%d",&r.ns.ng,&r.ns.th,&r.ns.nam);
break; case 3: printf("Nhap gioi tinh 0:Nu 1:Nam:");
scanf("%d",&r.gt) ;
break; case 4: printf("Nhap diem:");
scanf("%f",&r.diem);
break; case 5: printf("Sinh vien:");
in(r);
break; case 0: break; default: printf("Nhap gia tri khong dung\n");
break; } } while (chon) ; return 0;
}
////////
int in(Sinhvien x)
{
printf("Ho ten :%s\nNgay sinh %d/%d/%d\n",x.hoten,x.ns.ng, x.ns.th, x.ns.nam) ; printf("Gioi tinh :%s\nDiem :%f\n",(x.gt==1) ?"Nam" :"Nu",x.diem) ;
return 0;
} ///////
int nhap(Sinhvien *p)
{ printf("Nhap ho va ten: ");
scanf("%s",p>hoten);
printf("Nhap ngay sinh (ngay thang nam): ");
scanf("%d%d%d", &p>ns.ng ,&p>ns.th,&p>ns.nam);
printf("Gioi tinh 0: nu, 1: nam: ");
scanf("%d",& p>gt);
printf("Diem: ");
scanf("%f",& p>diem);
return 0; }
//////
int nhapds(Sinhvien *a, int n)
{
for (int i=1; i<=n; i++) nhap(&a[i]) ;
return 0;
}
/////
int suads(Sinhvien *a, int n)
{
int chon; do
{
printf("\nNhap phan tu duoc su tu 1 den %d, gia tri khac thoat:",n);
scanf("%d",&chon);
if(chon>0 &&chon<=n)
{
sua(a[chon]) ;
}
}while(chon>0 && chon<=n);
return 0;
}
//////////
int inds(const Sinhvien *a, int n)
{
for (int i=1; i<=n; i++)
in(a[i]) ;
return 0;
} ườ 5. Cấu trúc với thành phần kiểu bit
a. Tr ng bit ể ế ữ ậ Đ ti
ườ ư
ớ ố ượ ụ ộ ng bit xác đ nh không ph thu c vào s l ẩ ệ
ữ
t ki m trong l u tr , trong ngôn ng l p trình C cho phép khai báo
ố ượ
ị
ủ ấ
ng c a c u trúc v i s l
các tr
ng
ể ữ ệ
bit các ki u d li u chu n. ộ ườ ấ ố M t tr ộ
ng bit là m t khai báo tr ườ
ộ ớ ượ ủ
ấ ườ ể ợ ư ế ệ ằ ơ ng int và thêm d u: cùng s bit n theo
ụ
sau, trong đó 0 ≤ n < 15. Ví d do đ l n c a ngày không v
t quá 31, tháng
ng này trong c u trúc ngày tháng có th khai báo
không vu t quá 12 nên 2 tr
ti t ki m h n b ng 5 và 4 bit nh sau: struct Date {
int ng: 5;
int th: 4;
int nam:14;
} ;
ặ ể b. Đ c đi m ộ ấ ủ ứ ể ặ ầ ườ C n chú ý các đ c đi m sau c a m t c u trúc có ch a tr ng bit: ượ ố ụ − Các bit đ c b trí liên t c trên dãy các byte. ườ ả ặ ể
− Ki u tr ng bit ph i là int (signed ho c unsigned). ỗ ườ ộ − Đ dài m i tr ng bit không quá 16 bit. ộ ố ỏ ố ể ỏ ế ườ ụ − Có th b qua m t s bit n u b tr ng tên tr ng, ví d : struct tu { int: 8; int x:8; } ỗ ế ỏ ế ộ
ử ụ
m i m t bi n c u trúc theo khai báo trên g m 2 byte, b qua không s d ng
ấ
byte th p và tr ấ
ồ
ườ
ng x chi m byte (8 bit) cao. ỉ ủ ể ấ ầ ị − Không cho phép l y đ a ch c a thành ph n ki u bit. ự ượ ể ả ể
− Không th xây d ng đ c m ng ki u bit. ụ ế ầ ộ c tr ộ
ể
hàm m t thành ph n ki u bit. Ví d n u b là m t
ệ ả ề ừ
v t
ế ấ ượ
ầ ủ ể − Không đ
thành ph n c a bi n c u trúc x có ki u bit thì câu l nh sau là sai: return x.b ; // sai ụ ư ế ể tuy nhiên có th thông qua bi n ph nh sau: int tam = x.b ; return tam ;
ế ệ ộ ớ
t ki m b nh − Ti ể ấ ủ ộ ừ ể ụ ầ ể
(xem ví d trong ph n ki u − Dùng trong ki u union đ l y các bit c a m t t
h p). ợ 6. Câu lệnh typedef ậ ể ườ ể ượ ạ
c NSD t o m i s ớ ẽ ử ụ
ằ ệ
ộ ệ ượ ng các ki u đ
Đ thu n ti n trong s d ng, thông th
ư
ể
c gán cho m t tên ki u b ng câu l nh typedef nh sau: đ ể ể typedef ự ứ ụ ể ỉ ị ấ
Ví d : Đ t o ki u m i có tên Bool và ch ch a giá tr nguyên (th c ch t ỉ ầ ể ạ
ị ớ
ể ch c n 2 giá tr 0, 1), ta có th khai báo: typedef int Bool; ư ể ố khai báo này cho phép xem Bool nh ki u s nguyên. ể ặ ể ặ ớ ho c có th đ t tên cho ki u ngày tháng là Date v i khai báo sau: typedef struct Date {
int ng;
int th;
int nam; }; ể ử ụ ụ ể ể
khi đó ta có th s d ng các tên ki u này trong các khai báo (ví d tên ki u ả ạ ị ủ ố ủ
c a đ i, c a giá tr hàm tr l i …). 7. Hàm sizeof() ộ ặ ế ướ ủ ụ ể i kích th c c a m t bi n ho c ki u. Ví d : ầ ử ủ ả ạ
Hàm tr l
Bool a, b;
Date x, y, z[50];
printf("%d,%d,%d",sizeof(a),sizeof(b),sizeof(Bool)) ; // in 2,2,2
ố
printf("S ph n t
c a z =%d ",sizeof(z) / sizeof(Date)); // in 50 B. LÀM VIỆC VỚI FILE I. Một số khái niệm
ữ ệ ươ ượ ư ế D li u trong ch ng trình đ c l u tr ữ ở ế
RAM máy tính, vì th khi k t ươ ắ ữ ệ ẽ ị ả ữ ệ ể ử ầ thúc ch ng trình, t t máy d li u s b gi ả
i phóng. Đ x lý d li u c n ph i ứ ữ ộ ớ ướ ạ ậ ợ ư
l u tr trên b nh ngoài (đĩa c ng, USB, …) d i d ng file. File là t p h p các ụ ượ ư ữ ượ ử ọ ươ byte liên t c đ c l u tr và đ c gán tên g i. Khi x lý file ch ng trình có ữ ứ ử ể ỗ ớ ớ
th xem xét chu i byte v i cách nhìn khác nhau, có nh ng ng x khác nhau v i ỗ ợ ệ ể ả ớ ớ
ữ ệ
d li u. Trong C h tr vi c thao tác v i file v i quan đi m: file văn b n, file ị nh phân. ạ ậ ể ả ự lên đĩa. o File văn b n (Text File): là lo i t p tin dùng đ ghi các ký t ể ặ ệ ủ ậ ữ ệ ượ ư ữ ỗ Đi m đ c bi t là d li u c a t p tin đ c l u tr thành các dòng, m i dòng ượ ế ằ ự ệ ố ự đ c k t thúc b ng ký t xu ng dòng (new line), ký hi u ‘\n’; ký t này là s ự ự ề ầ ế ợ ủ
k t h p c a 2 ký t CR (Carriage Return V đ u dòng, mã Ascii là 13) và LF ỗ ậ ố ượ ế ở (Line Feed Xu ng dòng, mã Ascii là 10). M i t p tin đ c k t thúc b i ký t ự ở ổ ợ ị EOF (End Of File) có mã Ascii là 26 (xác đ nh b i t h p phím Ctrl + Z). ấ ậ ể ể ể ả ấ ỉ ầ
Truy xu t t p tin theo ki u văn b n ch có th truy xu t theo ki u tu n t . ự ệ ử ụ ể ậ ậ ị ớ
o T p tin nh phân: Quan đi m t p tin là dãy byte liên t c, vi c x lý v i ệ ọ ự ậ
t p tin d a trên vi c đ c ghi dãy byte. ế ậ ể ạ ệ ế ể ộ ộ Bi n t p tin: ữ ệ ậ
là m t bi n thu c ki u d li u t p tin dùng đ đ i di n cho ữ ệ ộ ậ ộ ậ ứ ượ ấ m t t p tin. D li u ch a trong m t t p tin đ ớ
c truy xu t qua các thao tác v i ế ậ ệ ạ ậ ố thông s là bi n t p tin đ i di n cho t p tin đó. ỏ ậ ượ ệ ở ạ Con tr t p tin: ộ ậ
Khi m t t p tin đ ể
c m ra đ làm vi c, t ờ
ỗ
i m i th i ủ ậ ộ ị ẽ ể ạ ẽ ả ệ ọ đi m, s có m t v trí c a t p tin mà t i đó vi c đ c/ghi thông tin s x y ra. ườ ỉ ế ặ ộ ỏ ị Ng i ta hình dung có m t con tr đang ch đ n v trí đó và đ t tên nó là con tr ỏ ậ
t p tin. ữ ệ ỏ ẽ ể ọ ộ ị Sau khi đ c/ghi xong d li u, con tr s chuy n d ch thêm m t ph n t ầ ử ố ậ ầ ử ữ ệ ế ấ ố ề
v phía cu i t p tin. Sau ph n t ủ ậ
d li u cu i cùng c a t p tin là d u k t thúc ậ
t p tin EOF (End Of File). ớ ậ II. Các thao tác trên tập tin
Các thao tác v i t p tin: ế ậ o Khai báo bi n t p tin. ở ậ ằ
o M t p tin b ng hàm fopen(). ủ ậ ữ ệ ử ự ệ ằ o Th c hi n các thao tác x lý d li u c a t p tin b ng các hàm ữ ệ ọ
đ c/ghi d li u. ậ ằ
o Đóng t p tin b ng hàm fclose(). Ở ờ ượ ị ớ ậ
đây, ta thao tác v i t p tin nh các hàm đ ư ệ
c đ nh nghĩa trong th vi n stdio.h. 1. Khai báo biến tập tin
Cú pháp ỏ ạ ế ệ ậ FILE ế ả ỏ ượ ở ấ ẩ Các bi n trong danh sách ph i là các con tr và đ c phân cách b i d u ph y(,). ụ Ví d : FILE *f1 ,*f2; 2. Mở tập tin
Cú pháp FILE *fopen(char *Path, const char *Mode) Trong đó: ỉ ườ ỗ ế ậ ẫ Path: chu i ch đ ng d n đ n t p tin trên đĩa. ẽ ở ứ ậ ỗ ị ị ể ủ
Mode: chu i xác đ nh cách th c mà t p tin s m . Các giá tr có th c a Mode: Chế Ý nghĩa ể ọ ả ậ ớ ể ả
M t p tin văn b n đ đ c
T o ra t p tin văn b n m i đ ghi
N i vào t p tin văn b n ả
ể ọ
ể ậ ị ị ị
T o ra t p tin nh phân đ ghi
N i vào t p tin nh phân ể ọ ả ể ọ ậ ả ở ậ
ạ
ố
ở ậ
ạ
ậ
ố
ở ộ ậ
ạ
ố ớ ậ ả đ ộ
r
w
ậ
a
rb M t p tin nh phân đ đ c
wb
ab
r+ M m t t p tin văn b n đ đ c/ghi
w+
a+ T o ra t p tin văn b n đ đ c ghi
ạ
N i vào hay t o m i t p tin văn b n đ ể ể ọ
ể ọ ị
ị ọ
đ c/ghi
ậ
ở
ậ
ạ
ố ị r+b M ra t p tin nh phân đ đ c/ghi
w+b T o ra t p tin nh phân đ đ c/ghi
ạ
a+b N i vào hay t o m i t p tin nh phân ớ ậ
ị ở ạ ế ế ặ ơ ị M c đ nh là m d ng text n u không có xác đ nh là b, n u rõ ràng h n thì thêm ể ể ỉ ị ị ch đ nh t đ xác đ nh là ki u text. ả ề ộ ỏ ậ ươ ủ ể Hàm fopen tr v m t con tr t p tin. Ch ng trình c a ta không th thay ị ủ ộ ỗ ế ở ậ ệ ấ ỏ
ổ
đ i giá tr c a con tr này. N u có m t l i xu t hi n trong khi m t p tin thì ả ề ỏ hàm này tr v con tr NULL. ở ộ ậ ụ ể Ví d : M m t t p tin tên TEST.txt đ ghi. ớ ậ ệ ể ậ FILE *f;
f = fopen("c:\\TEST.txt", "w");
if (f!=NULL)
{
/* Các câu l nh đ thao tác v i t p tin*/
/* Đóng t p tin*/
}
ể ỏ ớ ị ị ượ ệ ự Ki m tra con tr f v i giá tr NULL cho phép xác đ nh đ ệ
c l nh th c hi n thành công hay không? ở ậ ế ể ườ ợ ậ ồ ạ ồ ẽ ị ậ N u m t p tin đ ghi, tr ng h p t p tin đã t n t i r i thì t p tin s b xóa và ộ ậ ớ ượ ạ ố ữ ệ ả ử ụ ế ố m t t p tin m i đ c t o ra. N u ta mu n ghi n i d li u, ta ph i s d ng ch ế ế ộ ọ ả ồ ạ ồ ở ớ ế ậ ộ
đ “a”. Khi m v i ch đ đ c, t p tin ph i t n t i r i, n u không m t l ộ ỗ ẽ i s ệ ấ xu t hi n. 3. Đóng tập tin ượ ể ậ ượ ở ở Hàm fclose() đ c dùng đ đóng t p tin đ c m b i hàm fopen(). Hàm này ạ ệ ậ ạ ậ ữ ệ
ẽ
s ghi d li u còn l i trong vùng đ m vào t p tin và đóng l i t p tin. Cú pháp: int fclose(FILE *f) ỏ ậ ượ ị ả ề ủ ở ở Trong đó f là con tr t p tin đ c m b i hàm fopen(). Giá tr tr v c a hàm ả ề ệ ế ậ ằ ấ ệ
là 0 báo r ng vi c đóng t p tin thành công. Hàm tr v EOF n u có xu t hi n l i. ỗ ể ử ụ ể ấ ả ậ ạ Ngoài ra, ta còn có th s d ng hàm fcloseall() đ đóng t t c các t p tin l i. Cú pháp: int fcloseall() ả ả ề ủ ế ậ ố ượ ạ ế K t qu tr ổ
v c a hàm là t ng s các t p tin đ c đóng l i. N u không ả ả ề ế thành công, k t qu tr v là EOF. 4. Kiểm tra đến cuối tập tin hay chưa?
Cú pháp: int feof(FILE *f) ể ạ ớ ố ậ ư ả ề Ý nghĩa: Ki m tra xem đã ch m t i cu i t p tin hay ch a và tr ế
v EOF n u ố ậ ượ ớ ượ ạ ả ề cu i t p tin đ ạ
c ch m t i, ng i tr v 0. c l 5. Di chuyển con trỏ tập tin về đầu tập tin - Hàm rewind() ề ầ ậ ử ụ ể Chuy n v đ u t p tin, s d ng hàm rewind(). Cú pháp: void rewind(FILE *f); ỏ ậ + f: con tr t p tin đang thao tác. ấ ỳ ử ụ ể ế ị Chuy n đ n v trí b t k s d ng hàm fseek(). Cú pháp: int fseek(FILE *f, long offset, int whence); ỏ ậ + f: con tr t p tin đang thao tác. ỏ ậ ể ầ ố ị + offset: s byte c n d ch chuy n con tr t p tin. ắ ầ ể ể ả ị ị + whence: v trí b t đ u đ tính kho ng cách d ch chuy n cho offset: ị SEEK_SET ầ ậ
V trí đ u t p tin 0 ệ ạ ủ ị SEEK_CUR V trí hi n t ỏ ậ
i c a con tr t p 1 ố ậ SEEK_END tin
ị
V trí cu i t p tin 2 ả ả ề ủ ế ệ ể ế ế + K t qu tr v c a hàm là 0 n u vi c di chuy n thành công. N u không ỗ ượ ị
thành công, 1 giá tr khác 0 (đó là 1 mã l i) đ ả ề
c tr v . ị ủ ấ ỏ ị L y v tr c a con tr file hàm ftell(); Cú pháp: long ftell(FILE *stream); ế ệ ạ
+ stream: bi n đ i di n cho file ả ề ị ớ ầ ủ ỏ + tr v v trí c a con tr file so v i đ u file III. Truy cập tập tin văn bản 1. Ghi dữ liệu lên tập tin văn bản 1.1 Hàm fputc() ượ ể ộ ự ộ ậ ả Hàm này đ c dùng đ ghi m t ký t lên m t t p tin văn b n đang đ ượ
c ở ể ệ m đ làm vi c. Cú pháp: int fputc(int c, FILE *f) ủ ố ộ ự ượ ứ
Trong đó, tham s c ch a mã Ascii c a m t ký t nào đó. Mã này đ c ghi ế ớ ả ề ặ ỗ ế ậ ỏ lên t p tin liên k t v i con tr f. Hàm này tr v EOF n u g p l i. 1.2 Hàm fputs() ể ộ ỗ ự ứ ậ Hàm này dùng đ ghi m t chu i ký t ệ
ch a trong vùng đ m lên t p tin văn b n. ả Cú pháp: int fputs(const char *buffer, FILE *f) ỉ ế ủ ể ầ ỗ ỏ ị Trong đó, buffer là con tr có ki u char ch đ n v trí đ u tiên c a chu i ký ỗ ỗ ả ề ứ ế ị t ự ượ
đ c ghi vào. Hàm này tr v giá tr 0 n u buffer ch a chu i r ng và tr v ả ề ặ ỗ ế
EOF n u g p l i. 1.3 Hàm fprintf() ữ ệ ể ậ ạ ả ị Hàm này dùng đ ghi d li u có đ nh d ng lên t p tin văn b n. Cú pháp: fprintf(FILE *f, const char *format, varexpr) ủ ạ ạ ỗ ớ ố ị ị Trong đó: format: chu i đ nh d ng (gi ng v i các đ nh d ng c a hàm ứ ể ể ấ ỗ ẩ
ứ
printf()), varexpr: danh sách các bi u th c, m i bi u th c cách nhau d u ph y (,). ạ ị Đ nh d ng Ý nghĩa ố ữ ố ậ ố
Ghi s nguyên
ố ự ữ ố ậ ố %d
%[.s ch s th p phân] f Ghi s th c có ỗ ặ ặ ọ %o
%x
%c
%s
%e ho c %E ho c %g ố
ắ
t c làm tròn s .
ệ
ố
Ghi s nguyên h bát phân
ố
ệ ậ ụ
Ghi s nguyên h th p l c phân
ự
ộ
Ghi m t ký t
ự
Ghi chu i ký t
ố ự ạ
Ghi s th c d ng khoa h c (nhân 10 mũ x) ặ ho c %G ế ươ ỗ ự ậ ụ
Ví d : Vi t ch ng trình ghi chu i ký t ả
lên t p tin văn b n D:\\Baihat.txt #include 2. Đọc dữ liệu từ tập tin văn bản 2.1 Hàm fgetc() ữ ệ ừ ậ ể ọ ả ượ Hàm này dùng đ đ c d li u t t p tin văn b n đang đ ở ể
c m đ làm vi c. ệ Cú pháp: int fgetc(FILE *f) ả ề ủ ộ ự ể ả ậ Hàm này tr v mã Ascii c a m t ký t nào đó (k c EOF) trong t p tin ế ớ ỏ liên k t v i con tr f. 2.2 Hàm fgets() Cú pháp: char *fgets(char *buffer, int n, FILE *f) ượ ể ọ ỗ ộ ự ừ ậ ả Hàm này đ c dùng đ đ c m t chu i ký t t p tin văn b n đang đ t ượ
c ọ ủ ế ớ ế ở ự ặ ặ ỏ
m ra và liên k t v i con tr f cho đ n khi đ c đ n ký t ho c g p ký t ự ố
xu ng ự ượ ỗ ế ư ặ ả ự ế dòng ‘\n’ (ký t này cũng đ c đ a vào chu i k t qu ) hay g p ký t k t thúc ự ượ ư ỗ ế ả EOF (ký t này không đ c đ a vào chu i k t qu ). Trong đó: ớ ủ ớ ỉ ế ệ ể ỏ ứ
buffer (vùng đ m): con tr có ki u char ch đ n cùng nh đ l n ch a các ký t ự ậ ượ
nh n đ c. ấ ủ ỉ ộ ỗ ớ ị n: giá tr nguyên ch đ dài l n nh t c a chu i ký t ự ậ ượ
nh n đ c. ế ớ ộ ậ ỏ f: con tr liên k t v i m t t p tin nào đó. ự ự ộ ượ ỗ ế ả ư ố Ký t NULL (‘\0’) t đ ng đ c thêm vào cu i chu i k t qu l u trong vùng đêm. ả ề ị ỉ ầ ặ ỗ ủ ệ Hàm tr v đ a ch đ u tiên c a vùng đ m khi không g p l ư
i và ch a ự ế ả ề ị ặ
g p ký t k t thúc EOF. Ng ượ ạ
c l i, hàm tr v giá tr NULL. 2.3 Hàm fscanf() ữ ệ ừ ậ ể ọ ả Hàm này dùng đ đ c d li u t ế
t p tin văn b n vào danh sách các bi n ạ ị theo đ nh d ng. Cú pháp: fscanf(FILE *f, const char *format, varlist) ỗ ị ạ ố Trong đó: format: chu i đ nh d ng (gi ng hàm scanf()); varlist: danh sách ế ế ấ ẩ ỗ các bi n m i bi n cách nhau d u ph y (,). ế ươ ậ ở ậ ụ
Ví d : Vi t ch ng trình chép t p tin D:\Baihat.txt trên sang t p tin D:\Baica.txt. #include FILE *f1,*f2;
clrscr();
f1=fopen("D:\\Baihat.txt","rt");
f2=fopen("D:\\Baica.txt","wt");
if (f1!=NULL && f2!=NULL)
{ int ch=fgetc(f1);
while (! feof(f1))
{ fputc(ch,f2);
ch=fgetc(f1); }
fcloseall(); }
getch();
return 0; } ể ậ ị ậ
ư ầ ậ ừ ươ ủ ầ ấ ậ
ng trình, thay vì nh n t 3. Ví dụ
ớ
ọ
Đ c ma tr n tính ma tr n, ghi ma tr n chuy n v vào file m i. Xem xét file văn
ả
b n nh đ u vào, đ u ra c a ch
bàn phím và xu t ra
màn hình. #include int main()
{ char *infile="vao.txt", *outfile="ra.txt";
int i, j;
FILE *f1,*f2; f1=fopen(infile,"rt");
if(f1==NULL)
{ printf("Loi mo file %s",infile);
getch();
return 1; }
f2=fopen(outfile,"wt");
if(f2==NULL)
{ printf("Loi mo file %s",outfile);
getch();
fclose(f1);
return 2; }
fscanf(f1,"%d%d",&m,&n);
for(i=0;i for(j=0;j fscanf(f1,"%d",&a[i][j]); } }
fprintf(f2,"%d %d\n",n,m);
for(i=0;i for(j=0;j fprintf(f2,"%4d",a[j][i]); }
fprintf(f2,"\n"); }
fclose(f1);
fclose(f2);
printf("Ket thuc tinh chuyen vi"); getch();
return 0; } IV. Truy cập tập tin nhị phân 1. Ghi dữ liệu lên tập tin nhị phân
Cú pháp: size_t fwrite(const void *ptr, size_t size, size_t n, FILE *f) Trong đó: ỏ ỉ ế ậ ầ ớ ứ
ptr: con tr ch đ n vùng nh ch a thông tin c n ghi lên t p tin. ầ ử ẽ ậ ố
n: s ph n t s ghi lên t p tin. ướ ủ size: kích th ỗ
c c a m i ph n t ầ ử
. ượ ỏ ậ
f: con tr t p tin đã đ ở
c m . ị ả ề ủ ầ ử ượ ố ậ ị Giá tr tr v c a hàm này là s ph n t đ ằ
c ghi lên t p tin. Giá tr này b ng ệ ỗ ừ ấ n tr khi xu t hi n l i. 2. Đọc dữ liệu từ tập tin nhị phân Cú pháp: size_t fread(const void *ptr, size_t size, size_t n, FILE *f) Trong đó: ậ ữ ệ ừ ậ ỏ ỉ ế ớ ẽ ptr: con tr ch đ n vùng nh s nh n d li u t t p tin. ầ ử ượ ọ ừ ậ ố
n: s ph n t c đ c t t p tin. đ ướ ủ size: kích th ỗ
c c a m i ph n t ầ ử
. ượ ỏ ậ
f: con tr t p tin đã đ ở
c m . ị ả ề ủ ầ ử ố ị Giá tr tr v c a hàm này là s ph n t ọ
đã đ c đ ượ ừ ậ
c t t p tin. Giá tr này ố ậ ỏ ơ ế ế ạ ặ ỗ ệ ấ ằ
b ng n hay nh h n n n u đã ch m đ n cu i t p tin ho c có l i xu t hi n.. 3. Ví dụ ế ươ ị ố ậ ụ
Ví d 1: Vi t ch ự
ng trình ghi lên t p tin CacSo.Dat 3 giá tr s (th c, ố ừ ậ ừ ể ọ ị nguyên, nguyên dài). Sau đó đ c các s t t p tin v a ghi và hi n th lên màn hình. #include {
FILE *f;
f=fopen("number.txt","wb");
if (f!=NULL)
{ double d=3.14;
int i=101;
long l=54321;
fwrite(&d,sizeof(double),1,f);
fwrite(&i,sizeof(int),1,f);
fwrite(&l,sizeof(long),1,f);
/* Doc tu tap tin*/
rewind(f);
fread(&d,sizeof(double),1,f);
fread(&i,sizeof(int),1,f);
fread(&l,sizeof(long),1,f);
printf("Cac ket qua la: %f %d %ld",d,i,l);
fclose(f); }
else
{ printf("Khong mo duoc file"); ụ ầ ả ấ ỗ ọ }
getch();
return 0;
}
Ví d 2: M i sinh viên c n qu n lý ít nh t 2 thông tin: mã sinh viên và h tên. ế ươ ự ậ ọ Vi t ch ứ
ng trình cho phép l a ch n các ch c năng: nh p danh sách sinh viên t ừ ọ ữ ệ ừ ậ ậ ồ bàn phím r i ghi lên t p tin SinhVien.dat, đ c d li u t ồ
t p tin SinhVien.dat r i ủ ể ộ ọ ị ự
ế
hi n th danh sách lên màn hình, tìm ki m h tên c a m t sinh viên nào đó d a ậ ừ vào mã sinh viên nh p t bàn phím. ấ ằ ầ ử ủ ậ ộ ấ ậ ỗ Ta nh n th y r ng m i ph n t c a t p tin SinhVien.Dat là m t c u trúc có 2 ườ ử ụ ấ ầ ọ tr ng: mã và h tên. Do đó, ta c n khai báo c u trúc này và s d ng các hàm ậ ớ ướ ầ ử ủ ậ ỗ ị
ọ
đ c/ghi t p tin nh phân v i kích th c m i ph n t c a t p tin là chính kích ướ ấ th c c u trúc đó. ườ ữ ữ ệ ơ ư ư ể ợ ị Trong tr ng h p này có th coi file nh phân nh là n i l u tr d li u lâu ữ ệ ơ ư ữ ử ư ể ộ ớ
dài, cũng có th coi nh là n i l u tr x lý d li u thay vì dùng b nh . #include char Ma[10];
char HoTen[40]; } SinhVien;
///
void WriteFile(char *FileName)
{ FILE *f;
int n,i;
SinhVien sv;
f=fopen(FileName,"ab");
printf("Nhap bao nhieu sinh vien? ");
scanf("%d",&n);
for(i=1;i<=n;i++)
{ printf("Sinh vien thu %i\n",i);
fflush(stdin);
printf(" MSSV: ");gets(sv.Ma);
printf(" Ho ten: ");gets(sv.HoTen);
fwrite(&sv,sizeof(sv),1,f); }
fclose(f);
printf("Bam phim bat ky de tiep tuc");
getch(); }
void ReadFile(char *FileName) { FILE *f;
SinhVien sv;
f=fopen(FileName,"rb");
printf(" MSSV | Ho va ten\n");
fread(&sv,sizeof(sv),1,f);
while (!feof(f))
{ printf(" %s | %s\n",sv.Ma,sv.HoTen);
fread(&sv,sizeof(sv),1,f); }
fclose(f);
printf("Bam phim bat ky de tiep tuc!!!");
getch(); }
void Search(char *FileName)
{ char MSSV[10];
FILE *f;
int Found=0;
SinhVien sv;
fflush(stdin);
printf("Ma so sinh vien can tim: ");gets(MSSV);
f=fopen(FileName,"rb");
while (!feof(f) && Found==0)
{ fread(&sv,sizeof(sv),1,f);
if (strcmp(sv.Ma,MSSV)==0) Found=1; }
fclose(f);
if (Found == 1)
{ printf("Tim thay SV co ma %s. Ho ten la: %s",sv.Ma,sv.HoTen); }
else { printf("Tim khong thay sinh vien co ma %s",MSSV); }
printf("\nBam phim bat ky de tiep tuc!!!");
getch(); }
int main()
{
int c;
for (;;)
{
printf("1. Nhap DSSV\n");
printf("2. In DSSV\n");
printf("3. Tim kiem\n");
printf("4. Thoat\n");
printf("Ban chon 1, 2, 3, 4: ");
scanf("%d",&c);
fflush(stdin); if(c==1)
{ WriteFile("SinhVien.dat"); }
else if (c==2)
{ ReadFile("SinhVien.dat"); }
else if (c==3)
{ Search("SinhVien.Dat"); }
else break;
}
return 0;
} ư ệ ộ ố ị Ngoài ra th vi n stdio.h còn đ nh nghĩa m t s hàm khác cho phép thao tác ể ả ầ ợ ớ ậ
v i t p tin, sinh viên có th tham kh o trong ph n tr giúp. Kết quả: Chương trình QLSV chạy được theo các yêu cầu đặt ra.
3
4
5
6
7
8
9
10
11
12
13
14
15
1
2
3
4
16
17
18
19
theo quy20
21
22
23
24
25
26
27
28
29
Tài liệu liên quan
Tài liêu mới