Bài giảng Tin học đại cương - Phần 2: Lập trình bằng ngôn ngữ C - Bài 5: Hàm - Nguyễn Thanh Hùng

Khái niệm hàm

Còn được gọi là chương trình con

Những đoạn chương trình lặp đi lặp lại nhiều lần ở những chỗ khác nhau:

 Viết thành hàm để khi cần chỉ cần gọi ra chứ không phải viết lại toàn bộ.

Ví dụ:

Các hàm toán học: sin(x), pow(x,y), sqrt(x),.

Các hàm do người dùng viết ra.

Giải quyết một bài toán lớn thì chương trình của ta có thể rất lớn và dài  Chia thành các công việc nhỏ hơn được viết thành các hàm  Dễ viết, kiểm tra và sửa lỗi.

Việc chia nhỏ một chương trình thành các chương trình con đảm nhận những công việc nhỏ khác nhau chính là tư tưởng chính cho phương pháp lập trình cấu trúc (structured programming).

 

ppt 46 trang kimcuc 7920
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Tin học đại cương - Phần 2: Lập trình bằng ngôn ngữ C - Bài 5: Hàm - Nguyễn Thanh Hùng", để tải tài liệu gốc về máy hãy click vào nút Download ở trên

Tóm tắt nội dung tài liệu: Bài giảng Tin học đại cương - Phần 2: Lập trình bằng ngôn ngữ C - Bài 5: Hàm - Nguyễn Thanh Hùng

Bài giảng Tin học đại cương - Phần 2: Lập trình bằng ngôn ngữ C - Bài 5: Hàm - Nguyễn Thanh Hùng
1 
TIN HỌC ĐẠI CƯƠNG  PHẦN 2: LẬP TRÌNH BẰNG NGÔN NGỮ C BÀI 5: HÀM 
VIỆN CÔNG NGHỆ THÔNG TIN 
SCHOOL OF INFORMATION COMMUNICATION TECHNOLOGY 
Ts. Nguyễn Thanh Hùng 
2 
BÀI 5:	HÀM 
5.1. Khái niệm hàm 
5.2. Khai báo và sử dụng hàm 
5.3. Phạm vi biến 
5.4. Nguyên mẫu hàm 
5.5. Hàm đệ qui 
3 
5.1. Khái niệm hàm 
Còn được gọi là chương trình con 
Những đoạn chương trình lặp đi lặp lại nhiều lần ở những chỗ khác nhau: 
 Viết thành hàm để khi cần chỉ cần gọi ra chứ không phải viết lại toàn bộ. 
Ví dụ: 
Các hàm toán học: sin(x), pow(x,y), sqrt(x), ... 
Các hàm do người dùng viết ra. 
4 
5.1. Khái niệm hàm 
Giải quyết một bài toán lớn thì chương trình của ta có thể rất lớn và dài Chia thành các công việc nhỏ hơn được viết thành các hàm Dễ viết, kiểm tra và sửa lỗi. 
Việc chia nhỏ một chương trình thành các chương trình con đảm nhận những công việc nhỏ khác nhau chính là tư tưởng chính cho phương pháp lập trình cấu trúc ( structured programming ). 
5 
BÀI 5:	HÀM 
5.1. Khái niệm hàm 
5.2. Khai báo và sử dụng hàm 
5.3. Phạm vi biến 
5.4. Nguyên mẫu hàm 
5.5. Hàm đệ qui 
6 
5.2.1. Khai báo hàm 
Cú pháp: 
[kieu_gia_tri_tra_ve] ([danh_sach_tham_so,]) 
{ 
//Than ham` bao gom: 
//Cac khai bao 
... 
//Cac cau lenh 
} 
7 
5.2.1. Khai báo hàm (tiếp) 
Ví dụ: 
long giai_thua(int a) 
{ 
 long ket_qua ; 
 int i; 
 ket_qua = 1; 
 for(i = 1;i<=a;i++) 
	 ket_qua = ket_qua * i; 
 if(a < 0) ket_qua = -1; 
 return ket_qua; 
} 
Dong dau ham 
Cac khai bao 
Cac cau lenh 
8 
5.2.1. Khai báo hàm (tiếp) 
Kiểu dữ liệu trả về của hàm: 
Kiểu dữ liệu của giá trị tính toán mà hàm trả về sau khi thực hiện. 
Hàm có thể có giá trị trả về hoặc không có giá trị trả về. 
Nếu có giá trị trả về, trong thân hàm có ít nhất một lệnh return . 
Nếu không có giá trị trả về cần khai báo cho hàm đó có kiểu trả về là void . 
9 
5.2.1. Khai báo hàm (tiếp) 
Tên hàm 
Có thể là bất kì một định danh hợp lệ nào. 
Thường mang nghĩa gợi ý chức năng công việc mà hàm thực hiện. 
Ví dụ: Một hàm có chức năng tính và trả về bình phương của một số thực x thì nên có tên là binh_phuong . 
Các hàm không được đặt tên trùng nhau. 
10 
5.2.1. Khai báo hàm (tiếp) 
Tham số của hàm: 
Các thông tin cần cho hoạt động của hàm và các thông tin, kết quả tính toán được hàm trả lại. 
Tham số chứa dữ liệu vào cung cấp cho hàm 
Tham số chứa dữ liệu ra mà hàm tính toán được. 
Tham số trong lời khai báo hàm được gọi là tham số hình thức, tham số giả định của hàm. 
Cần chỉ ra tên của tham số và kiểu dữ liệu của tham số. 
Một hàm có thể không có tham số, hoặc có nhiều tham số. 
11 
5.2.1. Khai báo hàm (tiếp) 
Lệnh return 
Cú pháp: 
return bieu_thuc; 
Khi gặp lệnh này, chương trình sẽ tính toán giá trị của bieu_thuc , lấy kết quả tính toán được làm giá trị trả về cho lời gọi hàm rồi kết thúc việc thực hiện hàm, trở về chương trình đã gọi nó. 
Nếu thiếu bieu_thuc Kết thúc việc thực hiện hàm mà không trả về giá trị nào cả. 
12 
Ví dụ về các hàm trong thư viện Math.h 
13 
5.2.2. Sử dụng hàm 
Sử dụng hàm hay gọi hàm Cú pháp: 
Ten_ham([danh_sach_doi_so]) 
Tham số được cung cấp cho hàm trong quá trình thực hiện được gọi là tham số thực. 
Kiểu dữ liệu của tham số hình thức và tham số thực phải giống nhau. 
14 
Ví dụ 
#include 
#include 
int max(int x, int y, int z) 
{ 
	int max; 
	max = x>y?x:y; 
	max = max>z?max:z; 
	 return max; 
} 
void main() 
{ 
	int a,b,c; clrscr(); 
	printf("\n Nhap gia tri cho 3 so nguyen a, b, c: "); 
	scanf("%d %d %d",&a,&b,&c); 
	printf("\n Gia tri cac so vua nhap: "); 
	printf(" a = %-5d b = %-5d c = %-5d“, a, b, c); 
	 printf("\n Gia tri lon nhat trong 3 so la %d",max(a,b,c)); 
	getch(); 
} 
15 
Lưu ý 
Trong chương trình, khi gặp một lời gọi hàm thì hàm bắt đầu thực hiện bằng cách chuyển các lệnh thi hành đến hàm được gọi. Quá trình diễn ra như sau: 
Nếu hàm có tham số, trước tiên các tham số sẽ được gán giá trị thực tương ứng . 
Chương trình sẽ thực hiện tiếp các câu lệnh trong thân hàm bắt đầu từ lệnh đầu tiên đến câu lệnh cuối cùng. 
Khi gặp lệnh return hoặc dấu } cuối cùng trong thân hàm, chương trình sẽ thoát khỏi hàm để trở về chương trình gọi nó và thực hiện tiếp tục những câu lệnh của chương trình này. 
16 
#include 
#define KT 1000 
int nhap_so_pt() 
{ 
 int n; 
 do 
 { 
 printf("Nhap vao so phan tu cua mang: "); 
 scanf("%d", &n); 
 if (n KT) printf("Nhap sai\n"); 
 } while (n KT); 
 return n; 
} 
void hien_thi_mang(int *a, int n) 
{ 
 int i; 
 for (i = 0; i < n; i++) printf( "%4d", a[i]); 
} 
17 
void nhap_mang(int *a, int n) 
{ 
 int i; 
 for (i = 0; i < n; i++) 
 { 
	 printf("Nhap phan tu thu %d: ", i+1); 
	 scanf("%d", &a[i]); 
 } 
} 
void sap_xep_mang(int *a, int n) 
{ 
 int i, j, temp; 
 for (i=0; i<n-1; i++) 
	 for (j=i+1; j<n; j++) 
	 if (a[i] < a[j]){ 
	 temp=a[i]; a[i] = a[j]; a[j] = temp; 
 } 
} 
18 
void main() 
{ 
 int a[KT]; int n; 
 clrscr(); 
 n = nhap_so_pt(); 
 nhap_mang(a, n); 
 printf("Mang theo thu tu ban dau\n"); 
 hien_thi_mang(a, n); 
 sap_xep_mang(a, n); 
 printf("\nMang theo thu tu giam dan\n"); 
 hien_thi_mang(a, n); 
 getch(); 
} 
19 
Viết hàm để hoán đổi giá trị hai biến? 
void trao_doi(int so1, int so2) 
{ 
	int temp; 
 temp = so1; so1 = so2; so2 = temp; 
} 
void sap_xep_mang(int *a, int n) 
{ 
 int i, j, temp; 
 for (i=0; i<n-1; i++) 
	 for (j=i+1; j<n; j++) 
	 if (a[i] < a[j]) 
	 trao_doi(a[i], a[j]); 
} 
20 
Gọi hàm: tham chiếu và tham trị 
Khi gọi hàm cần truyền đối số (tham số) cho hàm. 
2 phương pháp truyền giá trị: 
Tham chiếu (biến) 
Tham trị 
21 
Gọi hàm: tham chiếu và tham trị 
Gọi theo tham trị (Call by value) 
Bản sao của đối số được truyền cho hàm 
Sử dụng khi không muốn thay đổi giá trị tham số truyền vào 
Gọi hàm tham trị loại bỏ các thay đổi ngoài ý muốn lên các tham số 
Gọi hàm tham biến (Call by reference) 
Truyền cho hàm biến gốc ( không phải bản sao ) 
 Truyền địa chỉ và sử dụng con trỏ 
Thay đổi giá trị của đối số trong hàm sẽ ảnh hưởng hoặc thay đổi trực tiếp lên biến gốc 
22 
Viết hàm để hoán đổi giá trị hai biến? 
void trao_doi( int *so1, int *so2 ) 
{ 
	int temp; 
 temp = *so1; *so1 = *so2; *so2 = temp; 
} 
void sap_xep_mang(int *a, int n) 
{ 
 int i, j; 
 for (i=0; i<n-1; i++) 
	 for (j=i+1; j<n; j++) 
	 if (a[i] < a[j]) 
	 trao_doi(&a[i], &a[j]); 
} 
23 
#include 
#define KT 1000 
void nhap_mang(int *a, int *n) 
{ 
 int i; 
 do 
 { 
 printf("Nhap so phan tu cua mang: "); 
 scanf("%d", n); 
 if (*n KT) 
	 printf("Nhap sai\n"); 
 } while (*n KT); 
 for (i = 0; i < *n; i++) 
 { 
	 printf("Nhap phan tu thu %d: ", i+1); 
	 scanf("%d", &a[i]); 
 } 
} 
24 
void hien_thi_mang(int *a, int n) 
{ 
 int i; 
 for (i = 0; i < n; i++) printf( "%4d", a[i]); 
} 
void trao_doi(int *so1, int *so2) 
{ 
	int temp; 
 temp = *so1; *so1 = *so2; *so2 = temp; 
} 
void sap_xep_mang(int *a, int n) 
{ 
 int i, j; 
 for (i=0; i<n-1; i++) 
	 for (j=i+1; j<n; j++) 
	 if (a[i] < a[j]) 
	 trao_doi(&a[i], &a[j]); 
} 
25 
void main() 
{ 
 int a[KT]; int n; 
 clrscr(); 
 nhap_mang(a, &n); 
 printf("Mang theo thu tu ban dau\n"); 
 hien_thi_mang(a, n); 
 sap_xep_mang(a, n); 
 printf("\nMang theo thu tu giam dan\n"); 
 hien_thi_mang(a, n); 
 getch(); 
} 
26 
BÀI 5:	HÀM 
5.1. Khái niệm hàm 
5.2. Khai báo và sử dụng hàm 
5.3. Phạm vi biến 
5.4. Nguyên mẫu hàm 
5.5. Hàm đệ qui 
27 
5.3. Phạm vi biến 
Biến địa phương (Local Variable): 
Là các biến được khai báo trong lệnh khối hoặc trong thân chương trình con. 
Biến toàn cục (Global Variable): 
Là biến được khai báo trong chương trình chính. 
Vị trí khai báo của biến toàn cục là sau phần khai báo tệp tiêu đề và khai báo hàm nguyên mẫu 
28 
5.3. Phạm vi biến (tiếp) 
#include 
void main() 
{ 
	{ 
	int a = 1; 
	printf( “ \n a = %d ” ,a); 
	{ 
	int a = 2; 
	printf( “ \n a = %d ” ,a); 
	} 
	printf( “ \n a = %d ” ,a); 
	} 
	{ 
	int a = 3; 
	printf( “ \n a = %d ” ,a); 
	} 
	getch(); 
} 
29 
Ví dụ 2 
#include 
#include 
int a, b, c; 
int tich() 
{ 
	printf("\n Gia tri cac bien tong the a, b, c: "); 
	printf(" a = %-5d b = %-5d c = %-5d“, a, b, c); 
	 return a*b*c; 
} 
void main() 
{ 
	clrscr(); 
	printf("\n Nhap gia tri cho 3 so nguyen a, b, c: "); 
	scanf("%d %d %d",&a,&b,&c); 
	printf("\n Tich cua 3 so la %d",tich()); 
	getch(); 
} 
30 
Biến register 
Thanh ghi có tốc độ truy nhập nhanh hơn so với các loại bộ nhớ khác (RAM, bộ nhớ ngoài). 
N ếu một biến thường xuyên sử dụng được lưu vào trong thanh ghi thì tốc độ thực hiện của chương trình sẽ được tăng lên. 
Để làm điều này ta đặt từ khóa register trước khai báo của biến đó. 
Ví dụ: 	 register int a; 
Số lượng và kích thước các thanh ghi có hạn Số lượng biến khai báo register sẽ không nhiều và thường chỉ áp dụng với những biến có kích thước nhỏ như kiểu char , int . 
31 
Biến static 
Một biến cục bộ khi ra khỏi phạm vi của biến đó thì bộ nhớ dành để lưu trữ biến đó sẽ được giải phóng . 
Nếu cần lưu giá trị của các biến cục bộ này , cần khai báo biến với từ khóa static . 
Ví dụ : 	 static int a; 
Biến static là biến tĩnh , nghĩa là nó sẽ được cấp phát một vùng nhớ thường xuyên từ lúc khai báo và chỉ giải phóng khi chương trình chính kết thúc . 
32 
Ví dụ 
# include 
# include 
void fct() 
{ 
	static int count = 1; 
	printf("\n Lan goi ham fct lan thu %2d",count++); 
} 
void main() 
{ 
	int i; 
	for(i=0; i<10; i++) 
	fct(); 
	getch(); 
} 
33 
BÀI 5:	HÀM 
5.1. Khái niệm hàm 
5.2. Khai báo và sử dụng hàm 
5.3. Phạm vi biến 
5.4. Nguyên mẫu hàm 
5.5. Hàm đệ qui 
34 
Nguyên mẫu hàm – Ví dụ 
#include 
#include 
int max(int, int, int);	// khai bao nguyen mau ham 
void main() 
{ 
	int a,b,c; clrscr(); 
	printf("\n Nhap gia tri cho 3 so nguyen a, b, c: "); 
	scanf("%d %d %d", &a, &b, &c); 
	printf("\n Gia tri cac so vua nhap: "); 
	printf(" a = %-5d b = %-5d c = %-5d“,a,b,c); 
	printf("\n Gia tri lon nhat trong 3 so la %d",max(a,b,c)); 
	 getch(); 
} 
int max(int x, int y, int z) 
{ 
	int max; 	max = x>y?x:y; max = max>z?max:z; 
	return max; 
} 
35 
Nguyên mẫu hàm 
Nếu muốn đặt phần khai báo hàm nằm sau hàm main() Cần khai báo nguyên mẫu của hàm 
Để báo cho chương trình dịch biết có một hàm có dòng đầu hàm giống như trong phần nguyên mẫu này. 
Chương trình dịch có thể kiểm tra được là các lời gọi hàm trong chương trình chính có đúng hay không 
Có phù hợp về kiểu dữ liệu trả về hay không 
Các tham số thực có kiểu dữ liệu có phù hợp với kiểu dữ liệu đã khai báo hay không. 
Trong hàm nguyên mẫu có thể không cần nêu tên các tham số hình thức, nhưng trong phần khai báo hàm ta cần phải có các tham số hình thức. 
36 
BÀI 5:	HÀM 
5.1. Khái niệm hàm 
5.2. Khai báo và sử dụng hàm 
5.3. Phạm vi biến 
5.4. Nguyên mẫu hàm 
5.5. Hàm đệ qui 
37 
5.5. Hàm đệ quy	 
Khái niệm hàm đệ quy 
Hàm tự gọi chính mình 
Khi xây dựng hàm đệ quy cần: 
Xây dựng trường hợp cơ bản 
Nguyên lý đưa trường hợp tổng quát về trường hợp cơ bản 
Đảm bảo tính dừng của giải thuật đệ quy - chắc chắn từ trường hợp tổng quát sẽ đến được trường hợp cơ bản 
38 
5.5. Hàm đệ quy 	 
Ví dụ điển hình: tính giai thừa 
6! = 6 * 5 * 4 * 3 * 2 * 1 
Nguyên lý: 
6! = 6 * 5! 
5! = 5 * 4! ... 
Kết luận là có thể tính giai thừa theo phương pháp đệ quy 
Trường hợp cơ bản: ( 1! = 0! = 1 ) được định nghĩa 
2! = 2 * 1! = 2 * 1 = 2; 
3! = 3 * 2! = 3 * 2 = 6; 
39 
5.5. Hàm đệ quy 	 
(factorial 6) 
(6 * (factorial 5)) 
(6 * (5 * (factorial 4))) 
(6 * (5 * (4 * (factorial 3)))) 
(6 * (5 * (4 * (3 * (factorial 2))))) 
(6 * (5 * (4 * (3 * (2 * (factorial 1)))))) 
(6 * (5 * (4 * (3 * (2 * 1))))) 
(6 * (5 * (4 * (3 * 2)))) 
(6 * (5 * (4 * 6))) 
(6 * (5 * 24)) 
(6 * 120) 
720 
40 
Ví dụ hàm đệ quy: tính giai thừa 
#include 
long factorial(long number);// khai bao kieu mau ham 
void main() 
{ 
 int i; 
 for (i = 0; i <= 10; i++) 
 printf("%2d! = %ld\n", i, factorial(i)); 
} 
/* dung de quy dinh nghia ham factorial */ 
long factorial(long number) 
{ 
 if (number < 0) return (-1); 
 else if (number <= 1) return 1; 
 else 
 return (number * factorial(number - 1)); 
} 
41 
Ví dụ hàm đệ quy: Dãy số Fibonacci 
Dãy số Fibonacci: 0, 1, 1, 2, 3, 5, 8... 
Mỗi số trong dãy số Fibonacci có giá trị là tổng của hai số đứng trước nó trong dãy 
Công thức tổng quát của dãy số Fibonacci 
fib(n) = fib(n - 1) + fib(n – 2) 
Hai số đầu tiên của dãy số Fibonacci có giá trị tương ứng 0 và 1: 
fib(0)=0 
fib(1)=1 
42 
Ví dụ hàm đệ quy: Dãy số Fibonacci 
Dãy số Fibonacci: 0, 1, 1, 2, 3, 5, 8... 
Giải thuật đệ quy để tính giá trị các số trong dãy Fibonacci: 
 long fibonacci(long n) 
 { 
	if (n == 0 || n == 1) //Truong hop co ban 
	return n; 
	else 
 return 
 fibonacci(n - 1) + fibonacci(n – 2); 
} 
43 
Ví dụ hàm đệ qui: Tìm kiếm nhị phân 
Trên mảng đã sắp xếp tăng dần hoặc giảm dần 
Nếu giá trị cần tìm > giá trị của phần tử đầu tiên và nhỏ hơn giá trị của phần tử trong mảng: 
So sánh phần tử giữa mảng với giá trị cần tìm 
Nếu bằng, tìm thấy và kết thúc 
Nếu giá trị cần tìm < giá trị giữa , tìm trong nửa trước của mảng 
Nếu giá trị cần tìm > giá trị giữa , tìm trong nửa sau của mảng 
Lặp lại cho tới khi tìm thấy hoặc đã duyệt qua hết các nửa 
Mỗi lần như vậy ta loại bỏ được một nửa số phần tử đang xét - tìm kiếm nhị phân 
 Giải thuật này sẽ thực hiện tìm kiếm rất nhanh 
44 
#include 
#define KT 20 
void main() 
{ 
	int ds[KT] = {1, 4, 8, 9, 18, 27, 38, 49, 55, 59, 67,68, 69, 72, 75, 79, 87, 88, 97, 98}; 
 int cs_min, cs_max; /* Bien luu chi so cua ptu dau 	va ptu cuoi trong mang */ 
 int gtri_tim; // gia tri can tim kiem 
 int cs; // chi so 
 scanf( “ Nhap gia tri can tim: %d ” , & gtri_tim); 
 minindex = 0; // Chi so cua phan tu dau tien 
 maxindex = KT-1; // Chi so cua phan tu cuoi cung 
45 
 while (cs_min < cs_max) 
 { 
	 cs = (cs_max + cs_min)/2; 
 if (ds[cs]==gtri_tim) //Neu tim thay thi dung 
 { 
	cs_min = cs_max; break; 
 } 
 if (gtri_tim > ds[cs]) // Khoang sau 
 { 
	cs_min = cs + 1; 
	 } 
 else{ 
	cs_max = cs - 1; 
	 } //Khoang truoc 
 } 
 if (cs_min == cs_max){ 
	 printf( “ Chi so cua phan tu can tim la:%d ” , cs); 
 } 
} 
46 
Câu hỏi? 

File đính kèm:

  • pptbai_giang_tin_hoc_dai_cuong_phan_2_lap_trinh_bang_ngon_ngu_c.ppt