Đề tài Hàm, biến toàn cục, biến cục bộ trong C++

MỤC LỤC

Phần I: Mở đầu 1

Phần II: Phần nội dung 2

Chương I: Hàm 2

I. Định nghĩa hàm 2

II. Sử dụng hàm 4

III. Truyền tham số cho hàm 5

IV.Sử dụng hàm trong nhiều chương trình khác 6

V. Danh sách đối của hàm 7

VI.Các hàm trong C++ 8

1. Tham chiếu 8

2. Đối có giá trị mặc định 11

3. Hàm trực tuyến 12

4. Đệ quy 13

Chương II: Biến toàn cục, biến cục bộ 15

I. Biến toàn cục 15

II. Biến cục bộ 16

Chương III: Chương trình có sử dụng định nghĩa hàm,

biến toàn cục, biến cục bộ trong C++ 17

Phần III: Phần kết luận 22

Tài liệu tham khảo 24

 

doc24 trang | Chia sẻ: maiphuongdc | Lượt xem: 4381 | Lượt tải: 1download
Bạn đang xem trước 20 trang tài liệu Đề tài Hàm, biến toàn cục, biến cục bộ trong C++, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
sử dụng phải tạo ra nó. Vì vậy những hàm này mới có tên là hàm do người dùng định nghĩa. Việc tạo ra và sử dụng những hàm tự định nghĩa làm cho chương trình ngắn gọn hơn, sáng sủa hơn và cho phép tiết kiệm công sức của lập trình viên. Có thể coi hàm là một phép toán do người dùng xác định. Nói chung hàm được biểu thị bởi một tên gọi chứ không phải là một toán tử. Các toán hạng của hàm, được gọi là các đối của nó, được xác định trong danh sách đối phân cách nhau bởi dấu phẩy và được bao trong dấu ngoặc tròn. Kết quả của hàm thường được coi là kiểu cho lại của nó. Hàm không cho lại giá trị nào có kiểu cho lại là Void. Các hành động thực tại mà một hàm thực hiện được xác định trong thân hàm. Thân hàm được bao trong ngoặc nhọn( "{ }" ) và đôi khi còn được coi là một khối. Trong C++ có 2 cách định nghĩa hàm: Định nghĩa hàm sau hàm main( ) và định nghĩa hàm trước hàm main(). Tuy nhiên cách định nghĩa hàm trước hàm main( ) ngăn gọn hơn và hay dùng hơn cho nên ở đây ta nghiên cứu kỹ về chúng. Việc định nghĩa một hàm theo mẫu sau: Đầu_đề_hàm { Phần khai báo Thân hàm } *Đầu đề hàm có dạng sau đây: TĐK(từ định kiểu) : int, char; TĐK tên hàm( TĐK1 tham số 1 [, TĐK2 tham_số 2 ]…) TĐK(*) xác định kiểu của hàm, tức là xác định kiểu của giá trị được trả lại thông qua tên hàm. Các tham số có trong ngoặc tròn ( ) đi sau tên hàm được gọi là các tham số hình thức. Toàn bộ các tham số trong ngoặc ( ) gọi là danh sách tham số hình thức. Danh sách này gồm 1 hay nhiều tham số, tham số nọ cách tham số kia dấu phẩy. Danh sách tham số hình thức kết thúc bởi dấu ngoặc, sau đó không có dấu chấm phẩy. *Phần khai báo của hàm: Dùng để khai báo các biến được dùng trong hàm này. Các biến được khai báo trong hàm chỉ có ý nghĩa trong hàm này nên được gọi là các biến cục bộ( địa phương). Việc sử dụng các biến cục bộ trong chương trình khác hoặc chương trình chính là không hợp lệ. Một hàm được tính bất kỳ khi nào toán tử gọi( "( )") được áp dụng vào tên của hàm. Nếu hàm cần có các đối thì các đối này, còn được gọi là các đối thực tại, sẽ được đặt vào bên trong toán tử gọi. Mỗi đối được phân cách bởi một dấu phẩy. Nó còn được gọi là truyền đối cho hàm. *Thân hàm: Giống như phần thân chương trình của một chương trình thông thường. Tuy nhiên sau khi tính xong giá trị hàm thì trong thân hàm thường có câu lệnh return để trả lại giá trị vừa tính được trong thân hàm cho tên hàm. Nó có dạng: Return Biểu thức; hoặc Return( biểu thức). Câu lệnh này có tác dụng trả cho tên hàm giá trị của biểu thức có trong câu lệnh này. Câu lệnh return kết thúc việc thực hiện các câu lệnh trong thân hàm và trả điều kiện về chỗ đã gọi hàm trong chương trình chính. Tuy nhiên câu lệnh return là không bắt buộc phải có. Hàm trả lại giá trị qua tên hàm nên hàm có thể được dùng là một toán hạng trong biểu thức. Trong C++ chỉ có một loại chương trình con đó là hàm. Mỗi chương trình Trong C++ phải có ít nhất một hàm main( ). Hàm trong C++ không nhất thiết phải có tham số, trả lại giá trị( đó là kiểu void). Trong chương trình nguồn hàm có thể là một toán hạng trong biểu thức hoặc có thể đứng một mình như một câu lệnh đơn độc. Ví dụ: #include #include // Dinh nghia ham BINH_PHUONG int BINH_PHUONG(int n) { int ketqua; ketqua=n*n; return ketqua; } // Chuong trinh chinh main() { int m; cout<<"m="; cin>>m; cout<<'\n'<<m<<"binhphuong="; cout<<BINH_PHUONG(m); (1); getch(); } Trong chương trình này dòng(1) có chứa lời gọi hàm là BINH_PHUONG(m). ở đây m được gọi là tham số thực sự gặp lời gọi này máy sẽ thực hiện hàm BINH_PHUONG mà ta đã khai báo ở trên. II.Sử dụng hàm. Muốn sử dụng hàm ta phải viết lời gọi hàm. Lời gọi hàm có dạng sau: Tên hàm( [ Danh sách tham số thực sự] ) Danh sách tham số thực sự bao gồm một hay một số tham số thực sự cách nhau bởi dấu phẩy. Danh sách tham số thực sự có thể là một hàm, một biến hoặc một biểu thức. Danh sách tham số thực sự là tuỳ chọn. Số tham số thực sự trong danh sách tham số thực sự phải bằng số tham số hình thức trong danh sách tham số hình thức. Kiểu của tham số thực sự phải phù hợp với kiểu của tham số hình thức tương ứng. Một lời gọi hàm có thể làm cho 1 hay 2 điều xuất hiện. Nếu hàm đã được khai báo là inline thì thân của hàm được mở rộng tại điểm gọi nó trong lúc dịch, ngoài ra hàm sẽ được gọi trong lúc chạy. Một lời gọi hàm làm cho điều khiển của chương trình được chuyển cho hàm được gọi, việc thực hiện của hàm đang chạy lúc đó bị tạm ngừng. Khi tính toán của hàm được gọi đã hoàn tất thì hàm bị ngừng sẽ lấy lại hoạt động tại điểm sau lời gọi. Việc gọi hàm được quản lý trong chồng khi chạy của chương trình. Nếu một hàm không được khai báo trong chương trình trước khi dùng nó thì sẽ có lỗi khi dịch. Hàm chỉ được định nghĩa một lần trong chương trình. Về cơ bản định nghĩa hàm trong tệp văn bản riêng của nó hay trong tệp văn bản có chứa nó và các hàm có liên quan khác. Một hàm thường được dùng trong các tệp khác tệp chứa định nghĩa của nó. Do đó cần có phương pháp phụ để khai báo hàm. Khai báo hàm bao gồm kiểu cho lại của hàm, tên hàm và danh sách đối. III.Truyền tham số cho hàm. Khi gặp lời gọi hàm trong chương trình chính thì quá trình thực hiện hàm bắt đầu. Quá trình này gồm các công việc sau: - Máy tạm thời rời khỏi chương trình chính, cấp phát bộ nhớ cho các tham số hình thức và các biến cục bộ. - Gán các giá trị của tham số thực sự cho các tham số hình thức tương ứng. - Lần lượt thực hiện các câu lệnh trong thân hàm. Nếu gặp câu lệnh return hoặc gặp dấu “}” thì máy sẽ xoá các tham số hình thức hoặc các biến cục bộ quay về chương trình chính ở chỗ có lời gọi hàm. Nếu thoát khỏi hàm bằng câu lệnh Return thì giá trị biểu thức có trong câu lệnh này sẽ được gán cho tên hàm. Khi gặp lời gọi hàm thì giá trị tham số thực sự sẽ được gán cho tham số hình thức tương ứng, mọi tính toán trong thân hàm sẽ được thực hiện trên các tham số hình thức. Khi thoát khỏi hàm máy sẽ xoá các tham số hình thức và các biến cục bộ, như vậy những thay đổi đối với các tham số hình thức không thể được truyền về chương trình chính thông qua tham số thực sự tương ứng. Vậy làm thế nào để trong chương trình con có thể thay đổi giá trị các biến có trong chương trình chính? Người ta dùng con trỏ làm tham số hình thức để giải quyết vấn đề này. Khi đó người ta truyền cho chương trình con địa chỉ của biến trước và sau lời gọi hàm( tức là trước và sau khi thực hiện hàm địa chỉ này không thay đổi, hoàn toàn phù hợp với các giả định của C++. Tuy nhiên trong quá trình thực hiện hàm thì giá trị chứa trong địa chỉ đó có thể bị thay đổi, giá trị này được giữ nguyên khi thoát khỏi hàm. Đây là phương pháp truyền giá trị từ chương trình con về chương trình chính. VD: Truyền giá trị từ chương trình con về chương trình chính. // Chuong trinh co ham tinh tong n so. #include #include float TONG(float *vecto, int n) { int i; float s=0; for(i=0; i<n;i++) s=s+ *(vecto+i); return (s); } main() { int i; float a[4]={1,2,3,4}; float b[6]={5,1,2,3,1,4}; clrscr(); cout<<"\n tong vecto a="<<TONG(a,4);//in so 10 cout<<"\n tong vecto b="<<TONG(&b[0],6); //in ra so 10 getch(); } IV. Sử dụng hàm trong nhiều chương trình khác. Giả sử có một tệp gọi là: DVVECTERE.CPP Chứa các hàm sau: Float TONG VTF( float * vecter, int n); Float TICH VTF ( float * vecter, int n); Void NHAP VTF ( float * vecter, int n); Void IN VTF ( float * vecter, int n); // Chương trình hàm định nghĩa trong chương trình khác #include #include #include "C:\ baitap TC \ dvvecter.CPP" main( ) { int n=2; float a[10]; NHAP VTF (a,n); IN VTF(a,n); TONG VTF(a,n); TICH VTF (a,n); Getch( ); } V. Danh sách đối của hàm. Các hàm khác nhau của một chương trình có thể thâm nhập chung vào các giá trị với nhau theo 2 phương pháp. Một phương pháp là dùng biến toàn cục trong chương trìnhl; Phương pháp thứ hai là dùng danh sách đối hình thức. Danh sách đối đưa ra một phương pháp khác để thâm nhập chung vào các giá trị giữa một hàm và chương trình chung. Danh sách đối cùng với kiểu cho lại của hàm xác định ra giao diện chung của hàm. Một hàm khép kín có thể được dùng qua nhiều chương trình, nó không nhất thiết bị giới hạn vào một ứng dụng riêng. Nếu bỏ bớt đi một đối hay truyền cho một đối kiểu sai sẽ gây ra lỗi. Khả năng lỗi trong truyền đối tăng lên theo kích cỡ của danh sách đối, dùng tối đa là 8 đối. *Cú pháp danh sách. Không được phép bỏ thiếu danh sách đối của hàm. Một hàm không có đối có thể được biểu thị hoặc bằng danh sách đối rỗng hoặc bằng danh sách đối chỉ chứa một từ khoá void. //Khai báo tương đương int fork(); int fork( void); Danh sách đối còn được gọi là dấu hiệu của hàm bởi vì nó thường được dùng để phân biệt một thể nghiệm của hàm này với hàm khác. Tên và dấu hiệu một hàm xác định duy nhất nó. Dấu hiệu bao gồm một danh sách các kiểu đối phân cách nhau bởi dấu phẩy. Không có hai tên đối nào xuất hiện trong dấu hiệu được phép trùng nhau. Tên đối cho phép đối đó được thâm nhập từ trong thân của hàm. Do đó tên đối không cần viết trong khai báo hàm. *Truyền đối. Danh sách đối của hàm mô tả cho các đối hình thức. Mỗi đối hình thức được cấp bộ nhớ bên trong vùng nhớ của hàm. Các biểu thức nằm giữa 2 dâu ngoặc tròn của lời gọi hàm được gọi là các đối thực tại của lời gọi. Việc truyền đối vậy là một tiến trình khởi đầu cho vùng nhớ của các đối hình thức theo các đối thực tại. Với truyền theo giá trị, hàm không bao giờ thâm nhập vào các đối thực tại của lời gọi, nội dung của đối thực tại không bị thay đổi. Có 2 phương án truyền theo giá trị. Thứ nhất là đối hình thức được khai báo là con trỏ. Void pswap( int * x, int * y) { int tg=* y; *y=* x; *x=tg; } Thứ 2 để truyền theo giá trị là khai báo đối hình thức có kiểu tham khảo Void rswap( int &x, int &y) { int tg= y; y= x; x=tg; } VI. Các hàm trong C++. 1. Tham chiếu. Tham chiếu là một bí danh của một vùng nhớ được cấp phát cho một biến nào đó. Một tham biến có thể là một biến tham số hình thức của hàm hay dùng làm một giá trị trả về của hàm. *Tham chiếu tới một biến. VD: int n; int &p=n; Dấu & xác định p là một biến tham chiếu, còn dấu "=" và tên biến n để xác định vùng nhớ mà p tham chiếu tới. Về bản chất tham chiêu và tham trỏ giống nhau vì cùng chỉ đến đối tượng có địa chỉ, cùng được cấp phát địa chỉ khi khai báo, nhưng cách sử dụng chúng thì khác nhau. Khi nói đến tham chiếu "&p" ta phải gắn nó với một biến nào đó đã khai báo qua "&p=n", trong khi đó khai báo con trỏ "*p" không nhất thiết phải khởi tạo giá trị cho nó. Sau khi khởi tạo cho tham chiếu gắn với một biến nào đó rồi thì ta không thể thay đổi để gắn tham chiếu với một biến khác, do vậy để truy nhập đến vùng nhớ tương ứng với một biến chúng ta có thể sử dụng hoặc là tên biến hoặc là tên tham chiếu tương ứng. VD: #include Void main( ) { int x=3, &y=x; // y lúc này là " bí danh" của x cout<<"x="<<x<<"\n"; cout<<"y="<<y<<"\n"; y=7; cout<<"x="<<x<<"\n"; <<"y="<<y<<"\n"; } Không thể gắn một tham chiếu với một hằng số trừ trường hợp có từ khoá const đứng trước khai báo tham chiếu. Const int &p=3; *Hằng tham chiếu. Hằng tham chiếu được khai báo như sau: Int n=5; Const int &x=n; Cũng giống như biến, hằng tham chiếu đến một biến hoặc một hằng. Int n=5; Const int &x=n; Const int &y=100; Hằng tham chiếu không được phép thay đổi giá trị của vùng nhớ mà nó tham chiếu. Hằng tham chiếu thường được sử dụng làm đối của hàm để cho phép hàm sử dụng giá trị của các tham số trong lời gọi hàm. *Truyền tham số cho hàm bằng tham chiếu. Nếu đối là biến hoặc hằng tham chiếu kiểu K thì tham số ( trong lời gọi hàm) phải là biến hoặc phần tử mảng kiểu K. VD: /*swap.cpp*/ #include #include /*Ham swap1 duoc goi voi cac tham so duoc truyen theo tham tri*/ void swap1(int x, int y) { int temp=x; x=y; y=temp; } /*Ham swap2 thuc hien viec truyen tham so bang tham tro*/ void swap2(int *x, int *y) { int temp=*x; *x=*y; *y=temp; } /*Ham swap3 thuc hien viec truyen tham so bang tham chieu*/ void swap3(int &x, int &y) { int temp=x; x=y; y=temp; } void main() { int a=2, b=3; clrscr(); cout<<"Truoc khi goi swap1:\n"; cout<<"a = "<<a<<"b = "<<b<<"\n"; swap1(a,b); cout<<"Sau khi goi ham swap1:\n"; cout<<"a = "<<a<<"b = "<<b<<"\n"; a=2;b=3; cout<<"Truoc khi goi swap2:\n"; cout<<"a = "<<a<<"b = "<<b<<"\n"; swap2(&a,&b); cout<<"Sau khi goi ham swap2:\n"; cout<<"a = "<<a<<"b = "<<b<<"\n"; a=2;b=3; cout<<"Truoc khi goi swap3:\n"; cout<<"a = "<<a<<"b = "<<b<<"\n"; swap3(a,b); cout<<"Sau khi goi ham swap3:\n"; cout<<"a = "<<a<<"b = "<<b<<"\n"; getch(); } ket qua se la: Truoc khi goi swap1: a=2 b=3 Sau khi goi swap1: a=2 b=3 Truoc khi goi swap2: a=2 b=3 Sau khi goi swap2: a=3 b=2 Truoc khi goi swap3: a=2 b=3 Sau khi goi swap3: a=3 b=2 Trong chương trình trên ta truyền tham số a,b cho hàm swap1() theo tham trị nên giá trị của chúng trước và sau khi gọi hàm là không thay đổi. Hàm swap2( ) thay vì truyền trực tiếp giá trị 2 biến a,b người ta truyền địa chỉ của chúng rồi thông qua các địa chỉ này để xác định giá trị biến, bằng cách đó giá trị của 2 biến a,b sẽ hoán đổi cho nhau sau lời gọi hàm. Hàm swap3( )đưa ra giải pháp sử dụng tham chiếu, các tham số hình thức của hàm swap3( ) bây giờ là các tham chiếu đến các tham số thực được truyền cho hàm. Nhờ vậy mà giá trị của 2 tham số thực a và b có thể hoán đổi được cho nhau. *Giá trị trả về của hàm là tham chiếu. Định nghĩa của hàm có dạng: & fct(… ) { … return; } Biểu thức được trả lại trong câu lệnh return phải là tên của một biến xác định từ bên ngoài hàm. Vì nếu là biến cục bộ thì nó sẽ bị mất đi khi kết thúc thực hiện hàm. Khi trả về của hàm là tham chiếu ta có thể gặp vế trái là một lời gọi hàm chứ không phải là tên một biến. VD: #include #include struct TS { char ht[25]; float dt,dl, dh,td; }; TS ts; TS &f() { return ts; } void main() { TS &h=f(); // h tham chieu den bien ts cout<<"\n Ho ten:"; cin.get(h.ht,25); cout<<" Cac diem toan, diem ly, diem hoa:"; cin>>h.dt>>h.dl>>h.dh; h.td=h.dt+h.dl+h.dh; cout<<"\n Ho ten:"<<ts.ht; cout<<"\n Tong diem:"<<ts.td; getch(); } 2. Đối có giá trị mặc định. Thông thường số tham số trong lời gọi hàm sẽ bằng số đối của hàm. Mỗi đối sẽ được khởi gán giá trị theo tham số tương ứng của nó. C++ cho phép tạo giá trị mặc định cho các đối. Các đối này có thể có hoặc không có tham số trong lời gọi hàm. Khi không có tham số tương ứng đối được khởi gán bởi giá trị mặc định. Sử dụng hàm có đối mặc định: Lời gọi hàm cần viết theo quy định sau: Các tham số thiếu vắng trong lời gọi hàm phải tương ứng với các đối mặc định cuối cùng, nghĩa là đã dùng giá trị mặc định cho một đối thì cũng phải sử dụng giá trị mặc định cho các đối còn lại. VD: Hàm có 3 đối mặc định. Void h( int d1, float d2, char *d3="VIET NAM", int d4=10, double d5=3.14); //lời gọi hàm h( 3, 3.4, "ABC", 10, 10); h( 3, 3.4, "ABC"); h( 3, 3.4); 3. Hàm trực tuyến( inline). Để khắc phục nhược điểm của hàm là làm chậm tốc độ chương trình do phải thực hiện một số thao tác có tính thủ tục mỗi khi gọi hàm. Người ta dùng hàm trực tuyến. Để biến một hàm thành trực tuyến ta viết thêm từ khoá inline vào trước nguyên mẫu hàm. Nếu không dùng nguyên mẫu thì viết từ khoá này trước dòng đầu tiên của định nghĩa hàm. VD: Inline float f( int n, float x); Float f(int n, float x) { // Các câu lệnh trong thân hàm } hoặc inline float f(int n, float x) { // Các câu lệnh trong thân hàm } Không được đặt inline trước định nghĩa hàm. Nếu không bị quẩn không thoát được. VD: Sử dụng hàm trực tuyến. Chương trình tính chu vi, diện tích của hình chữ nhật( Không khai báo nguyên mẫu khi đó hàm tính phải đặt trên hàm main). #include #include<iostream.h inline void dtcvhcn(int x, int y, int& dt,int& cv) { dt=x*y; cv=2*(x+y); } void main() { int x[10],y[10],dt[10],cv[10],; cout<<"\n So hinh chu nhat:"; cin>>n; for(int i=1;i<=n;++i) { cout<<"\n Nhap 2 canh cua hinh chu nhat thu"<<i<<":"; cin>>x[i]>>y[i]; dtcvhcn(x[i],y[i],dt[i],cv[i]); } clrscr(); for(i=1;i<=n;++i) { cout<<"\n Hinh chu nhat thu"<<i<<":"; cout<<"\n do dai 2 canh="<<x[i]<<"va"<<y[i]; cout<<"\n Dien tich="<<dt[i]; cout<<"\n Chu vi="<<cv[i]; } getch(); } 4. Đệ quy. Một đối tượng được gọi là có tính đệ quy nếu trong định nghĩa đối tượng này lại dùng chính bản thân nó tức là dùng chính đối tượng để định nghĩa đối tượng. Hàm đệ quy là hàm trong định nghĩa hàm có sử dụng lời gọi hàm. Một định nghĩa đệ quy có ít nhất 2 điều kiện: - Điều kiện dừng: Nó không chứa đối tượng đang định nghĩa. - Thành phần đệ quy: Nó có chứa đối tượng đang định nghĩa. Nếu không có điều kiện dừng thì hàm sẽ đệ quy “mãi mãi”. Sử dụng kỹ thuật đệ quy cho phép biến một quá trình gồm vô hạn các thao tác thành một quá trình gồm một số hữu hạn. Sau đó giao cho máy thực hiện với tốc độ rất cao. Chương trình con đệ quy là chương trình con có chứa lời gọi đến chính nó. Khi gặp một lời gọi đến chương trình con máy sẽ tạo ra một tập hợp các biến cục bộ mới, có bao nhiêu lời gọi đến chương trình con thì có bấy nhiêu lần thoát khỏi nó. Mỗi khi thoát khỏi chương trình con thì một tập hợp các biến cục bộ được giải phóng, quá trình giải phóng các biến cục bộ ngược với quá trình tạo ra nó, nghĩa là tập hợp biến cục bộ nào tạo ra sau thì sẽ được giải phóng trước. Viết và sử dụng các hàm đệ quy làm cho chương trình ngắn gọn nhưng tốn thời gian tính toán và tốn bộ nhớ. Bằng phương pháp lập trình thông thường có thể không cần đến kỹ thuật đệ quy. VD: // định nghĩa hàm GIAI_THUA theo kiểu đệ quy. Int GIAI_THUA( int n) { int gt; if( n==0) gt=1; // điều kiện dừng else gt=*n GIAI_THUA( n-1); //thành phần đệ quy return( gt); } Chương II. Biến toàn cục, biến cục bộ. I. Biến toàn cục. Biến toàn cục là một biến được khai báo trong chương trình và có ý nghĩa( nghĩa là có thể sử dụng) trong chương trình này cũng như tất cả các khối chương trình thuộc về chương trình này. Như vậy biến toàn cục có thể được sử dụng trong nhiều khối chương trình khác nhau. Biến toàn cục có thể được thâm nhập tới từ trong thân của hàm, chỉ cần nó được khai báo đúng chỗ. Người lập trình có thể gán một giá trị cho lại thứ hai cho một biến toàn cục. Biến toàn cục có ưu điểm là đơn giản, tiện lợi tiện dùng. Nhược điểm của nó là không trực giác. Tức là từ lời gọi hàm ta không biết được biến này đã được đặt giá trị. Nó gây khó khăn cho người lập trình khác khi muốn hiểu hay muốn thay đổi chương trình. Khả năng thâm nhập chung vào biến toàn cục từ bất kỳ đâu bên trong chương trình vừa là lợi ích chính của nó vừa là độ tin cậy có ý nghĩa nhất. Tính thấy được của biến toàn cục làm cho nó trở thành phương pháp thuận tiện cho liên lạc giữa các phần khác nhau của chương trình. Nhược điểm của việc dùng biến toàn cục cho việc liên lạc giữa các hàm là như sau: + Các hàm có dùng tới biến toàn cục phụ thuộc vào sự tồn tại và kiểu của biến toàn cục đó, làm cho việc dùng lại hàm này trong ngữ cảnh khác trở lên khó khăn hơn nhiều. + Nếu cần sửa đổi chương trình thì những sự phụ thuộc toàn cục sẽ làm tăng khả năng sinh lỗi. Hơn nữa việc đưa vào những thay đổi cục bộ đòi hỏi việc hiểu biết toàn bộ chương trình. + Nếu một biến toàn cục nhận một giá trị không đúng thì phải tìm kiếm trong toàn bộ chương trình để xem lỗi xuất hiện ở đâu; không có việc cục bộ hoá. + Việc đệ quy lại còn khó khăn đi đến đúng chỗ hơn khi hàm dùng một biến toàn cục. Một biến cục bộ có thể dùng lại tên của một biến toàn cục. Khi đó biến cục bộ che lấp biến toàn bộ cùng tên. Chẳng hạn: include int x; main( ) { int x=10; //biến cục bộ cout<< x <<"\n"; //biến toàn cục } Trong trường hợp đó, khi muốn truy xuất tới biến toàn cục phải sử dụng toán tử phạm vi "::" trước tên biến: include int x; main( ) { int x=10; //biến cục bộ ::x=10;// biến toàn cục cout<< x <<"\n"; //x cục bộ cout<< ::x <<"\n"; //x toàn cục } Một biến toàn cục được định nghĩa trong một tệp nhưng được dùng ở tệp thứ hai hay trong nhiều tệp khác. Từ khoá extert đưa ra giải pháp. Hai biến toàn cục được định nghĩa trong các tệp chương trình tách biệt cùng dùng chung một tên nhưng được dự định nói tới các thực thể chương trình khác nhau, mỗi biến rõ ràng được dịch riêng rẽ. Nhưng khi gắn lại với nhau, biến bị báo là có nhiều định nghĩa và trình biên dịch dừng lại. Việc dùng từ khoá static đưa ra một giải pháp. II. Biến cục bộ. Biến cục bộ là biến được khai báo trong chương trình và nó chỉ có ý nghĩa ở phạm vi nó khai báo. Khi ra khỏi phần nó khai báo thì nó không còn dùng được nữa. Các nguyên lý của biến cục bộ: + Các biến cục bộ ( dù trùng tên với biến toàn cục) cũng không làm thay đổi giá trị của biến toàn cục. + Mọi tham biến hình thức loại truyền theo trị trong các chương trình con( thủ tục và hàm) đều là các biến cục bộ. + Các biến khai báo trong các chương trình con đều là các biến cục bộ. +Khi phải sử dụng biến phụ thì nên dùng biến cục bộ. Phạm vi cục bộ có thể lồng nhau. Mỗi khối có chứa một câu lệnh khai báo đều duy trì phạm vi cục bộ riêng của nó. Chương III. Chương trình có sử dụng định nghĩa hàm, biến toàn cục, biến cục bộ. #include #include #include #include struct MT { double a[20][20]; int n; }; struct VT { double b[20]; int n; }; ostream & operator<<(ostream & os, const MT & x); ostream & operator<<(ostream & os, const VT & y); istream & operator>>(istream & is, MT & x); istream & operator>>(istream & is, VT & y); MT operator+(const MT & x1,const MT & x2); MT operator-(const MT & x1,const MT & x2); MT operator*( const MT & x1,const MT & x2); VT operator*(const MT & x, const VT & y); MT operator!(MT x); ostream & operator<<(ostream & os, const MT & x) { os<<setprecision(2)<<setiosflags(ios::showpoint); for(int i=1;i<=x.n;++i) { os<<"\n"; for(int j=1;j<=x.n;++j) os<<setw(6)<<x.a[i][j]; } os<<"\n"; return os; } ostream & operator<<(ostream & os, const VT & y) { os<<setprecision(2)<<setiosflags(ios::showpoint); for(int i=1;i<=y.n;++i) os<<setw(6)<<y.b[i]; os<<"\n"; return os; } istream & operator>>(istream & is, MT & x); { cout<<"- cap ma tran:"; is>>x.n; cout<<"Nhap cac phan tu:\n"; for(int i=1;i<=x.n;++i) for(int j=1;j<=x.n;++j) { cout<<"PT hang"<<i<<"cot"<<j<<"="; is>>x.a[i][j]; } return is; } istream & operator>>(istream & is, VT & y) { cout<<"- cap vector:"; is>>y.n; cout<<"Nhap cac phan tu:\n"; for(int i=1;i<=y.n;++i) { cout<<"Phan tu thu"<<i<<"="; is>>y.b[i]; } return is; } MT operator+(const MT & x1,const MT & x2) { if(x1.n!=x2.n) { cout<<"\n Khong thuc hien duoc phep cong vi 2 ma tran khong cung cap"; getch(); return x1; } else { MT x; int i,j,n; n=x.n=x1.n; for(i=1;i<=n;++i) for(j=1;j<=n;++j) x.a[i][j]=x1.a[i][j]+x2.a[i][j]; return x; } } MT operator-(const MT & x1,const MT & x2) { if(x1.n!=x2.n) { cout<<"\n Khong thuc hien duoc phep tru vi 2 ma tran khong cung cap"; getch(); return x1; } else { MT x; int i,j,n; n=x.n=x1.n; for(i=1;i<=n;++i) for(j=1;j<=n;++j) x.a[i][j]=x1.a[i][j]-x2.a[i][j]; return x; } } MT operator*(const MT & x1,const MT & x2) { if(x1.n!=x2.n) { cout<<"\n Khong thuc hien duoc phep nhan vi 2 ma tran khong cung cap"; getch(); return x1; } else { MT x; int i,j,n,k; n=x.n=x1.n; for(i=1;i<=n;++i) for(j=1;j<=n;++j) { x.a[i][j]=0.0; for(k=1;k<=n;++k) x.a[i][j]+=x1.a[i][j]*x2.a[i][j]; } return x; } } VT operator*(const MT & x,const VT & y) { if(x.n!=y.n) { cout<<"\n cap ma tran khac cap vector, phep nhan vo nghia"; getch(); return y; } else { VT z; int n; n=z.n=y.n; for(int i=1;i<=n;++i) { z.b[i]=0; for(int j=1;j<=n;++j z.b[i]+=x.a[i][j]*y.b[j]; } return z; } } MT operator!(MT x) { MT v; int i,j,k,r,n; double tg; n=v.n=x.n; for(i=1;i<=n;++i) for(j=1;j<=n;++j) if(i==j) v.a[i][j]=1; else v.a[i][j]=0; for(k=1;k<=n;++k) { r=k; for(i=k+1;i<=n;++i) if(abs(x.a[i][k]>abs(x.a[r][k]))r=i; if(abs(x.a[r][k])<1.

Các file đính kèm theo tài liệu này:

  • doc77783.DOC
Tài liệu liên quan