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

KỸ THUẬT LẬP TRÌNH (p6) doc

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 (365.34 KB, 9 trang )

0
K
K


THU
THU


T L
T L


P TRÌNH
P TRÌNH
KỸ THUẬT PHÁT TRIỂN CHƯƠNG TRÌNH
NỘI DUNG
 Hàm và Thủ tục
 Phát triển chương trình bằng phương pháp tinh
chỉnh dần từng bước.
 Định nghĩa và sử dụng hàm trong ngôn ngữ C
 Hàm đệ quy
1
Đ
Đ


nh ngh
nh ngh
ĩ
ĩ


a v
a v
à
à
s
s


d
d


ng h
ng h
à
à
m trong C
m trong C
 Hàm trong C
• Các Modules trong C
• Một chương trình bao gồm các hàm do người sử dụng tạo dựng và các
hàm thư viện
– Thư viện chuẩn C có một lượng lớn các hàm và có thể được mở rộng thêm
– V
ídụ: khi dùng #include <stdio.h>, ta có thể gọi hàm scanf,…
 Lời gọi hàm
• Xuất phát từ chương trình chính (main) hoặc từ 1 hàm nào đó.
• Yêu cầu gọi các hàm:
– Cung cấp tên hàm và các đối số
– Hàm thực hiện các hành động hoặc các thao tác

– Hàm trả lại kết quả
2
 Ngữ nghĩa lời gọi hàm:
– Giám đốc giao nhiệm vụ cần hoàn thành cho nhân viên
– Nhân viên nhận thông tin, thực hiện, trả lại kết quả
– Giám đốc không biết chi tiết về quá trình thực hiện
main
worker1 worker2 worker3
worker4 worker5
3
 Cú pháp định nghĩa hàm
return-value-type function-name( parameter-list )
{
khai báo dữ liệu và các lệnh
}
• Function-name: Tên hàm
• Return-value-type: kiểu dữ liệu c
ủa kết quả trả về (mặc
định là int)
– void – hàm không trả lại kết quả
• Parameter-list: các tham số cách nhau bằng dấu “,”
– Phải khai báo kiểu dữ liệu cho từng tham số.
4
 Cú pháp định nghĩa (tiếp theo)
• Các khai báo và các lệnh: thân của hàm (khối)
– Các biến có thể được định nghĩa bên trong hàm
– Các hàm không được định nghĩa trong hàm khác
• Kiểm soát kết quả trả về bằng lệnh return
– Nếu không có kết quả trả về
– return;

– hoặc gặp dấu ngoặc móc } để kết thúc
– Nếu có kết quả trả về
– return biểu_thức;
fig05_04.c (Part 1 of 2)
fig05_04.c (Part 1 of 2)
1
/* Fig. 5.4: fig05_04.c
2
Finding the maximum of three integers */
3
#include <stdio.h>
4

5
int maximum( int x, int y, int z ); /* function prototype */
6

7
/* function main begins program execution */
8
int main()
9
{
10
int number1; /* first integer */
11
int number2; /* second integer */
12
int number3; /* third integer */
13


14
printf( "Enter three integers: " );
15
scanf( "%d%d%d", &number1, &number2, &number3 );
16

17
/* number1, number2 and number3 are arguments
18
to the maximum function call */
19
printf( "Maximum is: %d\n", maximum( number1, number2, number3 ) );
20

21
return 0; /* indicates successful termination */
22

23
} /* end main */
24


Enter three integers: 22 85 17
Maximum is: 85
Enter three integers: 85 22 17
Maximum is: 85
Enter three integers: 22 17 85
Maximum is: 85

25
/* Function maximum definition */
26
/* x, y and z are parameters */
27
int maximum( int x, int y, int z )
28
{
29
int max = x; /* assume x is largest */
30

31
if ( y > max ) { /* if y is larger than max, assign y to max */
32
max = y;
33
} /* end if */
34

35
if ( z > max ) { /* if z is larger than max, assign z to max */
36
max = z;
37
} /* end if */
38

39
return max; /* max is largest value */

40

41
} /* end function maximum */

7
Ph
Ph


m vi c
m vi c


a bi
a bi
ế
ế
n
n
Biến toàn cục và biến địa phương
 Biến toàn cục: là những biến được sử dụng ở mọi nơi
trong chương trình.
• Cấp phát bộ nhớ cho biến toàn cục: cấp phát bộ nhớ tĩnh
 Biến địa phương: là biến chỉ có giá trị trong thời gian
hàm hoạt động, sau khi kết thúc hàm thì những biến khai
báo bên trong hàm và các tham số truyền cho hàm sẽ
không tồn tại nữa.
8
 Cấp phát bộ nhớ cho biến địa phương: cấp phát tự

động, cần đến đâu cấp phát đến đó, mỗi lần gọi hàm là
một lần cấp phát.
 Biến địa phương tĩnh static: Yêu cầu cấp phát các biến
của hàm ở vị trí cố định, tĩnh tại, luôn được dùng cho
hàm. Vì vậy, giá trị của các biến này có thể tồn tại ngay
cả khi hàm đã kết thúc hoạt động của hàm.
1 /* Fig. 5.12: fig05_12.c
2
A scoping example */
3
#include <stdio.h>
4

5 void useLocal( void ); /* function prototype */
6
void useStaticLocal( void ); /* function prototype */
7
void useGlobal( void ); /* function prototype */
8

9 int x = 1; /* global variable */
10

11 /* function main begins program execution */
12 int main()
13 {
14
int x = 5; /* local variable to main */
15


16 printf("local x in outer scope of main is %d\n", x );
17

18
{ /* start new scope */
19 int x = 7; /* local variable to new scope */
20
21
printf( "local x in inner scope of main is %d\n", x );
22
} /* end new scope */
23

24
printf( "local x in outer scope of main is %d\n", x );
25


26
useLocal(); /* useLocal has automatic local x */
27
useStaticLocal(); /* useStaticLocal has static local x */
28
useGlobal(); /* useGlobal uses global x */
29
useLocal(); /* useLocal reinitializes automatic local x */
30
useStaticLocal(); /* static local x retains its prior value */
31
useGlobal(); /* global x also retains its value */

32

33
printf( "local x in main is %d\n", x );
34

35
return 0; /* indicates successful termination */
36

37
} /* end main */
38

39
/* useLocal reinitializes local variable x during each call */
40
void useLocal( void )
41
{
42
int x = 25; /* initialized each time useLocal is called */
43

44
printf( "\nlocal x in a is %d after entering a\n", x );
45
x++;
46
printf( "local x in a is %d before exiting a\n", x );

47
} /* end function useLocal */
48


49
/* useStaticLocal initializes static local variable x only the first time
50
the function is called; value of x is saved between calls to this
51
function */
52
void useStaticLocal( void )
53
{
54
/* initialized only first time useStaticLocal is called */
55
static int x = 50;
56

57
printf( "\nlocal static x is %d on entering b\n", x );
58
x++;
59
printf( "local static x is %d on exiting b\n", x );
60
} /* end function useStaticLocal */
61


62
/* function useGlobal modifies global variable x during each call */
63
void useGlobal( void )
64
{
65
printf( "\nglobal x is %d on entering c\n", x );
66
x *= 10;
67
printf( "global x is %d on exiting c\n", x );
68
} /* end function useGlobal */

local x in outer scope of main is 5
local x in inner scope of main is 7
local x in outer scope of main is 5
local x in a is 25 after entering a
local x in a is 26 before exiting a
local static x is 50 on entering b
local static x is 51 on exiting b
global x is 1 on entering c
global x is 10 on exiting c
local x in a is 25 after entering a
local x in a is 26 before exiting a
local static x is 51 on entering b
local static x is 52 on exiting b
global x is 10 on entering c

global x is 100 on exiting c
local x in main is 5
13
Truy
Truy


n m
n m


ng
ng
cho
cho
h
h
à
à
m
m
 Để truyền mộtmảng cho hàm, chỉ ra tên củamảng,
không sử dụng cặp “[]”
int myArray[ 24 ];
myFunction( myArray, 24 );
– Kích thước của mảng cần được truyền qua hàm
• Mảng được truyền thông qua lời gọi tham chiếu
• Tên củamảng là địa chỉ phần tử đầu tiên
• Hàm biết được nơi lưu trữ mảng
– Thực hiện thay đổi tại vị trí chứa mảng trong bộ nhớ


Truyền các phần tử mảng
• Truyền thông qua lời gọi bởi giá trị (truyền theo trị)
• Truyền tên mảng cùng chỉ số tới hàm (ví dụ:
myarray[3])
14
Truy
Truy


n m
n m


ng cho h
ng cho h
à
à
m
m
 Khai báo nguyên mẫu hàm (function prototype) để
truyền mảng cho hàm
void modifyArray( int b[], int arraySize );
• Có thể bỏ qua tên mảng trong khai báo nguyên mẫu hàm
– int b[] có thể được viếtint[]
– int arraySize có thể được viết đơn giản là int
• Tên của array chính là &array[ 0 ] (địa chỉ của phần tử
đầu tiên trong mảng) do vậy khi truyền mảng (tham
biến) thông qua gọi hàm không cần sử dụng dấu &
Ví dụ gọi hàm với khai báo nguyên mẫu trên:

int a[10], n = 10;
modifyArray( a, n); // không sử dụng &a
array = 0012FF78
&array[0] = 0012FF78
&array = 0012FF78
1 /* Fig. 6.12: fig06_12.c
2
The name of an array is the same as &array[ 0 ] */
3 #include <stdio.h>
4

5
/* function main begins program execution */
6 int main()
7 {
8 char array[ 5 ]; /* define an array of size 5 */
9

10
printf( " array = %p\n&array[0] = %p\n"
11 " &array = %p\n",
12
array, &array[ 0 ], &array );
13

14 return 0; /* indicates successful termination */
15

16
} /* end main */


Ví dụ: Tên của array chính là &array[ 0 ] (địa chỉ của phần tử
đầu tiên trong mảng)
1 /* Fig. 6.13: fig06_13.c
2 Passing arrays and individual array elements to functions */
3 #include <stdio.h>
4
#define SIZE 5
5

6 /* function prototypes */
7 void modifyArray( int b[], int size );
8
void modifyElement( int e );
9

10 /* function main begins program execution */
11 int main()
12 {
13
int a[ SIZE ] = { 0, 1, 2, 3, 4 }; /* initialize a */
14 int i; /* counter */
15

16 printf( "Effects of passing entire array by reference:\n\nThe "
17
"values of the original array are:\n" );
18

19 /* output original array */

20 for ( i = 0; i < SIZE; i++ ) {
21
printf( "%3d", a[ i ] );
22 } /* end for */
23

24 printf( "\n" );
25

Ví dụ:
-Truyền mảng b và thay đổi các phần tử của mảng khi gọi hàm (tham chiếu)
-Truyền phần tử của mảng qua hàm (tham trị)
fig06_13.c (Part 2 of 3)
fig06_13.c (Part 2 of 3)
26 /* pass array a to modifyArray by reference */
27 modifyArray( a, SIZE );
28
29 printf( "The values of the modified array are:\n" );
30
31 /* output modified array */
32 for ( i = 0; i < SIZE; i++ ) {
33 printf( "%3d", a[ i ] );
34 } /* end for */
35
36 /* output value of a[ 3 ] */
37 printf( "\n\n\nEffects of passing array element "
38 "by value:\n\nThe value of a[3] is %d\n", a[ 3 ] );
39
40 modifyElement( a[ 3 ] ); /* pass array element a[ 3 ] by value */
41

42 /* output value of a[ 3 ] */
43 printf( "The value of a[ 3 ] is %d\n", a[ 3 ] );
44
45 return 0; /* indicates successful termination */
46
47 } /* end main */
48

49
/* in function modifyArray, "b" points to the original array "a"
50 in memory */
51
void modifyArray( int b[], int size )
52
{
53 int j; /* counter */
54
55
/* multiply each array element by 2 */
56 for ( j = 0; j < size; j++ ) {
57
b[ j ] *= 2;
58 } /* end for */
59

60
} /* end function modifyArray */
61

62

/* in function modifyElement, "e" is a local copy of array element
63
a[ 3 ] passed from main */
64 void modifyElement( int e )
65
{
66 /* multiply parameter by 2 */
67
printf( "Value in modifyElement is %d\n", e *= 2 );
68 } /* end function modifyElement */

-Mảng b sẽ thay đổi giá trị sau khi gọi thực hiện hàm modifyArray
-Phần tử a[3] không thay đổi khi truyền cho biến e khi gọi hàm modifyElement
Effects of passing entire array by reference:
The values of the original array are:
0 1 2 3 4
The values of the modified array are:
0 2 4 6 8
Effects of passing array element by value:
The value of a[3] is 6
Value in modifyElement is 12
The value of a[ 3 ] is 6
20
Truy
Truy


n tham s
n tham s



cho h
cho h
à
à
m
m
 Truyền tham trị
 Truyền tham số trong hàm sử dụng con trỏ (truyền theo
tham chiếu)
• Sử dụng toán tử & để truyền địa chỉ của biến
• Cho phép chúng ta thay đổi một vị trí thực sự trên bộ nhớ
• Các array thì không sử dụng & bởi vì tên array là con trỏ
 Sử dụng * để thay đổi giá trị của tham biến trong hàm
void Intdouble( int *number )
{
*number = 2 * ( *number );
}
• Trong đó:
*number sử dụng như tên biến (bí danh)
1
/* Fig. 7.6: fig07_06.c
2
Cube a variable using call-by-value */
3
#include <stdio.h>
4

5
int cubeByValue( int n ); /* prototype */

6

7 int main()
8
{
9
int number = 5; /* initialize number */
10

11
printf( "The original value of number is %d", number );
12
13 /* pass number by value to cubeByValue */
14 number = cubeByValue( number );
15

16
printf( "\nThe new value of number is %d\n", number );
17

18
return 0; /* indicates successful termination */
19

20 } /* end main */
21

22
/* calculate and return cube of integer argument */
23

int cubeByValue( int n )
24
{
25
return n * n * n; /* cube local variable n and return result */
26

27 } /* end function cubeByValue */

The original value of number is 5
The new value of number is 125
1
/* Fig. 7.7: fig07_07.c
2
Cube a variable using call-by-reference with a pointer argument */
3

4 #include <stdio.h>
5

6 void cubeByReference( int *nPtr ); /* prototype */
7

8
int main()
9
{
10
int number = 5; /* initialize number */
11


12 printf( "The original value of number is %d", number );
13
14 /* pass address of number to cubeByReference */
15 cubeByReference( &number );
16

17
printf( "\nThe new value of number is %d\n", number );
18

19 return 0; /* indicates successful termination */
20

21 } /* end main */
22

23
/* calculate cube of *nPtr; modifies variable number in main */
24
void cubeByReference( int *nPtr )
25
{
26 *nPtr = *nPtr * *nPtr * *nPtr; /* cube *nPtr */
27 } /* end function cubeByReference */

Gọi hàm và sử dụng truyền
biến con trỏ
Trong hàm cubeByReference,
*nPtr đượcsử dụng (*nPtr là số

nguyên).
Truyền tham biếnsử dụng
pointer, trỏ tớisố integer.
The original value of number is 5
The new value of number is 125
23
Con tr
Con tr


l
l
à
à
m tham bi
m tham bi
ế
ế
n c
n c


a h
a h
à
à
m
m
1 /* Fig. 7.10: fig07_10.c
2 Converting lowercase letters to uppercase letters

3 using a non-constant pointer to non-constant data */
4

5 #include <stdio.h>
6 #include <ctype.h>
7

8 void convertToUppercase( char *sPtr ); /* prototype */
9

10 int main()
11 {
12 char string[] = "characters and $32.98"; /* initialize char array */
13

14 printf( "The string before conversion is: %s", string );
15
convertToUppercase( string );
16 printf( "\nThe string after conversion is: %s\n", string );
17
18 return 0; /* indicates successful termination */
19

20 } /* end main */
21

22
/* convert string to uppercase letters */
23
void convertToUppercase( char *sPtr )

24
{
25
while ( *sPtr != '\0' ) { /* current character is not '\0' */
26

27
if ( islower( *sPtr ) ) { /* if character is lowercase, */
28
*sPtr = toupper( *sPtr ); /* convert to uppercase */
29
} /* end if */
30

31
++sPtr; /* move sPtr to the next character */
32
} /* end while */
33

34
} /* end function convertToUppercase */

The string before conversion is: characters and $32.98
The string after conversion is: CHARACTERS AND $32.98
25
Tham bi
Tham bi
ế
ế

n const đ
n const đ


i v
i v


i h
i h
à
à
m trong C
m trong C
 const
• biến không được phép thay đổi
• Sử dụng
const nếu hàm không cần thay đổi giá trị của biến
• Cố tình thay đổi biến
const sẽ gây lỗi
 const pointers
• Trỏ tới vùng nhớ cố định
• Phải được khởi tạo khi định nghĩa
• int *const myPtr = &x;
– Kiểu int *const – con trỏ hằng trỏ đến vùng nhớ kiểu int
• const int *myPtr = &x;
– Con trỏ thông thường trỏ đến const int
• const int *const Ptr = &x;
– con trỏ const trỏ đến một vùng nhớ const int
– x c

óthể thay đổi, nhưng *Ptr thì không.
1 /* Fig. 7.11: fig07_11.c
2 Printing a string one character at a time using
3 a non-constant pointer to constant data */
4

5 #include <stdio.h>
6

7 void printCharacters( const char *sPtr );
8

9 int main()
10 {
11 /* initialize char array */
12 char string[] = "print characters of a string";
13

14 printf( "The string is:\n" );
15 printCharacters( string );
16 printf( "\n" );
17

18 return 0; /* indicates successful termination */
19

20 } /* end main */
21



22
/* sPtr cannot modify the character to which it points,
23
i.e., sPtr is a "read-only" pointer */
24
void printCharacters( const char *sPtr )
25
{
26
/* loop through entire string */
27
for ( ; *sPtr != '\0'; sPtr++ ) { /* no initialization */
28
printf( "%c", *sPtr );
29
} /* end for */
30

31
} /* end function printCharacters */

The string is:
print characters of a string
1
/* Fig. 7.12: fig07_12.c
2
Attempting to modify data through a
3
non-constant pointer to constant data. */
4

#include <stdio.h>
5

6
void f( const int *xPtr ); /* prototype */
7

8
int main()
9
{
10
int y; /* define y */
11

12
f( &y ); /* f attempts illegal modification */
13

14
return 0; /* indicates successful termination */
15

16
} /* end main */
17

18
/* xPtr cannot be used to modify the
19

value of the variable to which it points */
20
void f( const int *xPtr )
21
{
22
*xPtr = 100; /* error: cannot modify a const object */
23
} /* end function f */

Ví dụ:trường hợp không được phép thay đổigiátrị khi
sử dụng con trỏ hằng.
29
Con tr
Con tr


h
h
à
à
m
m
 Khai báo con trỏ hàm
double (*f)(double): f là con trỏ hàm kiểu double, có một đối kiểu
double
double (*g)(double, int): g là con trỏ hàm kiểu double, có hai đối
theo thứ tự là kiểu double và kiểu int
double (*af[10])(double, int): af là mảng gồm 10 con trỏ hàm kiểu
double, có hai đối theo thứ tự là kiểu double và kiểu int

 Con trỏ hàm dùng để chứa địa chỉ của hàm
30
Cách dùng:
 Gán tên hàm cho con trỏ hàm (kiểu hàm và kiểu con trỏ
hàm phải tương thích). Sau phép gán có thể dùng tên
con trỏ hàm thay cho tên hàm.
 Đối con trỏ hàm:
Khi sử dụng con trỏ hàm là tham biến của một hàm thì
tham số thực sự tương ứng trong lời gọi hàm là tên của
hàm cùng kiểu.
31
 Ví dụ sử dụng con trỏ hàm làm tham biến của một
hàm: Tính gần đúng tích phân xác định theo công thức
hình thang.
 Tính gần đúng tích phân theo công thức hình
thang, với phép chia [a,b] thành n đoạn bằng nhau:
• Lập bảng giá trị của hàm số y = f(x)
• x
i
= x
0
+ i.h, i = 0 n, x
0
= a; h = (b - a)/n; y
i
= f(x
i
), i = 0 n.
• I ≈ I
T

• I
T
= h.((y
0
+y
n
)/2 + y
1
+ + y
n-1
)

=
b
a
dxxfI )(
32
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <math.h>
#include <alloc.h>
double f(double x);
double TP(double (*f)(double), float a, float b, int n);
void main()
{
float a = 0, b = 1;
int n = 10;
clrscr();
printf("\nTich phan sin(x) tren [%.2f, %.2f] xap xi bang:\n\t %lf", a, b, TP(sin, a, b, n));

printf("\nTich phan f(x) = 1/(1 + x) tren [%.2f, %.2f] xap xi bang:\n\t%lf", a, b, TP(f, a, b, n));
getch();
}
33
double f(double x)
{
return (1/(1 + x));
}
double TP(double (*f)(double), float a, float b, int n)
{
double h, *x, *y, IT;
int i;
x = (double*) malloc((n+1)*sizeof(double));
y = (double*) malloc((n+1)*sizeof(double));
h = (b - a)/n;
for ( i = 0; i <= n; i++) {
x[i] = a + i*h;
y[i] = f(x[i]);
printf("\n %lf\t%lf", x[i], y[i]);
}
for (i = 1, IT = (y[0] + y[n])/2; i < n; i++) {
IT += y[i];
}
return (IT*h);
}
34
B
B
À
À

I T
I T


P
P
1. Viết hàm giải hệ phương trình:
{a.x + b.y = c; d.x + e.y = f}
2. Viết hàm giải hệ phương trình đại số tuyến tính Ax = b,
A = (a
ij
)
NxN
theo phương pháp Gauss
3. Viết hàm tìm gần đúng nghiệm của phương trình f(x) = 0
trên [a, b] bằng phương pháp chia đôi. Giả thiết f(x) liên
tục, đơn điệu trên [a, b] và f(a).f(b) < 0.

×