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\n",argv[0]); exit(1); }//ki m tra n u nh p ch a đ 3 tham s ố  argv[1] và argv[2] là tên c a file ngu n và file ủ ồ ậ ủ

đí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);

}

Solution

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);

Solution

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; }

Truy nh pậ file tuỳ ý

 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ạ

Truy nh pậ file tuỳ ý

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);

Exercise 2.6 - c pấ phát bộ nhớ đ ngộ

 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.

Solution

#include #include enum {SUCCESS, FAIL, MAX_ELEMENT = 20}; // c uấ trúc phone book typedef struct phoneaddress {

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");

Solution

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);

Solution for (i=0; i<2; i++){

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; }

Exercise 2.7

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.

Đ nhị

d ngạ vào ra

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);

Homework

 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ộ .

Solution for homework

#include #include #include //author: Cao Tuan Dung //for HEDSPI project enum {SUCCESS, FAIL}; int main(void) {

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;

Solution for homework while(i

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; }