Tải bản đầy đủ (.pdf) (34 trang)

Bài giảng Ngôn ngữ lập trình C - Chương 6: Hàm và cấu trúc chương trình

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (283.27 KB, 34 trang )

CHƯƠNG VI
HÀM VÀ CẤU TRÚC CHƯƠNG TRÌNH
I.
1.

Hàm
Quy tắc xây dựng một hàm:
Hàm  có  thể  xem  là  một  đơn  vị  độc  lập  của 
chương  trình.  Các  hàm  có  vai  trò  ngang  nhau,  vì 
vậy không cho phép xây dựng một hàm bên trong 
một hàm khác.
Dòng đầu tiên (của một hàm) chứa các thông tin về 
hàm:

­
­
­

Kiểu giá trị của hàm (nếu hàm có giá trị)
Tên hàm
Danh sách các đối số (nếu có)


Các dòng tiếp theo dùng để khai báo kiểu giá 
trị của đối số.Và bắt buộc phải khai báo kiểu 
giá trị cho tất cả các đối số.
Tiép theo là thân hàm. Thân hàm là nội dung 
chính của hàm nó bắt đầu bằng dấu { và kết 
thúc }
Trong thân hàm có thể dùng 1 hoặc nhiều lệnh 
return hoặc có thể không dùng. Và có thể đặt 


chúng ở bất kỳ chỗ nào nếu thấy thích hợp.
Cú pháp chung của lệnh return
return ([Biểu thức]);
Giá trị của biểu thức trong ngoặc sẽ được 
gán cho hàm.


2. Quy tắc hoạt động của hàm
Cách gọi hàm:
tên_hàm([Danh sách tham số thực]);
Chú ý: 
­ Số  tham  số  thực  phải  bằng  với  số  tham 
số hình thức (đối) và mỗi tham số thực phải 
có cùng kiểu với giá trị như kiểu giá trị của 
đối tương ứng của nó.
­ Về  nguyên  tắc  mọi  hàm  cần  được  khái 
báo  trước  khi  sử  dụng  nó.  Nó  hoàn  toàn 
giống với việc khai báo một biến.


Ví dụ:
Viết chương trình tìm số lớn nhất và nhỏ nhất 
của từng cột trong ma trận, có sử dụng hàm tìm 
max, tìm min.
#include "stdio.h"
int max(a,b)
int a,b;
{
int m;
m=a>b?a:b;

return (m);
}


int min(a,b)
int a,b;
{
int m;
m=areturn (m);
}
main()
{
int s,k,i,j,ma,mi,max(),min(),temp;
int a[3][3];
clrscr();


 
 
  
  
  
 

 
 
 

for (i=0;i<3;++i)

for (j=0;j<3;++j)
{
printf("a[%d,%d] ",i,j);
scanf("%d",&temp);
a[i][j]=temp;
}
for (i=0;i<3;++i)
 {
 for (j=0; j<3;++j) printf(" %10d",a[i][j]);
 printf("\n");
}


for (j=0;j<3;++j)
 {
  ma=mi=a[0][j];
  for (i=0; i<3;++i)
  {
  mi=min(a[i][j],mi);
  ma=max(a[i][j],ma);
  }
  printf("\n Cot %d   Max = %d \Min = %d",i,ma,mi);
 }
getch();
return 0;
}


3. Các khái niệm liên quan đến hàm:
­ Tên hàm

­ Kiểu giá trị của hàm
­ Đối hay tham số hình thức
­ Thân hàm
­ Khái báo hàm
­ Lời gọi hàm
­ Tham số thực


4. Cách xây dựng hàm
[type] tên_hàm([Danh sách đối số])
[Khai báo kiểu giá trị cho tất cả các đối]
{
[Các khai báo kiểu giá trị cho các biến cục bộ và  các 
hàm nó sử dụng]
<Các câu lệnh>
[return ([Biểu thức]);]
}
Chú ý: 
­ Khi  xây  dựng  hàm  cần  nắm  vững  những  qui  định 
về mối quan hệ giữa: tham số thực và tham số hình 
thức (đối) cũng như các đối trong thân của hàm


­ Đối với hàm không cho giá trị thì chúng ta 
không cần khai báo kiểu giá trị của nó.
­ Đối  với  các  hàm  có  giá  trị  mà  ta  quên 
không khai báo kiểu giá trị của nó, thì máy 
sẽ  coi  hàm  đó  có  giá  trị  nguyên.  Như  vậy 
đối  với  hàm  có  gái  trị  kiểu  nguyên  thì 
không cần khai báo kiểu giá trị cho chúng.

­ Khi gặp lệnh return có chứa biểu thức, thì 
giá  trị  của  biểu  thức  bao  giờ  cũng  được 
chuyển về theo kiểu giá trị của hàm trước 
khi nó được gán cho hàm.


 Nguyên tắc hoạt động của tham số thực, các đối và các 
biến cục bộ
­ Do đối và biến cục bộ đều có phạm vi hoạt động trong 
cùng một hàm nên  đối và biến cục bộ cần có tên khác 
nhau.
­ Đối và biến cục bộ  đều là biến tự  động. Chúng  được 
cung cấp bộ nhớ khi hàm  được khởi  động và chúng sẽ 
lập tức biến mất khi máy ra khỏi hàm. Như vậy, không 
thể mang giá trị của đối ra khỏi hàm. Điều này có nghĩa 
là  không  thể  sử  dụng  đối  để  làm  thay  đổi  giá  trị  của 
bất kỳ một đại lượng nào ở ngoài hàm.
­ Khi một hàm  được gọi tới, việc  đầu tiên là gái trị của 
các tham số thực  được gán cho các  đối. Như  vậy, các 
đối chính là bản sao của các tham số thực. Hàm chỉ làm 
vcệc trên các  đối, tức là chỉ làm việc trên các bản sao 
này. Các đối có tể bị biến  đổi nhưng các tham số thực 
(các bản chính) không hề bị thay đổi


II.
1.

Con trỏ và địa chỉ
Đia chỉ

Liên quan đến một biến ta đã có các khái niệm:
­ Tên biến
­ Kiểu giá trị của biến
­ Giá trị của biến
Khi khai báo một biến thì máy sẽ cấp phát cho 
biến một vùng nhớ có số byte bằng với  độ lớn 
của kiểu đó. 
Ví dụ: 
Kiểu int là 2 byte
Kiểu float là 4 byte


Chúng ta cũng có thể hiểu: Đị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 nhau mà máy dành cho biến.
Cần  chú  ý  rằng:  Địa  chỉ  của  biến  là  mộ  số 
nguyên  nhưng  không  được  đánh  đồng  nó  với  các 
số nguyên thông thường trong các phép tính
Phép toán
&x 
cho ta địa chỉ của biến x


2. Con trỏ 
Con trỏ là một biến dùng  để chứa  địa chỉ. Vì có 
nhiều  loại  địa  chỉ  nên  cũng  có  bấy  nhiêu  kiểu 
con trỏ tương ứng.
Ví dụ:
Con trỏ kiểu int dùng  để chứa  địa chỉ các 
biến kiểu int.

Cũng  như  biến  thì  con  trỏ  cũng  cần  phải  đựoc 
khai báo trước khi sử dụng.
Cú pháp khai báo:
type *tên_con_trỏ
  
Ví dụ:
int x,y,*px,*py


Toán tử: & và * là các toán tử một ngôi, nó chỉ tác động 
lên biến, phần tử của mảng hoặc chuỗi.
&: Toán tử lấy đại chỉ của biến
*: Toán tử lấy giá trị tại địa chỉ nào đó.
Các toán tử này có độ ưu tiên hơn các toán tử số học và 
có độ ưu tiên tương đương với toán tử một ngôi.
3. Các biểu thức con trỏ:
a. Phép gán con trỏ:
Con trỏ cũng là một biến nên ta cũng có thể áp dụng 
phép gán lên nó.
Ví dụ:
int *p1, *p2,x;
Lúc đó  các phép toán sau là hợp lệ:
p1=&x;
p2=p1;


b. Phép toán số học trên con trỏ:
Các phép toán số học được áp dụng trên biến con trỏ cũng 
như giá trị của nó là 2 phép toán cộng và trừ.
Ví dụ:

int  *p;
Thì ta có thể dùng:
p++: để trỏ đến phần tử kế tiếp;
p­­: trỏ đến phần tử trước đó
p= p+3: Nhảy đến địa chỉ cách p là 3*Sizeof(p)
Trong biểu thức ta có thể dùng các dạng sau của một biến 
con trỏ p:
(*p)++,++(*p):Tăng giá trị tại p lên 1
*(p++): lấy gía trị phần tử kế tiếp trỏ bởi p,...


c. So sánh con trỏ
Các phép toán so sánh địa chỉ của các biến con 
trỏ là:
>,<, = =
4. Kiểu giá trị trong khai báo:
Mọi thành phần của cùng một khai báo (biến, 
phần tử mảng, hàm, con trỏ) khi xuất hiện trong 
biểu thức đều có cùng một kiểu giá trị.
Ví dụ:
int a, b[5], f(), *p;
Thì a, b[i], f(x) hoặ *p xuất hiện trong một 
biểu  thức thì chúng luôn luôn cho một gia trị 
kiểu  float.


5. Hàm có đối con trỏ:
Nếu đối là con trỏ thì tham số thực tương ứng 
phải là địa chỉ của biến hoặc địa chỉ của phần tử 
mảng có kiểu tương ứng.

Khi đó địa chỉ của biến được truyền cho đối con 
trỏ tương ứng.
Ví dụ:


#include "stdio.h"
int swap(x,y)
int x,y;
{
int tem;
tem=x;
x=y;
y=tem;
return (x,y);
}


main()
{
int x,y,swap();
printf("Nhap x = \n y = ");
scanf("%d %d",&x,&y);
printf("x = %d    y = %d",x,y);
swap(x,y);
printf("x = %d    y = %d",x,y);
getch();
return 0;
}



#include "stdio.h"
swap(x,y)
int *x,*y;
{
int tem;
tem=*x;
*x=*y;
*y=tem;
}


main()
{
int x,y;
clrscr();
printf("Nhap x =  ");
scanf("%d",&x);
printf("\nNhap y = ");
scanf("%d",&y);
printf("x = %d    y = %d",x,y);
swap(&x,&y);
printf("\nx = %d    y = %d",x,y);
getch();
return 0;
}


6. Sử dụng biến con trỏ:
Trong  các  đối  của  hàm,  ta  có  thể  chia  thành  2 
loại:

­ Gồm  các  đối  dùng  để  chứa  các  giá  trị  đã 
biết.(Tham trị)
­ Gồm  các  đối  dùng  để  chứa  các  kết  quả 
mới nhận được (Tham biến)
Ví dụ:
Viết chương trình giải phuơng trình bậc hai có 
sử  
dụng  con  trỏ  để  xây  dựng  hàm  giải 
phương trình


#include "stdio.h"
#include "math.h"
int ptb2(a,b,c,x1,x2)
float a,b,c,*x1,*x2;
{
 float delta;
 if (a==0) return (0);
 delta=pow(b,2)­4*a*c;
 if (delta<0) return (­1);
 *x1=(­b+sqrt(delta))/(2*a);
 *x2=(­b­sqrt(delta))/(2*a);
 return (1);
}


main()
{
int s;
float a,b,c,x1,x2;

clrscr();
printf("Nhap cac gia tri cho he so");
scanf("%f%f%f",&a,&b,&c);
printf("\na = %6.2f   b = %6.2f   c = %6.2f",a,b,c);
s=ptb2(a,b,c,&x1,&x2);
if (s==0)
printf("\nKhong phai la phuong trinh bac 2 vi a=0");


×