Bài giảng Ngôn ngữ lập trình C - Hàm
Mục đích
Biết cách xây dựng các chương trình từ
các hàm
Cách tạo ra các hàm mới
Cơ cấu truyền thông tin giữa các hàm
Cách dùng và viết hàm đệ quy
Giới thiệu hàm toán học trong thư viện C
chuẩn
àm toán học trong thư viện C chuẩn Nội dung Khai báo và định nghĩa hàm Tham số trong lời gọi hàm Địa chỉ và con trỏ Con trỏ hàm Khái niệm Khai báo biến con trỏ hàm Tham số hình thức của hàm là con trỏ hàm Đệ quy Ví dụ /*func1.c*/ #include #include int square(int); void main() { int i; for (i=1; i<=10; i++) printf("%5d", square(i)); printf("\n"); getch(); } int square(int x) { int y; y = x*x; return y; } Nguyên mẫu của hàm Lời gọi hàm Định nghĩa hàm Khái niệm liên quan đến hàm Tên hàm Kiểu giá trị của hàm Khai báo hàm Thân hàm Lời gọi hàm Tham số hình thức (đối) Tham số thực Tên_hàm là tên hợp lệ Kiểu giá trị trả về là kiểu dữ liệu của kết quả trả lại cho hàm gọi nó Nếu là void thì hàm không trả lại giá trị Nếu không xác định kiểu giá trị trả về trình biên dịch sẽ ngầm định là int Danh sách tham số: mô tả kiểu dữ liệu cùng thứ tự của các tham số hàm nhận khi được gọi Nếu hàm không nhận tham số, danh sách tham số là void Cần ghi rõ kiểu của tham số, nếu không ghi được ngầm định là int Khai báo và định nghĩa hàm Khai báo hàm (nguyên mẫu của hàm): [kiểu giá trị trả về] Tên_hàm([danh sách tham số]); Ví dụ: int square(int); Định nghĩa hàm: [kiểu giá trị trả về] Tên_hàm([danh sách tham số]) { Các khai báo … (Thân hàm) Các câu lệnh } Định nghĩa hàm (tiếp) Các khai báo và câu lệnh trong cặp dấu { và } tạo thành thân hàm Khai báo và cài đặt một hàm không được đặt trong hàm khác Trả lại giá trị cho hàm: [return [biểu thức];] Có thể có nhiều câu lệnh return Giá trị của biểu thức trong câu lệnh return được gán cho hàm Có thể không sử dụng return return; ~ hàm không trả về giá trị (có thể không có) Ví dụ Hàm trả về giá trị là một số nguyên. Tham số là hai số nguyên int max(int a, int b) {…..} Hàm trả về giá trị là một con trỏ thực. Tham số là một số nguyên float *nhap(int n) {…..} Hàm trả về một số thực. Tham số là một biến mảng thực hoặc một con trỏ thực float sum(float *a) {…..} Hàm trả về giá trị là một số nguyên. Tham số là một mảng số thực 20 phần tử int count(float a[20]) {…..} Ý nghĩaĐịnh nghĩa hàm Hàm nguyên mẫu Thông báo cho trình biên dịch biết kiểu dữ liệu hàm trả lại, số lượng, kiểu và thứ tự của các tham số được truyền cho hàm Dùng để kiểm tra lời gọi hàm Không cần chỉ rõ tên của tham số hình thức Tham số trong lời gọi hàm Khái niệm Tham số hình thức: là các tham số được khai báo trong phần danh sách tham số trong định nghĩa hàm Tham số thực: các thông tin được truyền cho hàm trong các lời gọi hàm Mỗi tham số thực tương ứng với một tham số hình thức Kiểu dữ liệu của tham số hình thức quyết định kiểu giá trị của tham số thực Các bước xây dựng hàm: Khai báo kiểu hàm Đặt tên hàm Khai báo các đối Viết các câu lệnh Chú ý Hàm không cho giá trị thì dùng kiểu void Hàm không đối dùng void để khai báo đối Giá trị của biểu thức được chuyển kiểu phù hợp với kiểu của hàm trước khi được gán cho hàm Ví dụ - max #include #include float max(float, float); void main() { float a, b, c, d; printf("Nhap 4 so thuc:\n"); scanf("%f%f%f%f",&a,&b,&c,&d); printf("Max cua 4 so vua nhap la: %f",max(a,max(b,max(c,d)))); getch(); } float max(float x, float y) { return (x>y?x:y); } Truyền thông tin cho hàm Truyền theo trị Tạo ra một bản sao giá trị của tham số thực Giá trị của tham số thực không bị thay đổi Tham số thực có thể là biến, hằng, biểu thức Truyền theo tham biến Truyền trực tiếp giá trị tham số cho hàm được gọi (tham số hình thức và thực là một) Tham số thực bắt buộc phải là biến Giá trị của tham số thực có thể bị thay đổi Truyền tham số trong C Trong C, tất cả các tham số được truyền theo trị /*swap1.c*/ #include #include void swap(int x, int y); void main() { int x=3, y=4; clrscr(); printf("Gia tri truoc khi goi ham\n"); printf("%5d %5d\n",x,y); swap(x,y); printf("Sau khi goi ham\n"); printf("%5d %5d",x,y); getch(); } void swap(int x, int y) { int t; t = x; x = y; y = t; } Địa chỉ Các khái niệm liên quan đến biến Tên biến Kiểu biến Giá trị của biến Địa chỉ của biến là số thứ tự của byte đầu tiên trong một dãy các byte liên tiếp máy dành cho biến Phép toán lấy địa chỉ: & Con trỏ Khái niệm: con trỏ là một biến/hằng có giá trị là địa chỉ của một đối tượng khác Đối tượng: biến hoặc hàm Cho phép ta tham chiếu đến một biến thông qua địa chỉ Khai báo biến con trỏ Cú pháp: type *ptr_name type là kiểu dữ liệu của biến mà con trỏ chứa địa chỉ ptr_name là tên của biến trỏ type* là một kiểu dữ liệu con trỏ Biến trỏ chưa chỉ đến địa chỉ nào có giá trị NULL Tham số hình thức của hàm là con trỏ Tham số hình thức của hàm là con trỏ Tham số thực tương ứng phải là một địa chỉ Có thể thay đổi giá trị của biến với địa chỉ được truyền Ví dụ #include "stdio.h" #include "conio.h" void swap(float *x, float *y) { float t; t = *x; *x = *y; *y = t; } main() { float a=3, b=4; clrscr(); printf("Gia tri truoc khi thay doi\n%8.2f\t%8.2f\n",a,b); swap(&a,&b); printf("Gia tri sau khi thay doi\n%8.2f\t%8.2f\n",a,b); getch(); } Kết quả Khi nào sử dụng đối con trỏ Con trỏ kiểu int (float, double) Địa chỉ kiểu int (float, double) Biến kiểu int (float, double) Giá trị kiểu int (float, double) Đối tương ứngTham số thực Ví dụ void nhap(int *k) { printf("Nhap "); scanf("%d",k); } void show(int k) { printf("\n%d\n",k); getch(); } void swap1(int i, int j){ int temp; temp = i; i = j; j = temp; } void swap2(int *i, int *j){ int temp; temp = *i; *i = *j; *j = temp; } void main(){ int n,m; nhap(&n); nhap(&m); show(n); show(m); printf("\nswap1\n"); swap1(n,m); printf("%d\t%d",n,m); printf("\nswap2\n"); swap2(&n,&m); printf("%d\t%d",n,m); getch(); } Kết quả Ví dụ #include #include void nhap(char *c) { printf("Nhap "); fflush(stdin); scanf("%c",c); } void show(char c) { printf("%c\n",c); } void upcase1(char c){ if (c>='a'&&c<='z') c = c - 32; } void upcase2(char *c){ if ((*c>='a')&&(*c<='z')) *c = *c - 32; } void main(){ char ch; clrscr(); nhap(&ch); show(ch); upcase1(ch); show(ch); upcase2(&ch); show(ch); getch(); } Kết quả Hàm đệ quy Khái niệm hàm đệ quy Cách dùng đệ quy Sử dụng đệ quy cho bài toán nào? Cách xây dựng hàm đệ quy Khái niệm hàm đệ quy Bên trong thân của hàm có lời gọi tới chính hàm đó Khi gọi đệ quy Máy tạo ra một tập các biến cục bộ độc lập với tập biến cục bộ đã được tạo ra trong các lần gọi trước Có bao nhiêu lần gọi tới hàm thì cũng có bấy nhiêu lần thoát ra khỏi hàm Cách dùng đệ quy Áp dụng cho lớp bài toán Dễ dàng giải quyết trong trường hợp riêng (trường hợp suy biến) Trường hợp tổng quát: Đưa về bài toán cùng dạng, tham số thay đổi Sau một số hữu hạn bước biến đổi, dẫn tới trường hợp suy biến Cách dùng đệ quy Cách xây dựng hàm đệ quy if (trường hợp suy biến) { Trình bày cách giải } else /*trường hợp tổng quát*/ { Gọi đệ quy tới hàm (đang lập) với giá trị khác của tham số } Ví dụ - chỉnh hợp, tổ hợp long giaithua(int); void main() { int n, k; printf("Nhap n, k= "); scanf("%d%d",&n,&k); printf("%n!=%ld\n",n,giaithua(n)); printf("%n!=%ld\n",n,giaithua(k)); printf("C(%d,%d)=%ld\n",n,k,giaithua(n)/(giaithua(n- k)*giaithua(k))); printf("A(%d,%d)=%ld",n,k,giaithua(n)/giaithua(n-k)); getch(); } long giaithua(int n) { if (n==1||n==0) return 1; else return (giaithua(n-1)*n); } Ví dụ - ước chung lớn nhất int ucln(int x, int y){ if (x==y) return x; else if (x>y) return ucln(x-y,y); else return ucln(x,y-x); } Con trỏ hàm Con trỏ hàm là con trỏ trỏ đến điểm xâm nhập vào hàm Có thể sử dụng thay cho tên hàm Cho phép các hàm cũng được truyền như là các tham số cho các hàm khác Khai báo biến con trỏ hàm Cú pháp: [kiểu giá trị] (*tên biến con trỏ hàm)([danh sách tham số]); Con trỏ hàm nhận giá trị là tên của các hàm có cùng kiểu giá trị trả về và kiểu giá trị của các tham số Ví dụ float (*f)(float) Khai báo f là con trỏ hàm kiểu float và có đối là float double (*g)(int, double) Khai báo g là con trỏ hàm kiểu double có các đối int và double Tác dụng của con trỏ hàm Chứa địa chỉ của hàm Thực hiện phép gán tên hàm cho con trỏ hàm Kiểu hàm và kiểu con trỏ phải tương thích Ví dụ #include #include float max(float x, float y){ return (x>y?x:y); } int main(){ float x = 3, y = 5; float (*f)(float, float) = max; printf("max=%f\n",f(x,y)); getch(); return 0; } Kết quả Đối con trỏ hàm Hàm có tham số thực trong lời gọi tới nó là tên của một hàm khác Tham số hình thức tương ứng phải là một con trỏ hàm Cách dùng Nếu đối được khai báo: float (*f)(float, int) Sử dụng trong thân hàm: f(x,n) hoặc (f)(x,n) hoặc (*f)(x,n) Ví dụ #include #include #include double tichphan(double (*f)(double), double a, double b) { double s, h; int i, n; n = 10000; h = (b-a)/n; s = (f(a)+f(b))/2; for (i=1; i<n; i++){ s = s + f(a+i*h); } return s*h; } double g(double x){ double s; s = (exp(x) - 2*sin(x*x)/(1+pow(x,4))); return s; } void main() { clrscr(); printf("TP1 = %f\n",tichphan(sin,0,M_PI/2)); printf("TP2 = %f\n",tichphan(cos,0,M_PI/2)); printf("TP3 = %f\n",tichphan(exp,0,1.0)); printf("TP4 = %f\n",tichphan(g,0,2.0)); getch(); } Kết quả Thư viện các hàm toán học cos(0.0)=1cos của xcos(x) tan(0.0)=0tan của xtan(x) sin(0.0)=0sin của x (x theo radian)sin(x) fmod(13.657,2.333)=1.992Phần dư của phép chia x cho yfmod(x,y) pow(2,7)=128x mũ ypow(x,y) floor(-9.8)=-10Làm tròn xuốngfloor(x) ceil(9.2)=10.0Làm tròn lênceil(x) fabs(x)=|x|Trị tuyệt đối của xfabs(x) log10(1.0)=0.0logarithm cơ số 10 của xlog10(x) log(2.718282)=1.0logarithm cơ số e của xlog(x) exp(1.0)=2.718282Hàm mũ exexp(x) sqrt(9.00)=3.0Căn bậc 2 của xsqrt(x) Ví dụMô tảHàm
File đính kèm:
- Bài giảng Ngôn ngữ lập trình C - Hàm.pdf