Topics
ngượ .
Các c uấ trúc, c pấ phát đ ngộ Các phép toán File trên bộ nhớ ngưở t t Bài t pậ
C pấ phát đ ngộ
M tộ m ngả các bi nế đã đ
kích th (t cượ nấ đ nhị ngượ bi nế đã xác đ nhị cướ , iạ th iờ
Kích thước này sẽ không thể thay đ iổ sau khi
). dùng để lưu trữ 1 l đi mể biên d chị
. biên d chị Tuy nhiên chúng ta th ngườ không bi tế tr cướ
Vì v yậ nên có thể sử d ngụ c pấ phát bộ nhớ đ ngộ
đ cượ số l ngượ không gian c nầ thi tế cho m ngả .
cượ đi mể trên c aủ m ngả , tránh
để kh cắ ph cụ nh lãng phí không gian nhớ.
Hàm malloc
void * malloc(unsigned int nbytes);
Hàm malloc đ
cượ sử d ngụ để c pấ phát
đ ngộ nbytes trong bộ nhớ.
malloc trả về con trỏ t
iớ vùng nhớ
cượ c pấ phát n uế thành công, trả về
đ con trỏ NULL n uế th tấ b iạ .
Nên ki mể tra xem có c pấ phát thành
công hay không.
Ph iả #include
cượ m ngả đ ngộ
Ví dụ - Đ oả ng int main(void) {
cướ thích h p */ợ
int i, n, *p; printf(“B nạ mu nố nh pậ bao nhiêu số ?\n"); scanf("%d", &n); /* C pấ phát 1 m ngả int v iớ kích th p = (int *)malloc(n * sizeof(int)); if (p == NULL) {
printf("Memory allocation failed!\n"); return 1;
}
Ví dụ - Đ oả ng
cượ m ngả đ ngộ
int main(void) {
. . . /* Nh nậ các số từ bàn phím */ printf("Please enter numbers now:\n"); for (i = 0; i < n; i++)
cượ l
i*/ạ
scanf("%d", &p[i]); /* Đưa ra theo thứ tự ng printf("The numbers in reverse order are \n"); for (i = n - 1; i >= 0; --i) printf("%d ",p[i]);
i phóng b
ộ nh */ớ
printf("\n"); /* Gi ả free(p); return 0;
}
T iạ sao ph iả ép ki uể
p = (int *)malloc(n*sizeof(int));
Vi cệ ép ki uể : Là c nầ thi
tế vì hàm malloc trả về ki uể void*:
void * malloc(unsigned int nbytes);
Ki uể void* chỉ 1 ki uể con trỏ chung, có thể
ép t
iớ b tấ kì ki uể con trỏ nào.
Gi
iả phóng bộ nhớ đã đ
cượ c pấ phát
void free(void *ptr);
Ta sử d ngụ hàm free(p) để gi
iả phóng
cượ c pấ phát đ
cượ chỉ
bộ nhớ đã đ đ n bế
iở con trỏ p.
N uế p không trỏ đ nế 1 vùng nhớ đã cượ c pấ phát b iở malloc, sẽ x yả ra
đ lỗi thi hành.
Luôn luôn ph iả nhớ gi
iả phóng bộ nhớ
n uế không c nầ đ nế chúng n aữ .
Exercise 2.1
ố ủ
xâu s1,s2 (đ
ỏ ỏ ớ c c p phát đ ng).
T oạ hàm my_strcat(): - Đ uầ vào: 2 xâu s1,s2 - Đ uầ ra: tr v con tr tr t ả ề ượ
ấ
i xâu n i c a 2 ộ
- Ví dụ: xâu n iố c aủ “hello_” and “world!” là:
“hello_world!”
• Test hàm c aủ b nạ .
Solution my_strcat()
char *my_strcat(char *str1, char *str2) {
int len1, len2; char *result; len1 = strlen(str1); len2 = strlen(str2); result = (char*)malloc((len1 + len2 + 1) * sizeof(char)); if (result == NULL) {
iạ bộ nhớ!\n");
printf(“c pấ phát th tấ b iạ ! Ki mể tra l return NULL;
} strcpy(result, str1); strcpy(result + len1, str2); return result;
}
Solution main()
int main(void) {
char str1[MAX_LEN + 1], str2[MAX_LEN + 1]; char *cat_str; printf("Please enter two strings\n"); scanf("%100s", str1); scanf("%100s", str2); cat_str = my_strcat(str1, str2); if (cat_str == NULL) {
iỗ trong quá trình c pấ phát bộ nh !n");
ớ
printf(“X yẩ ra l return 1;
} printf("The concatenation of %s and %s is %s\n", str1, str2, cat_str); free(cat_str); return 0;
}
cượ đ nhị
nghĩa b iở
Các c uấ trúc - ki uể đ ng
iườ dùng
iướ cùng 1 tên đơn
iợ để nhóm các thông tin
Là 1 t pậ các bi nế d Là 1 cách thu nậ l có liên quan t
iớ nhau.
đ
Các bi nế trong struct(c u trúc)
ấ
cượ g iọ la ng)
member (thành viên) ho cặ field (tr
ườ
Đ nhỊ
nghĩa 1 c uấ trúc
struct struct-name {
field-type1 field-name1; field-type2 field-name2; field-type3 field-name3; …
};
Ví dụ - số ph cứ
struct complex {
int real;//ph nầ th cự int img;//ph nầ oả
}; struct complex num1,num2,num3;
Typedef
nghĩa
Ta có thể ph iố h pợ typedef v iớ đ nhị c uấ trúc đ đ nh nghĩa 1 ki u m i: ớ
ể
ể ị typedef struct complex {
int real; int img; } complex_t;
complex_t num1, num2;
Exercise 2.2
Cho 2 c uấ trúc sau: typedef struct point //đi mể trong mặt ph ngẳ (2 to đ ) ạ ộ {
double x; double y;
} point_t;
òn
ờ
typedef struct circle //đư ng tr {
point_t center; //tâm double radius; //bán kính
tế 1 hàm trả về giá trị 1 n uế đi mể p n mằ trong đ
ngườ tròn c.
} circle_t; Vi Test hàm b ngằ 1 chương trình.
Solution
int is_in_circle(point_t *p, circle_t *c) {
double x_dist, y_dist; x_dist = p->x - c->center.x; y_dist = p->y - c->center.y; return (x_dist * x_dist + y_dist * y_dist <= c->radius * c->radius);
}
Solution int main(void) {
ể
point_t p; circle_t c; printf(“Nh pậ toạ độ đi m\n"); scanf("%lf%lf", &p.x, &p.y); ngườ tròn \n"); printf(“nh pậ toạ độ tâm đ scanf("%lf%lf", &c.center.x, &c.center.y); printf(“Nh pậ bán kính \n"); scanf("%lf", &c.radius); if (is_in_circle(&p, &c))
printf(“đi mể n mằ trong\n");
else
printf(“đi mể n mằ ngoài\n");
return 0;
}
Con trỏ trong c uấ trúc
N uế 1 tr
ngườ c aủ c uấ trúc là con trỏ, nó ủ
iớ chính b n sao c a ả
có thể là con trỏ trỏ t nó.
Chế độ cho Binary file (file nh fân)
ị
Mô tả chế độ
"rb" Mở 1 file binary đã có để đ cọ
“wb” T oạ 1 file binary để ghi
“ab” Mở 1 file đã có để thêm dữ li uệ vào cu iố
“r+b” Mở 1 file binary đã có để đ cọ ho cặ ghi
"w+b“ ặ ọ
"a+b" ạ ở 1 file đã có để thêm dữ
T oạ 1 file binary để đ c ho c ghi T o m i ho c m ặ ớ li uệ vào cu iố
Qu nả lí file: làm vi cệ v iớ 1 kh iố dữ li uệ
2 hàm vào/ra là fread() và fwrite() có thể dùng để th cự hi nệ các thao tác v iớ kh iố dữ li uệ .
Như các hàm qu nả lí file khác, chúng làm
vi cệ v iớ con trỏ file.
fread()
Nguyên m uẫ : size_t fread(void *ptr, size_t size,size_t n, FILE ữ ệ
ướ ọ
*stream); //đ c n d li u, (kích th là size) t ỏ ở ừ
c m i d li u ỗ ữ ệ file tr b i stream l u vào m ng ptr ả ư iớ m ngả lưu trữ dữ li uệ
cướ m iỗ ph nầ tử m ng.ả
ptr là con trỏ trỏ t • size: kích th • n: số ph nầ tử c nầ đ c.ọ • stream: con trỏ t • Hàm fread() trả về số ph nầ tử th cự tế đ
iớ file đã đ cượ mở để đ cọ
cượ đ cọ .
fwrite()
Nguyên m uẫ :
ượ ướ ỏ ế
iớ m ngả lưu trữ dữ li uệ
cướ m iỗ ph nầ tử m ng.ả
cượ mở để ghi iớ file đã đ
size_t fwrite(const void *ptr, size_t size, size_t n, c m i d FILE *stream); //ghi n d li u, (kích th ỗ ữ ữ ệ c tr đ n b i li u là size) m ng ptr vào file đ ở ả ệ con tr stream ỏ ptr là con trỏ t • size: kích th • n: số ph nầ tử c nầ ghi. • stream: con trỏ t • Hàm fwrite() trả về số ph nầ tử th cự tế đ cượ ghi
vào file.
Hàm feof()
ả ề
ư ớ
ố
ế
i cu i file, tr v s ả ề ố i c a file (k t thúc ế
ớ ủ
int feof(FILE *stream); Tr v 0 n u ch a t ế nguyên # 0 n u đã t file).
Ví dụ - Đ cọ 80 bytes từ 1 file
nghĩa MAX_LEN=80
enum {MAX_LEN = 80};//đ nhị
int num; FILE *fptr2; char filename2[]= "haiku.txt"; char buff[MAX_LEN + 1]; if ((fptr2 = fopen(filename2, "r")) == NULL){ printf("Cannot open %s.\n", filename2); reval = FAIL; exit(1);
cướ ki uể char trong C là 1 byte
} . . . . num = fread(buff, sizeof(char), MAX_LEN, fin);//kích th buff[num * sizeof(char)] = `\0'; printf("%s", buff);
Exercise 2.3
Vi
tế 1 chương trình sử d ngụ các phép toán thao tác trên file theo kh iố , copy n iộ dung từ file lab1.txt sang file lab1a.txt
Sử d ngụ fread(), fwrite(), feof().
Solution
#include
enum {SUCCESS, FAIL, MAX_LEN = 80};
void BlockReadWrite(FILE *fin, FILE *fout);//hàm đ cọ ghi dữ li uệ theo
kh iố main(void) {
FILE *fptr1, *fptr2; char filename1[]= "lab1a.txt"; char filename2[]= "lab1.txt"; int reval = SUCCESS; if ((fptr1 = fopen(filename1, "w")) == NULL){
printf("Cannot open %s.\n", filename1); reval = FAIL;
} else if ((fptr2 = fopen(filename2, "r")) == NULL){ printf("Cannot open %s.\n", filename2); reval = FAIL;
} else {
BlocReadWrite(fptr2, fptr1); fclose(fptr1); fclose(fptr2);
} return reval;
}
Solution
void BlockReadWrite(FILE *fin, FILE *fout) {
int num; char buff[MAX_LEN + 1]; while (!feof(fin)){
num = fread(buff, sizeof(char),MAX_LEN, fin); buff[num * sizeof(char)] = `\0'; printf("%s", buff); fwrite(buff, sizeof(char), num, fout);
}
}
Exercise 2.4
ệ
C iả thi n ch
ương trình trong bài 2.3 b ngằ cách nh nậ vào tên file qua tham số dòng l nhệ .
Ví dụ: n uế tên chương trình c aủ b nạ là “filecpy” , b nạ có thể sử d ngụ nó theo nguyên m uẫ sau (trong Linux): ./filecpy haiku.txt haiku2.txt
G iợ ý Sử d ngụ argc[] và argv[]
ư ế ể
if(argc<3) { printf("%s
đích.
if((fp=fopen(argv[1],"r"))==NULL) { … };
if((fp2=fopen(argv[2],"w"))==NULL) { … };
Exercise 2.5 – vào ra theo c uấ trúc
T oạ 1 s danh b ổ Đ nhị
ạ đi nệ tho iạ
nghĩa 1 c uấ trúc g mồ ”name”, ”telephone
ố ệ ạ ị
Nh pậ kho ngả 10 dữ li uệ vào m ngả . Vi
number”(s đi n tho i), ”e-mail address”(đ a ch ỉ mail). T oạ 1 m ngả ch aứ các ph nầ tử có c uấ trúc iố đa 100 f nầ tử. trên.M ngả ch aứ t
tế chương trình ghi n iộ dung c aủ m ngả vào 1 ỳ theo số f nầ tử d li u ử ụ
ữ ệ iạ
file (s d ng fwrite()) tu có trong m ngả , và đ cọ các dữ li uệ đó trở l m ngả , sử d ngụ hàm fread().
Solution
#include
enum {SUCCESS, FAIL, MAX_ELEMENT =
20};
//c uấ trúc danh bạ typedef struct phoneaddress { char name[20]; char tel[11]; char email[25]; }phoneaddress;
Solution int main(void) {
FILE *fp;
phoneaddress phonearr[MAX_ELEMENT];
phoneaddress one_address, *phonebook =
&one_address;
int i,n, irc; // return code
int reval = SUCCESS;
printf("How many contacts do you want to enter (<20)?");
scanf("%d", &n);
for (i=0; i printf("name:"); scanf("%s",phonearr[i].name);
printf("tel:"); scanf("%s",phonearr[i].tel);
printf("email:"); scanf("%s",phonearr[i].email); } if ((fp = fopen("phonebook.dat","w+b")) == NULL){
printf("Can not open %s.\n", "phonebook.dat");
reval = FAIL;
} // ghi dữ li uệ m ngả vào file ề irc = fwrite(phonearr, sizeof(phoneaddress), n,
fp);
printf(" fwrite trả v = %d\n", irc);
fclose(fp); iạ vào m ngả
//đ cọ dữ li uệ trở l
if ((fp = fopen("phonebook.dat","rb")) == NULL){ printf("Can not open %s.\n", "phonebook.dat");
reval = FAIL; }
irc = fread(phonearr, sizeof(phoneaddress), n, fp);
printf(" fread return code = %d\n", irc);
for (i=0; i printf("%s-",phonearr[i].name);
printf("%s-",phonearr[i].tel);
printf("%s\n",phonearr[i].email);
} fclose(fp);
return reval;
} 2 hàm fseek() và ftell()
fseek():hàm chuy nể con trỏ file t iớ vị trí theo ý - Nguyên m uẫ :
fseek(FILE *stream, long offset, int whence);
- stream: con trỏ tới file đã mở
- offset: chỉ ra số byte tính từ vị trí đã đ mu nố trong file cượ đ nhị - Whence: SEEK_SET, SEEK_CUR, và tr cướ . SEEK_END • SEEK_SET: tính từ đ uầ file
• SEEK_CUR: tính từ vị trí hi nệ t
• SEEK_END: tính từ cu iố file iạ cượ giá trị vị trí hi nệ t iạ . ftell :thu đ
- Nguyên m uẫ : long ftell(FILE *stream);
tế l pậ l iạ vị trí con trỏ file về rewind(): thi
đ uầ file. - Nguyên m u:ẫ void rewind(FILE *stream); Vi c), v ướ
cặ “t ứ cượ
tế 1 chương trình n pạ vào 1 ph nầ dữ li uệ đ
í dụ:”t
d
ừ ữ
d li u th
ứ
ừ ữ ệ
iạ dữ li uệ đó và ghi aử đ iổ l chỉ đ nhị
c aủ address book (bt tr
li u th 3 đ n d li u th 6”, ho
ữ ệ
ế
ứ
ệ
2 đ n d li u th 3”, s
ứ
ữ ệ
ế
iạ vào file.
nó trở l Nhưng b nạ ph iả cấp phát bộ nhớ 1 cách t
ướ c b nh c nầ thi ộ iố c nầ
ừ tế .Ví dụ:kích th
ứ
ữ ệ tế cho “t
à 4.Sử d ngụ ớ
ứ ữ ệ thi
d li u th 3 đ n d li u th 6” l
ế
hàm malloc. #include char name[20];
char tel[11];
char email[25]; }phoneaddress;
int main(void)
{ FILE *fp;
phoneaddress *phonearr;
int i,n, irc; // return code
int reval = SUCCESS;
printf("Read from 2sd data to 3rd data \n"); if ((fp = fopen("phonebook.dat","r+b")) == NULL){
printf("Can not open %s.\n", "phonebook.dat");
reval = FAIL; }
// c pấ phát bộ nhớ
phonearr =(phoneaddress *)malloc(2 * sizeof(phoneaddress));
if (phonearr == NULL)
{ printf("Memory allocation failed!\n");
return FAIL; }
if (fseek(fp,1*sizeof(phoneaddress),SEEK_SET) != 0)
{ printf("Fseek failed!\n");
return FAIL; }
irc = fread(phonearr, sizeof(phoneaddress), 2, fp); printf("%s-",phonearr[i].name);
printf("%s-",phonearr[i].tel);
printf("%s\n",phonearr[i].email); }
// Sửa đ iổ 1 số dữ li uệ
strcpy(phonearr[1].name,"Lan Hoa");
strcpy(phonearr[1].tel,"0923456");
strcpy(phonearr[1].email,"lovelybuffalo@hut.edu.vn");
fseek(fp,1*sizeof(phoneaddress),SEEK_SET);
irc = fwrite(phonearr, sizeof(phoneaddress), 2, fp);
printf(" fwrite return code = %d\n", irc);
fclose(fp); free(phonearr);
return reval;
} Có 1file text class1EF.txt
Vi t ch ng trình thêm vào 1 dòng tr ng ươ ế ố gi aữ các dòng trong file. 2 hàm fprintf() và fscanf(): làm vi cệ gi ngố printf() và scanf(). • int fscanf(FILE *stream, const char *format, …); • int fprintf(FILE *stream, const char *format, …); • • fprintf(fp, "%d %s", 5, "bear");
fscanf(fp, "%d %s", &n, s); Vi tế chương trình đ cọ các số từ 1 đ uầ vào chu nẩ và i. Th êm c l
ượ ạ ứ ự đưa chúng ra file “out.txt” theo th t
vào đó, ph iả đưa ra t ngổ các số ở cu i file out.txt ng
ố
cượ n pạ vào từ đ uầ vào chu nẩ :đ uầ D ngạ c aủ dữ li uệ đ tiên là số l ngượ các số, sau đó là các số. cượ ghi vào file out.txt Ví dụ: input: 4 12 -45 56 3
- 4: số các số theo sau là 4
- 12 -45 56 3: các số c nầ đ
- out.txt : 3 56 -45 12 26 //các số đưa ra theo thứ tự cượ l iạ . Số 26 ở cu iố cùng là t ngổ t tấ cả các số tr cướ ng
nó. ngượ các số thay đ iổ nên ph iả sử d ngụ cấp • Lưu ý: số l
phát đ ngộ . #include FILE *fp;
int *p;
int i,n, value, sum;
int reval = SUCCESS;
printf("Enter a list of numbers with the first is the size of list: \n");
scanf("%d", &n);
p = (int *)malloc(n*sizeof(int)); i=0; sum=0; scanf("%d", &value);
p[i++]=value;
sum+=value; }
if ((fp = fopen("out.txt","w")) == NULL){ printf("Can not open %s.\n", "out.txt");
reval = FAIL; }
for (i=n-1; i>=0;i--){ fprintf(fp,"%d ",p[i]); }
fprintf(fp,"%d ",sum);
fclose(fp);
free(p);
return reval;
}Solution
Solution
Truy nh pậ file tuỳ ý
Truy nh pậ file tuỳ ý
Exercise 2.6 - c pấ phát bộ nhớ đ ngộ
Solution
Solution
Solution
for (i=0; i<2; i++){
Exercise 2.7
Đ nhị
d ngạ vào ra
Homework
Solution for homework
Solution for homework
while(i