Chương II trong KTLT (6LT – 2BT) Last update 8-2010 SE-SoICT KTLT-2.1 Chương II 1. ng Last update 8-2010 SE-SoICT KTLT-2. Last update 8-2010 SE-SoICT KTLT-2. Last update 8-2010 SE-SoICT KTLT-2.4 p) • m trong C int GT(int n) { if ( n==0) return 1; else return n * GT(n-1); } • c trong C void nhapmang(Mang V, int n) {int i; for (i=0;i <n;i++) { printf("\n V[ %d ]=",i); scanf("%d",&V[i]); } } Last update 8-2010 SE-SoICT KTLT-2.
Last update 8-2010 SE-SoICT KTLT-2. c Printf(“\3!= %d”,GT(3)); Last update 8-2010 SE-SoICT KTLT-2. • c!!! Last update 8-2010 SE-SoICT KTLT-2. •=> C c!!! • TD: • n theo tên (macro) • n sau).
Last update 8-2010 SE-SoICT KTLT-2.h> swap (int a, int b); { int temp = a; a = b; b= temp); in ra } main() c=5 d=7 { int c = 5; int d = 7; clrscr(); swap (c,d); printf("\n c= %d d=%d",c,d); getch(); } Last update 8-2010 SE-SoICT KTLT-2.h> swap (int *a, int *b); { int temp = *a; *a = *b; *b= temp; in ra } main() c=7 d=5 { int c = 5; int d = 7; clrscr(); swap (&c,&d); printf("\n c= %d d=%d",c,d); getch(); } Last update 8-2010 SE-SoICT KTLT-2.11 Tổ chức CT con • Để tiện sử dụng CT con được tổ chức theo nhiều hình thức khác nhau: 1. Trong cùng 1 chương trình với CT chính 2. Ghép thành đơn vị CT 3. Ghép thành mô đun (đơn thể chương trình) • Cách tổ chức thứ 2 và 3 tiện dụng hơn vì tính tái sử dụng.
Các CT con của ND có thể chuyển vào Thư Viện chương trình của NNLT đó (các NNLT đều có công cụ hỗ trợ việc này. • TD: minh họa qua C/ Pascal. Last update 8-2010 SE-SoICT KTLT-2.12 Chương II 1. ng Last update 8-2010 SE-SoICT KTLT-2.13 c (global) • Khi 1 CT được gọi nó được nạp vào bộ nhớ và thường trú trong bộ nhớ đến khi kết thúc thực hiện.
Đó chính là vòng đời của CT => Do vậy các đại lượng định nghĩa trong CT đó cũng kết thúc vòng đời của mình. => Nảy sinh khái niệm biến cục bộ và biến toàn cục. • Biến cục bộ (local variables): Các biến được định nghĩa trong 1 CT và chỉ được sử dụng trong CT con đó. Nó có cùng vòng đời với CT sinh ra nó.
Khái niệm cục bộ cũng là tương đối và phụ thuộc vào cách tổ chức CT. Nó là cục bộ của CT con đó song là toàn cục với CT con của nó. Last update 8-2010 SE-SoICT KTLT-2.14 c (tiếp) • Biến toàn cục (global variables): Các biến được định nghĩa trong 1 CT và được sử dụng trong CT con đó và các CT con của nó. => Đ/n ở 1 nơi và sử dụng ở nơi khác.
• Một loại nữa là static: Nó là cục bộ của 1. • Chú ý cách dùng Last update 8-2010 SE-SoICT KTLT-2.15 Thí dụ int V[…]; void inmang(int n) { a CT con inmang int i; for (i=0;i <n;i++) printf(" %4d",V[i]); } main () a main {int i,j,n, tam; clrscr(); printf(" So Phan tu cua mang:\n"); scanf("%d",&n); nhapmang(n); printf("\n Day so vua nhap:"); inmang(n); } Last update 8-2010 SE-SoICT i CT con!!! KTLT-2.16 Chương II 1. ng Last update 8-2010 SE-SoICT KTLT-2. • i • c Union Last update 8-2010 SE-SoICT KTLT-2.18 struct WORDREGS { unsigned int ax, bx, cx, dx, si, di, cflag, flags; }; struct BYTEREGS { unsigned char al, ah, bl, bh, cl, ch, dl, dh; }; union REGS { struct WORDREGS x; struct BYTEREGS h; }; Last update 8-2010 SE-SoICT KTLT-2.19 p) Typedef union { struct { long abscisse ; long ordonne; }cart; struct { float rho; float theta; }pol; p2 m: P1.theta Last update 8-2010 SE-SoICT KTLT-2.
Last update 8-2010 SE-SoICT KTLT-2.21 phân void main() { int i , j, n; mang A, B; FILE *fp; char filename[]="Mang.Txt"; clrscr(); if ((fp=fopen(filename,"w+"))==NULL) printf("\n Khong mo duoc tep!"); else { do { printf("\n so phan tu (1 <n <10)"); scanf("%d",&n); } while ((n < 1) ||(n>10)); printf("\n nhap cac phan tu:"); for (i =0;i<n;i++) for (j=0;j<n;j++) {printf("\n A[%d,%d]=",i,j); scanf("%d",&A[i][j]); } fwrite(&A,sizeof(int), MAX * MAX,fp); Last update 8-2010 SE-SoICT KTLT-2.22 phân if ((fp=fopen(filename,"r+"))==NULL) printf("\n Khong mo duoc tep!"); else { fread(&B,sizeof(int), MAX * MAX,fp); fclose(fp); }// ket thuc else printf("\n Mang doc ra tu tep:"); for (i = 0;i<n;i++) { for (j = 0;j<n;j++) printf("\ %d ",B[i][j]); printf("\n"); } Last update 8-2010 SE-SoICT KTLT-2.23 n void main() { char c; FILE *fv, *fr; char *filename="D_ghitep.cpp"; clrscr(); if ((fv=fopen(filename,"r+"))==NULL) printf("\n Khong mo duoc tep!"); else { filename= "D_ghitep.Txt"; if ((fr = fopen(filename,"w+")) == NULL); do { c = fgetc(fv); fputc(c,fr); } while (c != EOF); fclose(fv); fclose(fr); } Last update 8-2010 SE-SoICT KTLT-2.24 Chương II 1. ng Last update 8-2010 SE-SoICT KTLT-2. Last update 8-2010 SE-SoICT KTLT-2.26 nh • như khai báo mảng, biến và các đối tượng 1 cách tường minh. • nhiều đối tượng có kích thước thay đổi linh hoạt.
Last update 8-2010 SE-SoICT KTLT-2. • riêng: – Trong C ta dùng các hàm malloc, calloc, realloc và free để xin cấp phát, tái cấp phát và giải phóng bộ nhớ. Trong C++ là new và delete. sung trong C/C++ Last update 8-2010 SE-SoICT KTLT-2.28 delete • Để xin cấp phát bộ nhớ ta dùng : <biên trỏ> = new <kiểu dữ liệu>; hoặc <biến trỏ> = new <kiểu dữ liệu>[số ftử]; dòng trên xin cấp phát một vùng nhớ cho một biến đơn, còn dòng dưới : cho một mảng các phần tử có cùng kiểu với kiểu dữ liệu.
• Bộ nhớ động được quản lý bởi hệ điều hành, và với môi trường đa nhiệm (multitask interface) thì bộ nhớ này sẽ được chia sẻ giữa hàng loạt các ứng dụng, vì vậy có thể không đủ bộ nhớ. Khi đó toán tử new sẽ trả về con trỏ NULL. • ví dụ : int *pds; pds = new int [200]; if (pds == NULL) { // thông báo lỗi và xử lý Last update 8-2010 SE-SoICT KTLT-2.29 Giải phóng bộ nhớ • delete ptr; // xóa 1 biến đơn • delete [] ptr; // xóa 1 biến mảng • ví dụ : #include <iotream> int main() { int i,n; long total=100,x,*l; cout << “Vao so ptu “; cin >> n; l = new long [n]; if (l==NULL) exit(1); for (i=0;i<n;i++){ cout <<“\n Vao so thu “<< i+1 <<“ :”; cin >> l[i] } Cout << “Danh sach cac so : \n” for (i=0;i<n;i++) cout << l[i] << “,”; delete []l; return 0; } Last update 8-2010 SE-SoICT KTLT-2. Last update 8-2010 SE-SoICT KTLT-2.
• c Last update 8-2010 SE-SoICT KTLT-2.32 c nâng cao trong C/ C++ Last update 8-2010 SE-SoICT KTLT-2. Mảng • Là một dãy hữu hạn các phần tử liên tiếp có cùng kiểu và tên • Có thể là 1 hay nhiều chiều, C không giới hạn số chiều của mảng • Khai báo theo cú pháp sau : DataType ArrayName [size]; hooặc DataType ArrayN [Size1][Size2].; Last update 8-2010 SE-SoICT KTLT-2.34 • Khởi tạo giá trị cho mảng theo 2 cách: – Khi khai báo : float y[5]={3.6} int m[6][2] = {{1,1},{1,2},{2,1},{2,2},{3,1},{3,2}}; char s1[6] ={„H‟,‟a‟,‟n‟,‟o‟,‟i‟,‟\0‟}; hoặc char s1[6] = “Hanoi”; char s1[] =“Dai hoc Bach Khoa Hanoi”; L=24 int m[][] ={{1,2,3},{4,5,6}}; – Khai báo rồi gán giá trị cho từng phần tử của mảng. Ví dụ : int m[4]; m[0] = 1; m[1] = 2; m[2] = 3; m[3] = 4; Last update 8-2010 SE-SoICT KTLT-2. Con trỏ • Khái niệm : Giá trị các biến được lưu trữ trong bộ nhớ MT, có thể truy cập tới các giá trị đó qua tên biến, đồng thời cũng có thể qua địa chỉ của chúng trong bộ nhớ (CTDL>).
• Con trỏ thực chất là 1 biến mà nội dung của nó là địa chỉ của 1 đối tượng khác (biến, hàm, nhưng không phải 1 hằng số). • Có nhiều kiểu biến với các kích thước khác nhau, nên có nhiều kiểu con trỏ. Con trỏ int để trỏ tới biến hay hàm kiểu int,… • Việc sử dụng con trỏ cho phép ta truy nhập tới 1 đối tượng gián tiếp qua địa chỉ của nó. • Trong C, con trỏ là một công cụ rất mạnh, linh hoạt.
Last update 8-2010 SE-SoICT KTLT-2.36 • Khai báo con trỏ : • Cú pháp : dataType * PointerName; Chỉ rằng đây là con trỏ trỏ về kiểu dataType. • Sau khi khai báo, ta được con trỏ NULL (chưa trỏ tới 1 đối tượng nào). • Để sử dụng con trỏ, ta dùng toán tử lấy địa chỉ & PointerName = & VarName Ví dụ : int a; int *p; a=10; p= &a; => *p = 10 • Để lấy nội dung biến do con trỏ trỏ tới, ta dùng toán tử lấy nội dung *: Last update 8-2010 * PointerName SE-SoICT KTLT-2.37 Ví dụ : Đ/c n int i,j, *p; 100 i i= 5; p= & i; 102 j j= *p; *p= j+2; 104 p 100 5 i 100 5 i Gán i=5 gán p = & i 102 j 102 j 104 p 104 100 p 100 5 i 100 7 i gán j = *p *p = j+2 102 5 j 102 5 j 104 100 p Last update 8-2010 SE-SoICT 104 100 KTLT-2.38 p Chú ý • Một con trỏ chỉ có thể trỏ tới 1 đối tượng cùng kiểu. • Toán tử 1 ngôi * và & có độ ưu tiên cao hơn các toán tử số học.
• Ta có thể viết *p mọi nơi có đối tượng mà nó trỏ tới xuất hiện. int x = 5, *p; p = &x; => x=x+10; ~ *p = *p+10; • Ta cũng có thể gán nội dung 2 con trỏ cho nhau : khi đó cả hai con trỏ cùng trỏ tới 1 đối tượng. int x=10, *p, *q; p = &x; q = p; => p và q cùng trỏ tới x Last update 8-2010 SE-SoICT KTLT-2.39 Các phép toán trên con trỏ • Một biến trỏ có thể cộng hoặc trừ với 1 số nguyên n để cho kết quả là 1 con trỏ cùng kiểu, là địa chỉ mới trỏ tới 1 đối tượng khác nằm cách đối tượng đang bị trỏ n phần tử • Phép trừ giữa 2 con trỏ cho ta khoảng cách (số phần tử ) giữa 2 con trỏ • Không có phép cộng, nhân, chia 2 con trỏ • Có thể dùng các phép gán, so sánh các con trỏ, nhưng cần chú ý đến sự tương thích về kiểu. Ví dụ : char *pchar; short *pshort; long *plong; sau khi xác lập địa chỉ cho các con trỏ, nếu : pchar ++; pshort ++; plong ++; và các địa chỉ ban đầu tương ứng của 3 con trỏ là 100, 200 và 300, thì kết quả ta có các giá trị tương ứng là : 101, 202 và 304 tương ứng.
Last update 8-2010 SE-SoICT KTLT-2.40 • Nếu viết tiếp : plong += 5; => plong = 324 (304 + 5 x 4) pchar -=10; => pchar = 91 pshort +=5; => pshort = 212 • Chú ý : ++ và – có độ ưu tiên cao hơn * => *p++ ~ *(p++) tức là tăng địa chỉ mà nó trỏ tới chứ không phải tăng giá trị mà nó chứa. • *p++ = *q++ sẽ tương đương : *p = *q; Vì cả 2 phép tăng đều p=p+1; diễn ra sau khiphép gán được thực hiện q=q+1; => Cần dùng dấu () để tránh nhầm lẫn Last update 8-2010 SE-SoICT KTLT-2.41 Con trỏ void* • Là con trỏ không định kiểu (void *). Nó có thể trỏ tới bất kì một loại biến nào.