&

VC

N i dung

BB

Khái niệm và cú pháp

1

Tầm vực

2

Tham số và lời gọi hàm

3

Đệ quy

4

11

NMLT ­ Hàm (Function)

&

VC

ặ ấ Đ t v n đ

BB

Viết chương trình tính S = a! + b! + c! với a, b, c

là 3 số nguyên dương nhập từ bàn phím.

Chương trình chính

Nhập a, b, c > 0 Tính S = a! + b! + c! Xuất kết quả S

22

NMLT ­ Hàm (Function)

Nhập a > 0 Nhập b > 0 Nhập c > 0 Tính s1=a! Tính s2=b! Tính s3=c!

&

VC

ặ ấ Đ t v n đ

BB

3 đoạn lệnh nhập a, b, c > 0

do {

printf(“Nhap mot so nguyen duong: ”); scanf(“%d”,&a);

} while (a <= 0);

do {

printf(“Nhap mot so nguyen duong: ”); scanf(“%d”,&b);

} while (b <= 0);

do {

printf(“Nhap mot so nguyen duong: ”); scanf(“%d”,&c);

33

NMLT ­ Hàm (Function)

} while (c <= 0);

&

VC

ặ ấ Đ t v n đ

BB

3 đoạn lệnh tính s1 = a!, s2 = b!, s3 = c!

{ Tính s1 = a! = 1 * 2 * … * a } s1 = 1; for (i = 2; i <= a ; i++) s1 = s1 * i;

{ Tính s2 = b! = 1 * 2 * … * b } s2 = 1; for (i = 2; i <= b ; i++) s2 = s2 * i;

44

NMLT ­ Hàm (Function)

{ Tính s3 = c! = 1 * 2 * … * c } s3 = 1; for (i = 2; i <= c ; i++) s3 = s3 * i;

&

VC

ặ ấ Đ t v n đ

BB

Giải pháp => Viết 1 lần và sử dụng nhiều lần  Đoạn lệnh nhập tổng quát, với n = a, b, c

do {

printf(“Nhap mot so nguyen duong: ”); scanf(“%d”,&n);

} while (n <= 0);

 Đoạn lệnh tính giai thừa tổng quát, n = a, b, c

{ Tính s = n! = 1 * 2 * … * n } s = 1; for (i = 2; i <= n ; i++)

55

NMLT ­ Hàm (Function)

s = s * i;

&

VC

Hàm

BB

Khái niệm

 Một đoạn chương trình có tên, đầu vào và

đầu ra.

 Có chức năng giải quyết một số vấn đề chuyên biệt cho chương trình chính.

 Được gọi nhiều lần với các tham số khác

nhau.

 Được sử dụng khi có nhu cầu:

• Tái sử dụng. • Sửa lỗi và cải tiến.

66

NMLT ­ Hàm (Function)

&

VC

Hàm

BB

Các đặc trưng của Hàm

 Nằm trong hoặc ngoài văn bản có chương trình gọi đến hàm. Một văn bản có thể chứa nhiều hàm.

 Được gọi từ chương trình chính (main), từ hàm

khác hoặc từ chính nó (đệ quy).

 Không lồng nhau.  Có 3 cách truyền giá trị: Truyền theo tham trị,

tham biến và tham trỏ.

 Các biến cục bộ trong hàm được tạo ra khi hàm

được gọi và biến mất khi hàm thực thi xong.

77

NMLT ­ Hàm (Function)

&

VC

Hàm

BB

88

NMLT ­ Hàm (Function)

&

VC

Hàm

BB

Có 2 loại hàm trong NNLT “C/C++”:  Hàm thư viện (library functions):

 Do chương trình dịch “C/C++” cung cấp.  Để sử dụng các hàm này trong chương trình, đầu chương trình phải chứa các khai báo và định nghĩa hằng, biến, hàm nguyên mẫu, . . . bằng các chỉ thị tiền xử lý #include .

 Ví dụ: #include #include

 Hàm tự tạo:

 Do người sử dụng định nghĩa thêm các hàm khác phục vụ cho nhu cầu lập trình của mình.

99

NMLT ­ Hàm (Function)

&

VC

Hàm

BB

Cú pháp

([danh sách tham số]) {

[return ;]

 Trong đó }

: kiểu bất kỳ của C (char, int,

long, float,…). Nếu không trả về thì là void. • : theo quy tắc đặt tên định danh. • : tham số hình thức đầu vào giống khai báo biến, cách nhau bằng dấu ,

: trả về cho hàm qua lệnh return.

1010

NMLT ­ Hàm (Function)

&

VC

ướ

ế

Các b

c vi

t hàm

BB

Cần xác định các thông tin sau đây:

 Tên hàm.  Hàm sẽ thực hiện công việc gì.  Các đầu vào (nếu có).  Đầu ra (nếu có).

Đầu vào 1

Đầu vào 2

Đầu ra (nếu có)

Đầu vào n

Các công việc sẽ thực hiện

1111

NMLT ­ Hàm (Function)

Tên hàm

&

VC

Hàm

BB

Ví dụ 1

 Tên hàm: XuatTong  Công việc: tính và xuất tổng 2 số nguyên  Đầu vào: hai số nguyên x và y  Đầu ra: không có

void XuatTong(int x, int y) {

int s; s = x + y; printf(“%d+%dy=%dx“,x,y,s);

1212

NMLT ­ Hàm (Function)

}

&

VC

Hàm

BB

Ví dụ 2

 Tên hàm: TinhTong  Công việc: tính và trả về tổng 2 số nguyên  Đầu vào: hai số nguyên x và y  Đầu ra: một số nguyên có giá trị x + y

int TinhTong(int x, int y) {

int s; s = x + y; return s;

1313

NMLT ­ Hàm (Function)

}

&

VC

ươ

Ch

ng trình con ­ Function

BB

Ví dụ 3

 Tên hàm: NhapXuatTong  Công việc: nhập và xuất tổng 2 số nguyên  Đầu vào: không có  Đầu ra: không có

void NhapXuatTong() {

int x, y; printf(“Nhap 2 so nguyen: ”); scanf(“%d%d”,&x,&y); printf(“%d+%dy=%dx“,x,y,x+y);

1414

NMLT ­ Hàm (Function)

}

&

VC

T m v c

BB

Khái niệm

 Là phạm vi hoạt động của biến và hàm.  Biến:

• Toàn cục: khai báo ngoài tất cả các hàm (kể cả hàm main) và có tác dụng lên toàn bộ chương trình.

• Cục bộ: khai báo trong hàm hoặc khối { } và chỉ có tác dụng trong bản thân hàm hoặc khối đó (kể cả khối con nó). Biến cục bộ sẽ bị xóa khỏi bộ nhớ khi kết thúc khối khai báo nó.

1515

NMLT ­ Hàm (Function)

&

VC

T m v c

BB

int a;

int Ham1() {

int a1;

}

int Ham2() {

int a2; {

int a21;

}

}

void main() {

int a3;

}

1616

NMLT ­ Hàm (Function)

&

VC

BB

Hàm nguyên m uẫ  (function prototype)

 Hàm nguyên mẫu:

 Được dùng để cung cấp thông tin cho chương trình dịch về tên hàm, kiểu giá trị trả về, số lượng, thứ tự và kiểu của các tham số của hàm.

 Chương trình dịch căn cứ vào các thông tin này để kiểm

tra các lời gọi hàm trong chương trình.

 Hàm nguyên mẫu được đặt sau phần khai báo toàn cục và ngay trước hàm main() hoặc có thể đặt trong tập tin khác.  Khai báo:

[] ([]) ;

1717

 Ví dụ: Khai báo hàm nguyên mẫu có chức năng xác định

trị min giữa 2 số nguyên. int Min(int, int) ; int Min(int a, int b) ; // nên dùng cách khai báo này

&

VC

ươ

T  ch c m t ch

ng trình “C/C++”

BB

PHẦN KHAI BÁO TOÀN CỤC

PHẦN KHAI BÁO VÀ ĐỊNH NGHĨA HÀM

HÀM main()

 Cách 1: chương trình gồm 3 phần

PHẦN KHAI BÁO TOÀN CỤC

PHẦN KHAI BÁO HÀM NGUYÊN MẪU

HÀM main()

PHẦN ĐỊNH NGHĨA HÀM

1818

 Cách 2: chương trình gồm 4 phần (nên dùng cách này)

&

VC

ươ

T  ch c m t ch

ng trình “C/C++”

BB

 Ví dụ: Cách 2

#include int min(int a, int b);

//prototype

#include int min(int a, int b) {

void main() { int a=40, b=30;

if (a

int min1 = min(a,b); printf(“Min = %d“,min1);

} void main() { int a=40, b=30;

} int min(int a, int b) {

int min1 = min(a,b); printf(“Min = %d“,min1);

if (a

}

}

1919

 Ví dụ: cách 1

&

VC

ươ

Các ph

ng pháp truy n tham s

BB

Có hai loại tham số:  Tham số thực (actual parameter):là tham số trong lời gọi

hàm.

2020

 Tham số hình thức (formal parameter): là tham số trong phần khai báo và định nghĩa. Tham số hình thức chỉ là tên đại diện cho tham số thực tương ứng. Kiểu của tham số hình thức sẽ qui định kiểu của tham số thực.

&

VC

ươ

Các ph

ng pháp truy n tham s

BB

 Ví dụ:

int min(int a, int b) //a,b là tham số hình thức {

if(a

int minAB =min(7,10)//Gọi hàm

2121

} void main() { // a = 7, b=10 } // Lúc này a,b là tham số thực

&

VC

ươ

Các ph

ng pháp truy n tham s

BB

Có hai cách truyền tham số: 1. Truyền tham trị (call by value):  Chương trình dịch cấp phát vùng nhớ riêng cho từng tham số hình thức, sau đó sao chép giá trị của tham số thực tương ứng vào các tham số hình thức.

 Khi kết thúc thực hiện hàm, chương trình dịch sẽ thu hồi các vùng nhớ đã cấp phát cho các tham số hình thức, và các biến cục bộ khai báo bên trong hàm.

 Như vậy, mọi sự thay đổi trị của các tham số hình thức đều

không ảnh hưởng đến các tham số thực bên ngoài hàm.

 Cách truyền:

void F(int, int ); // truyền bằng trị

hay

2222

void F(int a, int b); // truyền bằng trị

&

VC

ươ

Các ph

ng pháp truy n tham s

BB

 Truyền Giá trị (Call by Value)

 Truyền đối số cho hàm ở dạng giá trị.  Có thể truyền hằng, biến, biểu thức nhưng hàm

sẽ chỉ nhận giá trị.

 Được sử dụng khi không có nhu cầu thay đổi giá

trị của tham số sau khi thực hiện hàm.

void TruyenGiaTri(int x) {

… x++;

2323

NMLT ­ Hàm (Function)

}

&

VC

ươ

Các ph

ng pháp truy n tham s

BB

#include void doubleNum(int a); //prototype void main() { int a=40;

doubleNum(a); printf(“Bên trong hàm main:\n”); printf(“a = %d“, a);

} void doubleNum(int a) {

a = a*2; printf(“Inside doubleNum function. a = %d“,a);

}

2424

 Ví dụ: Khảo sát chương trình sau

&

VC

ươ

Các ph

ng pháp truy n tham s

BB

2. Truyền tham chiếu(call by reference):  Chương trình dịch sẽ truyền địa chỉ của các tham số thực tương

ứng cho các tham số hình thức.

 Nghĩa là ta có thể xem tham số hình thức cũng chính là tham số thực, hay nói cách khác tham số hình thức là tên gọi khác của tham số thực.

 Mọi sự thay đổi trị của tham số hình thức bên trong hàm chính là

thay đổi trị của tham số thực bên ngoài hàm.

 Cách truyền:

void Swap(int &,int &); // truyền bằng tham chiếu

hay

2525

void Swap(int & a,int & b); // truyền bằng tham chiếu

&

VC

ươ

Các ph

ng pháp truy n tham s

BB

Truyền Địa chỉ (Call by Address)

 Truyền đối số cho hàm ở dạng địa chỉ (con

trỏ).

 Không được truyền giá trị cho tham số này.  Được sử dụng khi có nhu cầu thay đổi giá

trị của tham số sau khi thực hiện hàm.

void TruyenDiaChi(int *x) {

… *x++;

2626

NMLT ­ Hàm (Function)

}

&

VC

ươ

Các ph

ng pháp truy n tham s

BB

 Truyền Tham chiếu (Call by Reference) (C++)

 Truyền đối số cho hàm ở dạng địa chỉ (con trỏ).

Được bắt đầu bằng & trong khai báo.

 Không được truyền giá trị cho tham số này.  Được sử dụng khi có nhu cầu thay đổi giá trị của

tham số sau khi thực hiện hàm.

void TruyenThamChieu(int &x) {

… x++;

2727

NMLT ­ Hàm (Function)

}

&

VC

ươ

Các ph

ng pháp truy n tham s

BB

#include void doubleNum(int a); //prototype void main() { int a=40;

doubleNum(a); printf(“Inside main function:\n”); printf(“a =%d “ , a);

} void doubleNum(int &a) {

a = a*2; printf(“Inside doubleNum function. a = %d“, a);

}

2828

 Ví dụ: Khảo sát chương trình sau

&

VC

ươ

Các ph

ng pháp truy n tham s

BB

Chú ý:  Trong cách truyền tham chiếu, tham số thực tương ứng phải là một biến. Còn trong cách truyền trị, tham số thực tương ứng có thể là biến, hằng, lời gọi hàm, hoặc một biểu thức cùng kiểu với tham số hình thức.

2929

 Các tham số hình thức trong cách truyền bằng giá trị được gọi là tham trị. Còn các tham số hình thức trong cách truyền bằng tham chiếu được gọi là tham biến.

&

VC

ố ố

ư

L u ý khi truy n đ i s

BB

Lưu ý

 Trong một hàm, các tham số có thể truyền

theo nhiều cách.

void HonHop(int x, int &y) {

… x++; y++;

3030

NMLT ­ Hàm (Function)

}

&

VC

ố ố

ư

L u ý khi truy n đ i s

BB

Lưu ý

 Sử dụng tham chiếu là một cách để trả về

giá trị cho chương trình.

int TinhTong(int x, int y) {

return x + y;

} void TinhTong(int x, int y, int &tong) {

tong = x + y;

} void TinhTongHieu(int x, int y, int &tong, int &hieu) {

3131

NMLT ­ Hàm (Function)

tong = x + y; hieu = x – y;

}

&

VC

ờ ọ

L i g i hàm

BB

 Cách thực hiện

 Gọi tên của hàm đồng thời truyền các đối số (hằng, biến, biểu thức) cho các tham số theo đúng thứ tự đã được khai báo trong hàm.  Các biến hoặc trị này cách nhau bằng dấu ,  Các đối số này được được đặt trong cặp dấu

ngoặc đơn ( )

(<đối số 1>,… , <đối số n>);

3232

NMLT ­ Hàm (Function)

&

VC

ờ ọ

L i g i hàm

BB

Ví dụ

3333

NMLT ­ Hàm (Function)

&

VC

ờ ọ

ươ

L i g i ch

ng trình con

BB

Ví dụ

3434

NMLT ­ Hàm (Function)

&

VC

Đ  quy

BB

3. Hàm gọi đệ qui: một lệnh trong thân hàm gọi đến chính nó. Số lần

gọi này phải có giới hạn (điểm dừng)  Ví dụ: chương trình tính giai thừa của n.

int giaiThua(int n) {

#include int giaiThua(int n); void main() {

int gt; if(n==1) return(1); // goi de qui gt = giaiThua(n­1)*n;  return gt;

}

int gt4, gt7; gt4 = giaiThua(4); gt7 = giaiThua(7); cout << “4! =“ << gt4 << endl; cout << “7! =“ << gt7 << endl;

3535

}

&

VC

Đ  quy

BB

Đặc điểm của hàm đệ qui:  Chương trình viết rất gọn,  Việc thực hiện gọi đi gọi lại hàm rất nhiều lần phụ thuộc vào độ lớn của đầu vào. Do đó chương trình sẽ mất thời gian để lưu giữ các thông tin của hàm gọi trước khi chuyển điều khiển đến thực hiện hàm được gọi. Mặt khác các thông tin này được lưu trữ nhiều lần trong ngăn xếp sẽ dẫn đến tràn ngăn xếp nếu n lớn.

3636

 Tuy nhiên, đệ qui là cách viết rất gọn, dễ viết và đọc chương trình, mặt khác có nhiều bài toán hầu như tìm một thuật toán lặp cho nó là rất khó trong khi viết theo thuật toán đệ qui thì lại rất dễ dàng.

&

VC

Đ  quy

BB

Lớp các bài toán giải được bằng đệ qui  Giải quyết được dễ dàng trong các trường hợp riêng gọi là trường hợp suy biến hay cơ sở, trong trường hợp này hàm được tính bình thường mà không cần gọi lại chính nó,

3737

 Đối với trường hợp tổng quát, bài toán có thể giải được bằng bài toán cùng dạng nhưng với tham đối khác có kích thước nhỏ hơn tham đối ban đầu. Và sau một số bước hữu hạn biến đổi cùng dạng, bài toán đưa được về trường hợp suy biến.

&

VC

Đ  quy

BB

 Các ví dụ  Ví dụ 1 : Tìm UCLN của 2 số a, b. Bài toán có thể được định

nghĩa dưới dạng đệ qui như sau: − nếu a = b thì UCLN = a − nếu a > b thì UCLN(a, b) = UCLN(a-b, b) − nếu a < b thì UCLN(a, b) = UCLN(a, b-a)

 Chương trình đệ qui để tính UCLN của a và b như sau.

int UCLN(int a, int b) // qui uoc a, b > 0 { if (a < b) UCLN(a, b-a); if (a == b) return a; if (a > b) UCLN(a-b, b);

3838

}

&

VC

Đ  quy

BB

 Ví dụ 2 : Tính số hạng thứ n của dãy Fibonaci là dãy f(n) được

− f(0) = f(1) = 1

− f(n) = f(n-1) + f(n-2) với n ≥ 2.

định nghĩa:

{ long kq;

if (n==0 || n==1) kq = 1; else kq = Fib(n-1) + Fib(n-2);

return kq;

}

3939

long Fib(int n)

&

VC

(Function overloading)

ồ N p ch ng hàm

BB

 Nạp chồng hàm là dùng chung một danh hiệu để đặt tên cho các

hàm khác nhau.

void main() {

double x = 20.0; int y = 10; F(x, y); // mơ hồ! chương trình dịch không biết gọi hàm nào

}

 Chỉ nạp chồng hàm đối với những hàm giống nhau về bản chất, nhưng khác nhau ở số lượng, và kiểu dữ liệu của các tham số.  Khả năng nạp chồng hàm kết hợp với hàm có tham số với giá trị

4040

ngầm định có thể gây ra tình trạng nhập nhằng, mơ hồ void F(int, double) { …. } void F(int) { …. } void F(double) { … }

&

VC

ộ ố ợ

ế ế

M t s  g i ý khi thi

t k  hàm

BB

 Xác định rõ chức năng, nhiệm vụ của hàm.  Chỉ nên thiết kế hàm theo phương châm “mỗi hàm chỉ thực hiện một nhiệm vụ duy nhất”, và nên thiết kế sao cho có thể sử dụng lại hàm để hổ trợ cho các việc khác (reusable).

4141

 Đặt tên hàm sao cho có tính gợi nhớ (Memonic)  Nên đặt chú thích, ghi rõ các thông tin về hàm như chức năng, điều kiện dữ liệu vào, xác định dữ liệu ra của hàm, . . .  Xác định trị trả về: hàm có cần trả về giá trị? Nếu có, xác định rõ kiểu trả về. Đối với các hàm có chức năng nhập/xuất dữ liệu, trị trả về thường là void. Còn đối với loại hàm kiểm tra một tính chất P nào đó, ta thường trả về giá trị 0 hoặc 1, i.e. trả về trị của một biểu thức logic.

&

VC

ộ ố ợ

ế ế

M t s  g i ý khi thi

t k  hàm

BB

 Xác định số lượng tham số và kiểu của từng tham số: hàm có nhận tham số hay không? Bao nhiêu tham số? Kiểu của từng tham số?

4242

 Xác định rõ phương pháp truyền tham số: nếu không có nhu cầu làm thay đổi trị của tham số thực truyền vào cho hàm thì áp dụng phương pháp truyền bằng giá trị. Còn ngược lại thì áp dụng cách truyền bằng tham chiếu.

&

VC

ố ượ

Ph m vi (scope) c a các đ i t

ng

BB

 Phạm vi là vùng chương trình mà đối tượng được nhận biết và có

thể được sử dụng.

 Phạm vi của một đối tượng trải dài từ nơi nó được khai báo đến

cuối khối, hàm, hay tập tin chứa đối tượng đó. Có các loại phạm vi sau:

− Phạm vi khối (Block scope) − Phạm vi hàm (Function scope)

 Phạm vi cục bộ (local scope)

− Phạm vi tập tin (File scope) − Phạm vi chương trình (Program scope)

4343

 Phạm vi toàn cục (global scope)

&

VC

ố ượ

Ph m vi (scope) c a các đ i t

ng

BB

 Phạm vi khối: Trong C, một khối được giới hạn bởi ngoặc {}. Biến khai báo trong khối đó có phạm vi khối, nghĩa là nó chỉ hoạt động trong khối đó mà thôi. Phạm vi này còn gọi là cục bộ, và biến đưọc gọi là biến cục bộ.

 Ví dụ: int main()

4444

{ int i; /* block scope */ . . . return 0; }

&

VC

BB

ố ượ

Ph m vi (scope) c a các đ i t

ng

 Ví dụ: 1: /* Scopes in nested block */ 2: #include 3: 4: main() 5: { 6: int i = 32; /* block scope 1*/ 7: 8: cout<<"Within the outer block: i=“<

Kết quả: Within the outer block: i=32 Within the inner block: i= 0, j=10 i= 1, j= 9 i= 2, j= 8 i= 3, j= 7 i= 4, j= 6 i= 5, j= 5 i= 6, j= 4 i= 7, j= 3 i= 8, j= 2 i= 9, j= 1 i=10, j= 0 Within the outer block: i=32

4545

&

VC

BB

ố ượ

Ph m vi (scope) c a các đ i t

ng

 Phạm vi hàm: chỉ định một biến có phạm vi hoạt động từ đầu đến cuối một hàm (không nhầm lẫn với biến có phạm vi khối). Trong C, chỉ có nhãn (label) đối với lệnh goto là có phạm vi hàm.

 Ví dụ : int main()

. .

. .

{ int i; /* block scope */ start: /* A goto label has function scope */ goto start; /* the goto statement */

. .

4646

return 0;

}

&

VC

BB

ố ượ

Ph m vi (scope) c a các đ i t

ng

 Phạm vi chương trình: Biến có phạm vi chương trình khi nó

được khai báo bên ngoài các hàm.

 Ví dụ:

int i; /* block scope */

. . return 0;

int x = 0; /* program scope */ float y = 0.0; /* program scope */ int main() { }

4747

 Biến này còn gọi là biến toàn cục

&

VC

BB

ố ượ

Ph m vi (scope) c a các đ i t

ng

 Ví d :ụ

ế

ả   K t qu : From function_1:   x=1234, y=1.234567 Within the main block:   x=4321, y=1.234567 From function_1:   x=1234, y=1.234567 Within the nested block:   x=4321, y=7.654321

1:  /* Program scope vs block scope */ 2:  #include  4:  int x = 1234;         /* program scope */ 5:  double y = 1.234567;  /* program scope */ 7:  void function_1() 8:  { 9:     cout<<"From function_1: x=,”<

4848

&

VC

BB

ố ượ

Ph m vi (scope) c a các đ i t

ng

 Phạm vi tập tin: Trong C, biến được khai báo là toàn cục và

static được gọi là có phạm vi tập tin.

4949

int x = 0; /* program scope */ static int y = 0; /* file scope */ static float z = 0.0; /* file scope */ int main() { int i; /* block scope */ . . . return 0; }

&

VC

BB

ố ượ

Ph m vi (scope) c a các đ i t

ng

 Ví dụ:

cout<<”Y = “<

bị hủy, không thể truy xuất

#include int x=3; // biến x toàn cục const int MAX = 10; void fct(int x); void main() {

cout<<”X của hàm main() = “<

int x=1; // x cục bộ của hàm main() fct(x);

“<

}

{

int y=4; x += y;

5050

}

&

VC

BB

ố ượ

Ph m vi (scope) c a các đ i t

ng

Biến toàn cục (local variable) Biến cục bộ (Global variable)

Biến cục bộ là biến khai báo bên trong khối hay hàm của khối. Biến toàn cục là biến khai báo bên ngoài mọi hàm

Có thể được truy xuất ở mọi nơi trong chương trình.

Chỉ có thể được truy xuất bên trong phạm vi khối hay hàm đó mà thôi.

Các biến toàn cục có thời gian tồn tại là thời gian của chương trình

5151

Các biến cục bộ có thời gian tồn tại tương đối ngắn. Chúng sẽ bị hủy mỗi khi ra khỏi khối hay kết thúc thực hiện hàm chứa nó.

&

VC

ấ ư

ố ượ

BB

ữ ủ C p l u tr  c a các đ i t

ng

 Cấp lưu trữ (storage class) là cách thức NNLT cấp phát vùng nhớ và lưu trữ biến. Cấp lưu trữ của một biến được xác định bằng các từ khóa sau: auto, register, static, extern.

 Biến auto (còn gọi là biến tự động, biến cục bộ):

 Mọi biến khai báo bên trong một khối hay hàm mặc nhiên

5252

có tính chất auto, trừ khi xác định rõ cấp lưu trữ khác.  Ví dụ, khai báo int x; tương đương với khai báo auto int x;.  Biến auto có phạm vi cục bộ bên trong hàm hay khối và có thời gian tồn tại ngắn, do được cấp phát trong vùng nhớ STACK.

&

VC

BB

ấ ư

ố ượ

ữ ủ C p l u tr  c a các đ i t

ng

 Để tăng tốc độ truy xuất biến, chương trình dịch lưu trữ biến trong thanh ghi. Chương trình dịch có thể bỏ qua không đáp ứng lời yêu cầu này nếu có quá nhiều lời đề nghị loại này hoặc nếu không còn đủ thanh ghi để cấp phát.

 Ví dụ: int main()

 Biến register (ít dùng)

{ /* block scope with the register specifier */ register int i; . . . for (i=0; i

*/}

5353

. . . return 0; }

&

VC

BB

ấ ư

ố ượ

ữ ủ C p l u tr  c a các đ i t

ng

 Là biến được cấp phát trong vùng nhớ DATA do

đó có tính chất cố định, lâu dài.

 Biến static khai báo bên trong một khối, hay hàm sẽ không bị hủy khi ra khỏi khối hay hàm đó, và vẫn lưu giữ giá trị cũ của lần gọi hàm trước.

 Biến static phải được khởi tạo giá trị khi khai báo. Chương trình dịch sẽ chỉ khởi tạo giá trị cho biến static duy nhất một lần trong lần gọi hàm đầu tiên.

5454

 Biến static (còn gọi là biến tĩnh)

&

VC

BB

ấ ư

ố ượ

ữ ủ C p l u tr  c a các đ i t

ng

 Ví d : Bi n Static

static int lanthu = 0; lanthu++; i = 2 * i;

ạ ầ

ứ   cout << "Hàm ch y l n th  " << lanthu << ", i = " << i ;

} main() {

ạ ầ ạ ầ ạ ầ

ứ ứ ứ

ham(); // Hàm ch y l n th  1, i = 2 ham(); // Hàm ch y l n th  2, i = 4 ham(); // Hàm ch y l n th  3, i = 6

…}

5555

ế ụ int i = 1; void ham() {

&

VC

BB

ấ ư

ố ượ

ữ ủ C p l u tr  c a các đ i t

ng

 Biến extern

 Phạm vi của một biến extern trong chương trình có thể

được trải dài trên nhiều tập tin.

 Chương trình dịch sẽ không cấp phát thêm vùng nhớ cho biến có khai báo extern mà sử dụng chung vùng nhớ đã cấp phát trước đó.

 Ví dụ: int x = 0; /* a global variable */

5656

extern int y; /* an allusion to a global variable y */ int main() { extern int z; /* an allusion to a global variable z */ int i; /* a local variable */ . . return 0; }

&

VC

BB

ấ ư

ố ượ

ữ ủ C p l u tr  c a các đ i t

ng

 Ví d : Bi n Extern

int i = 1; in();

ế ụ void in(); void main() { void in(); void main() {

extern i = 1; in();

} void in() {

} void in() {

cout << i ;

cout << i ;

}

Lỗi (cú pháp) vì i là biến cục bộ trong main(), trong in() không nhận biết i, nếu trong hoặc trước in() khai báo thêm i thì lỗi ngữ nghĩa (tức chương trình in giá trị i khác không theo ý muốn của lập trình viên).

5757

}

&

VC

BB

ấ ư

ố ượ

ữ ủ C p l u tr  c a các đ i t

ng

 Ví dụ: Biến Extern

/* program2.cpp */ void in() {

Giả thiết 2 chương trình trên nằm trong 2 tệp khác nhau. Để liên kết (link) biến i giữa 2 chương trình cần định nghĩa tổng thể i trong một và khai báo extern trong chương trình kia.

extern i; cout << i ;

/* program1.cpp*/ void in(); int i; void main() {

}

i = 1; in();

5858

}

&

VC

BB

ấ ư

ố ượ

ữ ủ C p l u tr  c a các đ i t

ng

5959

ắ ề ấ ư Tóm t t v  c p l u tr  bi n ( ữ ế Storage class)

&

VC

Các ch  ỉ th  ị tiền x  ử lý

BB

a. Chỉ thị bao hàm tệp #include  Cho phép ghép nội dung các tệp đã có khác vào chương trình trước khi dịch. Các tệp cần ghép thêm vào chương trình thường là các tệp chứa khai báo nguyên mẫu của các hằng, biến, hàm … có sẵn trong C hoặc các hàm do lập trình viên tự viết.

 Có hai dạng viết chỉ thị này.

1: #include

Các tập tin nguyên mẫu của thư viện C++, chứa trong thư mục Borlandc\Include

2: #include “đường dẫn\tệp”

6060

Tìm tệp theo đường dẫn, nếu không có đường dẫn sẽ tìm trong thư mục hiện tại. Tệp thường là các tệp (thư viện) được tạo bởi lập trình viên và được đặt trong cùng thư mục chứa chương trình.

&

VC

Các ch  ỉ th  ị tiền x  ử lý

BB

#define tên_macro xaukitu

b. Chỉ thị macro #define  Cú pháp:  Trước khi dịch bộ tiền xử lý sẽ tìm trong chương trình và thay thế bất kỳ vị trí xuất hiện nào của tên_macro bởi xâu kí tự. Ta thường sử dụng macro để định nghĩa các hằng hoặc thay cụm từ này bằng cụm từ khác dễ nhớ hơn.

if (i < MAX) then begin

Viết

Ok = TRUE; cout << i ;

end

if (i < 100 then {

 Ví dụ:

Ct dịch

Ok = 1; cout << i ;

}

6161

#define then // thay then bằng dấu cách #define begin { // thay begin bằng dấu { #define end } // thay end bằng dấu } #define MAX 100 // thay MAX bằng 100 #define TRUE 1 // thay TRUE bằng 1

&

VC

Các ch  ỉ th  ị tiền x  ử lý

BB

c. Các chỉ thị biên dịch có điều kiện #if, #ifdef, #ifndef  Chỉ thị:

#if dãy lệnh … #endif #if dãy lệnh … #else dãy lệnh … #endif,

 Báo cho chương trình dịch biết đoạn lệnh giữa #if (điều kiện) và

#endif chỉ được dịch nếu điều kiện đúng.

const int M = 10; void main() { int i = 5; #if M > 8

cout << i+i ;

 Ví dụ:

#else

const int M = 1; void main() { int i = 5; #if M ==1

cout << i*i ;

cout << i ;

#endif

}

#endif

6262

}

&

VC

Các ch  ỉ th  ị tiền x  ử lý

BB

d. Chỉ thị #ifdef và #ifndef  Chỉ thị này báo cho chương trình dịch biết đoạn lệnh có được dịch

hay không khi một tên gọi đã được định nghĩa hay chưa.

 Để định nghĩa một tên gọi ta dùng chỉ thị #define tên.  Chỉ thị này đặc biệt có ích khi chèn các tệp thư viện vào để sử

6363

dụng. Một tệp thư viện có thể được chèn nhiều lần trong văn bản do vậy nó có thể sẽ được dịch nhiều lần, điều này sẽ gây ra lỗi vì các biến được khai báo nhiều lần.

&

VC

Các ch  ỉ th  ị tiền x  ử lý

BB

d. Chỉ thị #ifdef và #ifndef  Thư viện 1. tên tệp: MYLIB.H

ươ

int max(int a, int b) { return (a>b? a: b); }

 Thư viện 2. tên tệp: MATHFUNC.H

>> b >> c;

ậ Hàm  main  c a  chúng  ta  nh p  3  ặ ố ủ ừ ố s , in ra max c a t ng c p s  và  ố ả ủ ng  trình  max  c a  c   3  s .  Ch ư ệ ả ử ụ ầ c n ph i s  d ng c  2 th  vi n.        #include "mylib.h"        #include "mathfunc.h"        main()       {             int a, b, c;             cout << "a, b, c = " ; cin >> a

cout << max(a,b) << max(b,c)  << max(a,c) << max(a,b,c) ;

#include "mylib.h" int max(int a, int b) { return (a>b? a: b); }

 C++ sẽ báo lỗi (do hàm int max(inta, int b) được khai báo hai lần

6464

}

&

VC

Các ch  ỉ th  ị tiền x  ử lý

BB

// tệp mylib.h #ifndef _MYLIB_ // nếu chưa định nghĩa tên gọi _MYLIB_ #define _MYLIB_ // thì định nghĩa nó int max(int a, int b) // và các hàm khác {

return (a>b? a: b);

} #endif

6565

Khắc phục

&

VC

BB

ậ   Câu h i và bài t p

1. Nêu cách khai báo hàm, định nghĩa hàm, cách gọi hàm. 2. Phạm vi của một đối tượng (biến, hằng) trong chương trình ? 3. Trình bày các phương pháp truyền tham số cho hàm (truyền

bằng giá trị, bằng tham chiếu, và bằng tham trỏ)

4. Nêu cách thiết kế hàm mà theo Anh (Chị) cho là đạt yêu cầu. 5. Cho ví dụ về hàm xuất/nhập. 6. Cho ví dụ về hàm kiểm tra một giá trị nguyên thỏa tính chất “P”

nào đó.

7. Cho ví dụ về hàm xác định giá trị nguyên thỏa tính chất “P” nào

đó.

6666

8. Trình bày cách tổ chức một chương trình “C/C++”.

&

VC

BB

ậ   Câu h i và bài t p

8. Trình bày cấp lưu trữ của một đối tượng (auto, register,

static, extern).

− Giải phương trình bậc 2 ax2 + bx + c = 0 − In bảng cửu chương theo chiều dọc, ngang. − Kiểm tra 1 bộ ngày, tháng, năm có hợp lệ hay không ? − Vẽ hình tam giác với chiều cao h dạng … − Phân tích số n > 0 thành tích các thừa số nguyên tố theo

9. Khai báo các hàm nguyên mẫu sau:

dạng n = 120 = 2*2*2*3*5.

6767

− Kiểm tra số tự nhiên n > 0 có phải là số nguyên tố ? − Tính trị max của 2 số nguyên. − Tính trị min của 2 số nguyên. − Tính USCLN của 2 số tự nhiên.

&

VC

BB

ậ   Câu h i và bài t p

10 Chọn câu sai trong các câu sau đây:

A: Hàm không trả lại giá trị thì không cần khai báo kiểu giá trị

của hàm.

B: Các biến được khai báo trong hàm là cục bộ, tự xoá khi hàm

thực hiện xong

C: Hàm không trả lại giá trị sẽ có kiểu giá trị ngầm định là void. D: Hàm là đơn vị độc lập, không được khai báo hàm lồng nhau.

11 Chọn câu đúng nhất trong các câu sau đây:

A: Hàm phải được kết thúc với 1 câu lệnh return B: Phải có ít nhất 1 câu lệnh return cho hàm C: Các câu lệnh return được phép nằm ở vị trí bất kỳ trong thân

hàm

D: Không cần khai báo kiểu giá trị trả lại của hàm nếu hàm

6868

không có lệnh return

&

VC

Câu hỏi và bài tập

BB

12. Chọn câu sai trong các câu sau đây:

A: Số tham số thực sự phải bằng số tham số hình thức trong lời

gọi hàm

B: Các biến cục bộ trong thân hàm được chương trình dịch cấp

phát bộ nhớ

C: Các tham số hình thức sẽ được cấp phát bộ nhớ tạm thời khi

hàm được gọi

D: Kiểu của tham số thực sự phải bằng kiểu của tham số hình

thức tương ứng với nó trong lời gọi hàm

13. Để thay đổi giá trị của tham biến, các đối của hàm cần khai

6969

báo dưới dạng: A: biến bình thường và tham đối được truyền theo giá trị B: biến con trỏ và tham đối được truyền theo giá trị C: biến bình thường và tham đối được truyền theo địa chỉ D: biến tham chiếu và tham đối được truyền theo giá trị

&

VC

Câu hỏi và bài tập

BB

ế

ươ

ế ị

Hãy cho bi

ng tr

àn hình c a củ ác bi n x, y, v

à z c a củ ác ch

ình sau:

t tr  in ra m #include  void mul(int&,int,int&); int main( ) {

int x = 4, y = 3, z = 2; mul( y, z, x ); cout << "\nX = " << x; cout << "\nY = " << y; cout << "\nZ = " << z; return 0;

} void mul( int & x,int y, int & z ) {

x *= y; y *= z; z *= x;

}

7070

&

VC

BB

ậ   Câu h i và bài t p

ế

ươ

ế ị

Hãy cho bi

ng tr

àn hình c a củ ác bi n x, y, v

à z c a củ ác ch

ình sau:

t tr  in ra m #include  void f( int x, int & y, int z ); void g( int & x, int y, int & z ); int main() {

void f( int x, int & y, int z ) {

g( z, y, x ); x += y; y += z; z += x;

} void g( int & a, int b, int &  c ) {

int x = 2, y = 3, z = 4; f( y, z, x ); cout << "\nX = " << x; cout << "\nY = " << y; cout << "\nZ = " << z; return 0;

7171

a *= b; b *= c; c *= a; } }

&

VC

Bài t p th c hành

BB

5. Bài 4, 5, 6, 7, 8 trang 140-141 chương 8 (Câu lệnh

điều kiện và rẽ nhánh) a. Viết hàm đổi một ký tự hoa sang ký tự thường. b. Viết thủ tục giải phương trình bậc nhất. c. Viết thủ tục giải phương trình bậc hai. d. Viết hàm trả về giá trị nhỏ nhất của 4 số

nguyên.

e. Viết thủ tục hoán vị hai số nguyên. f. Viết thủ tục sắp xếp 4 số nguyên tăng dần.

7272

NMLT ­ Hàm (Function)

&

VC

Bài t p th c hành

BB

6. Bài tập 3 trang 155 chương 9 (Câu lệnh lặp). Hàm nhận vào một số nguyên dương n và thực hiện: a. Trả về số đảo của số đó. b. Có phải là số đối xứng (Trả về True/False) c. Có phải là số chính phương. d. Có phải là số nguyên tố. e. Tổng các chữ số lẻ. f. Tổng các chữ số nguyên tố. g. Tổng các chữ số chính phương.

7373

NMLT ­ Hàm (Function)

&

VC

Bài t p th c hành

BB

7. Bài tập 4 trang 156 chương 9 (Câu lệnh lặp). Hàm nhận vào một số nguyên dương n và thực hiện: a. S = 1 + 2 + … + n b. S = 12 + 22 + … + n2 c. S = 1 + 1/2 + … + 1/n d. S = 1 * 2 * … * n e. S = 1! + 2! + … + n!

7. Hàm trả về USCLN của 2 số nguyên. In ra n phần tử của dãy Fibonacy. 8.

7474

NMLT ­ Hàm (Function)