PH L C 4
HÀM V I Đ I S B T Đ NH TRONG C
Trong các giáo trình C th ng ch h ng d n cách xây d ngườ ướ
hàm v i các đ i c đ nh. M i đ i c n m t tham s (cùng ki u
v i nó) trong l i g i hàm. Tuy nhiên m t vài hàm chu n c a C l i
không nh v y, mà linh ho t h n, ch ng khi dùng hàm printf hayư ơ
scanf thì s tham s ta cung c p cho hàm không c đ nh c
v s l ng l n ki u cách. Ví d trong câu l nh: ượ
printf(“\n T ng = %d “ , 3+4+5) ;
có 2 tham s , nh ng trong câu l nh: ư
printf(“\n Hà N i“ ) ;
ch có m t tham s .
Nh v y c n phân bi t các khái ni m sau: ư
- Đ i s c đ nh đ c khai báo trong dòng đ u c a hàm, ượ
tên và ki u
- Tham s ng v i đ i s c đ nh g i là tham s c đ nh
- Đ i b t đ nh đ c khai báo b i ba d u ch m: b t đ nh c v ượ
s l ng và ki u ượ
- Tham s b t đ nh ( ng v i đ i b t đ nh) m t danh sách giá
tr v i s l ng và ki u tuỳ ý (không xác đ nh) ượ
Trong ph l c này s trình b y cách xây d ng các hàm v i đ i
s b t đ nh. Công c ch y u đ c dùng là con tr và danh sách. ế ượ
1. Bi n con tr ế
Bi n con tr (hay con tr ) ng đ ch a đ a ch c a bi n,ế ế
m ng, hàm, ... nhi u ki u đ a ch , v y cũng nhi u ki u
con tr . Bi n con tr đ c khai báo theo m u: ế ượ
Ki u *Tên_bi n_con_tr ; ế
Ví d :
float px ; // px là con tr th c
Các phép toán quan tr ng trên con tr g m:
+ Gán đ a ch m t vùng nh cho con tr (dùng toán t gán, phép
l y đ a ch , các hàm c p phát b nh )
+ Truy nh p vào vùng nh thông qua con tr , dùng phép toán:
*Tên_con_tr
ý đây 2 vùng nh : vùng nh c a bi n con tr vùng ế
nh mà đ a ch đ u c a nó ch a trong bi n con tr ) ế
+ C ng đ a ch đ con tr ch a đ a ch c a ph n t ti p theo, ế
dùng phép toán:
++ Tên_con_tr ho c Tên_con_tr ++
Chú ý r ng các phép toán trên ch th th c hi n đ i v i con
tr có ki u.
2. Danh sách không cùng ki u
Dùng con tr ki u ch qu n đ c m t danh sách giá tr ượ
cùng ki u, ví d d y s th c, d y s nguyên, d y các c u trúc,....
Khi c n qu n m t danh sách các giá tr không cùng ki u ta
ph i dùng con tr không ki u (void) khai báo nh sau: ư
void * Tên_con_tr ;
Con tr void th ch a các đ a ch ki u b t kỳ, dùng đ
tr đ n vùng nh ch a danh sách c n qu n lý. M t chú ý quan ế
tr ng m i khi g i vào hay l y ra m t giá tr t vùng nh , thì tuỳ
theo ki u giá tr ta ph i dùng phép chuy n ki u thích h p đ i
v i con tr . d sau minh ho cách l p m t danh sách g m m t
s nguyên, m t s th c m t chu i t . Chúng ta c n m t b
nh đ ch a s nguyên, s th c đ a ch chu i dùng các con
tr void đ qu n lý vùng nh này.
void *list , *p ; // Con tr list tr t i đ u danh sách
// p dùng đ duy t qua các ph n t c a danh sách
list=malloc(sizeof(int) + sizeof(float)+ sizeof(char*) );
p=list;
561 562
*((int*)p) = 12; // Đ a s nguyên 12 vào danh sách ư
((int*)p)++ ; // Chuy n sang ph n t ti p theo ế
*((float*)p) = 3.14; // Đ a s th c 3.14 vào danh sách ư
((float*)p)++ ; // Chuy n sang ph n t ti p theo ế
*((char**)p) = “HA NOI”; // Đ a đ a ch chu i “HA NOI” ư
// vào danh sách
// Nh n các ph n t trong danh sách
p=list; // V đ u danh sách
int a = *((int*)p); // Nh n ph n t th nh t
((int*)p)++ ; // Chuy n sang ph n t ti p theo ế
float x= *((float*)p); // Nh n ph n t th hai
((float*)p)++ ; // Chuy n sang ph n t ti p theo ế
char *str = *((char**)p) ; // Nh n ph n t th ba
3. Hàm v i đ i s b t đ nh
+ Đ i b t đ nh bao gi cũng đ t sau cùng đ c khai báo ượ
b ng d u ba ch m. Ví d ví d hàm
void f(int n, char *s, ...) ;
có 2 đ i c đ nh là n, s và đ i b t đ nh.
+ Đ nh n đ c các tham s b t đ nh trong l i g i hàm ta c n ượ
l u ý các đi m sau:ư
- Các tham s b t đ nh ch a trong m t danh sách. Đ nh n
đ c đ a ch đ u danh sách ta dùng m t con tr void phép gánượ
sau:
void *list ;
list = ... ;
- Dùng m t tham s c đ nh ki u chu i đ quy đ nh s l ng ượ
và ki u c a m i tham s trong danh sách, ví d :
“3i” hi u là : tham s b t đ nh g m 3 giá tr int
“3f” hi u là : tham s b t đ nh g m 3 giá tr float
“fiss” hi u 4 tham s b t đ nh ki u l n l t float, ượ
int, char*, char*
M t khi đã bi t đ c đ a ch đ u danh sách, bi t đ c s l ng ế ượ ế ượ ượ
ki u c a m i tham s , thì d dàng nh n đ c giá tr các tham ượ
s đ s d ng trong thân hàm.
Ví d sau đây minh ho cách xây d ng các hàm v i tham s b t
đ nh. Hàm dùng đ in các giá tr ki u int, float và char. Hàm có m t
tham s c đ nh đ cho bi t bao nhiêu giá tr ki u các giá tr ế
c n in. Ki u quy đ nh nh sau: i int, f float, s char*. Tham ư
s 2 cách vi t: l p (g m m t h ng s nguyên m t ch cái ế
đ nh ki u) và li t kê (m t d y các ch cái đ nh ki u). Ví d :
“4s” có nghĩa in 4 chu i
“siif” nghĩa in m t chu i, 2 giá tr nguyên m t giá tr
th c:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <conio.h>
#include <stdlib.h>
#include <stdarg.h>
void InDanhSachGiaTri(char *st,...)
{
void *list ;
int gt_int ;
float gt_float;
char *gt_str;
int n,i ;
char kieu;
int lap;
list = ... ; // list tro toi vung nho chua danh sach dia chi cac
563 564
// tham so
lap = isdigit(st[0]) ;
if (lap)
n=st[0] - '0' ;
else
n=strlen(st);
printf("\n n= %d lap = %d",n,lap); getch();
for(i=0;i<n;++i)
{
if(lap)
kieu=st[1];
else
kieu = st[i];
printf("\nKieu= %c",kieu); getch();
switch(kieu)
{
case 'i' :
gt_int = *((int*)list);
if(!lap)
((int*)list)++ ;
printf("\nGia tri %d = %d",i,gt_int);
break;
case 'f' :
gt_float = (float) (*((double*)list));
if(!lap)
((double*)list)++ ;
printf("\nGia tri %d = %0.2f",i,gt_float);
break;
case 's' :
gt_str = *((char**)list) ;
if(!lap)
((char**)list)++ ;
printf("\nGia tri %d = %s",i,gt_str);
}
}
}
void main()
{
float x=3.14;
int a=123;
char *tp="HAI PHONG";
InDanhSachGiaTri("4i",a);
InDanhSachGiaTri("4s","HA NOI");
InDanhSachGiaTri("ifsssffii", a, x, tp, tp,"QUY NHON",
x, 6.28, a, 246);
InDanhSachGiaTri("4f",6.28);
getch();
}
4. Hàm không đ i và hàm v i đ i b t đ nh
Nhi u ng i nghĩ hàm khai báo nh sau ườ ư
void f();
là hàm không đ i trong C. Trong C++ thì hi u nh th đúng, còn ư ế
trong C thì đó hàm đ i b t đ nh (hàm không đ i trong C khai
báo nh sau: f(void) ). Do không có đ i c đ nh nào cho bi t v sư ế
l ng ki u c a các tham s b t đ nh, nên gi i pháp đây ượ
565 566
dùng các bi n toàn b . ràng gi i pháp này không không thu nế
ti n cho ng i dùng vì ph i khai báo đúng tên bi n toàn b và ph i ườ ế
kh i gán giá tr cho nó tr c khi g i hàm. Ví d trình b y m t hàm ướ
ch có đ i b t đ nh dùng đ tính max min c a các giá tr th c.
Các tham s b t đ nh đ c đ a vào theo trình t sau: Đ a ch ch a ượ ư
max, đ a ch ch a min, các giá tr nguyên c n tính max, min.
Ch ng trình dùng bi n toàn b N đ cho bi t s giá tr nguyênươ ế ế
c n tính max, min.
int N;
void maxmin()
{
void *lt = ... ;
float *max, *min , tg;
int i;
max = *((float**)lt)++;
min = *((float**)lt)++;
*max = *min = (float) *((double*)lt)++;
for(i=1;i<N;++i)
{
tg= (float) *((double*)lt)++;
if(tg > *max) *max = tg;
if(tg < *min) *min = tg;
}
}
567