46
CƠ SỞ LẬP TRÌNH CƠ BẢN VỀ C - HÀM

CƠ BẢN VỀ C - HÀM - nmlt.files.wordpress.com · Cấu trúc chương trình C • Cấu trúc tổng quát của một chương trình C: 1. Khai báo các thư viện với

  • Upload
    others

  • View
    13

  • Download
    0

Embed Size (px)

Citation preview

CƠ SỞ LẬP TRÌNH

CƠ BẢN VỀ C -HÀM

Nội dung môn học1. Cơ bản về C2. Hàm và con trỏ3. Mảng, chuỗi4. File5. Lập trình cấu trúc6. Các chỉ thị tiền xử lý & tổ chức chương

trình gồm nhiều file

2

Cấu trúc chương trình C• Cấu trúc tổng quát của một chương trình C:

1. Khai báo các thư viện với từ khóa #include.2. Các câu lệnh #define.3. Các đối tượng toàn cục (biến, hằng).4. Khai báo các nguyên mẫu hàm.5. Hàm main().6. Định nghĩa các hàm đã khai báo.

• Chú ý: Hàm main() có thể được đặt trước hoặc sau phần định nghĩa các hàm.

3

Cấu trúc chương trình C• Ví dụ:

#include <stdio.h> #include#define PI 3.14 #definefloat r; khai báo biếnvoid CalculateArea(); prototypevoid main(){scanf(“%f”, &r); hàm main()CalculateArea();

}void CalculateArea(){return PI*r*r; định nghĩa hàm

}

4

Kiểu dữ liệu cơ bản

5

Kiểu Số bit Tầm trịunsigned char 8 0 .. 255char 8 -128 .. 127enum 16 -32,768 .. 32,767unsigned int 16 0 .. 65,535short int 16 -32,768 .. 32,767int 16 -32,768 .. 32,767unsigned long 32 0 .. 4,294,967,295long 32 -2,147,483,648 ..2,147,483,647float 32 3.4 * (10-38) ..3.4 * (10+38)double 64 1.7 * (10-308) .. 1.7 * (10+308)long double 80 3.4 * (10-4932) .. 1.1 * (10+4932)

Kiểu dữ liệu có cấu trúc• Pointer• Array• Chuỗi• Enum• Struct, Union• File

6

Lệnh cơ bản• <biểu thức>;• Ví dụ: x=5; y++;

7

Lệnh điều khiển• Chọn: if – else, switch – case.• Lặp: for, while, do – while• Ngắt/nhảy: break, continue, return, goto.

8

HÀMNội dung1. Cơ bản về hàm2. Phạm vi biến3. Đệ quy

9

Cơ bản về hàm• Hàm: khối mã lệnh Thực hiện một số lệnh đã được định nghĩa

trước. Đảm trách một chức năng cụ thể, xác định.

• Có 2 loại hàm: Hàm thư viện được xây dựng sẵn. Hàm tự tạo.

• Hàm chia vấn đề lớn thành các vấn đề con nhỏ hơn.

10

Cơ bản về hàm• Ví dụ: Các hàm xây dựng sẵn:

• printf()• scanf()• …

Hàm tự định nghĩa:

float CalculateAverageValue(float a, float b){

float avg = (a + b)/2;return avg;

}

11

Cơ bản về hàm• Nguyên mẫu hàm (Function prototype): Báo

cho trình biên dịch biết sẽ sử dụng hàm này ở phía sau.

• Bao gồm: Tên hàm Kiểu trả về (void nếu không có giá trị trả về) Các tham số được truyền vào hàm (số lượng

và kiểu dữ liệu của tham số)• Ví dụ:

float CalculateAverageValue(float a, float b);

12

Cơ bản về hàm• Định dạng của một khai báo hàm như sau:

return_type function_name ( arg_type arg1, ..., arg_type argN ); arg_type: kiểu dữ liệu của mỗi tham số. return_type: kiểu dữ liệu của giá trị trả về.

Chú ý: Có thể có nhiều hơn một tham số được truyền vào hoặc không có tham số nào.

• Từ khóa return: Trả dữ liệu về. Trả điều khiển lại cho nơi gọi. Nếu không trả về

giá trị thì sử dụng lệnh return; Cú pháp: return value; hoặc return (value);

13

Cơ bản về hàm• Ví dụ:1. Viết hàm tìm giá trị lớn nhất của 2 số.int max( int a, int b){

return (a>b ? a : b);}2. Viết hàm kiểm tra n là số chẵn hay lẻ.

14

Cơ bản về hàm• Nguyên mẫu hàm: Hàm không có giá trị trả về có kiểu trả về là

void. Ví dụ:

void InputThenOutputFullName();• Function prototype chỉ cần đến nếu định

nghĩa hàm đặt sau lời gọi hàm (function call). Prototype không phải là hàm thực sự. Prototype là một khai báo hàm.

15

Cơ bản về hàm• Định nghĩa hàm: Bắt đầu với prototype, không có dấu ; Khối lệnh nằm trong dấu { … }

• Ví dụ:void InputThenOutputFullName(){char[64] strName;scanf(“%s”, strName);printf(“Name is: %s”, strName);

}

16

Cơ bản về hàm• Định nghĩa hàm: Bất kỳ tham số nào được truyền vào hàm có thể

được sử dụng như chúng đã được khai báo trong thân hàm. Ví dụ:

float CalculateAverageValue(float a, float b)

{float avg = (a + b)/2;return avg;

}17

Cơ bản về hàm• Nguyên tắc sử dụng hàm khi không có

prototype: Phải định nghĩa hàm trước hàmmain().

• Nguyên tắc sử dụng hàm với prototype:1. Khai báo prototypes trước.2. Định nghĩa hàm sau prototype.3. Viết hàm main sau prototype.

Chú ý: Luôn khai báo hoặc định nghĩa hàmtrước khi gọi hàm.

18

Cơ bản về hàm• Tại sao phải có hàm? Thực thi một khối lệnh thường xuyên lặp lại

định nghĩa hàm chỉ một lần. Làm chương trình dễ đọc. Dễ chỉnh sửa khi có sự thay đổi trong chương

trình. Chia chương trình thành nhiều phần nhỏ.

19

Cơ bản về hàm• Gọi hàm: Cú pháp: function_name(arg1, arg2, … , argN); Ví dụ:

float a = 10.0, b = 5.0;

float c = 3.0, d = 8.0;

float x1, x2;

x1 = CalculateAverageValue(a, b);

x2 = CalculateAverageValue(c, d);

20

Cơ bản về hàm• Gọi hàm: Tham số:

• Truyền đầy đủ các tham số được khai báo.• Chính xác kiểu của từng tham số.

Hàm lồng nhau: Một hàm có thể được gọi trongcác hàm khác. Không thể định nghĩa một hàmbên trong một hàm khác.

21

Cơ bản về hàm• Tham số: Tham số hình thức: xuất hiện trong khai báo hàm. Tham số thực: xuất hiện trong lời gọi hàm.void calculate_bill ( int a, int b, int c ) {

int total;

total = a + b + c;

}

void main(){

int x = 5, y = 7, z = 8;

calculate_bill( x, y, z );

}

22

Formal?Actual?

Formal?Actual?

Tham số giá trị, tham số biến• Tham chiếu là một bí danh của biến khác.• Khi tạo ra một tham chiếu, gán nó lên một biến khác thì

tham chiếu hoạt động như chính biến đã gán đến nó.• Kiểu dữ liệu của tham chiếu phải trùng với kiểu dữ liệu của

biến mà nó tham chiếu đến.• Trong mô hình bộ nhớ máy tính, địa chỉ của tham chiếu

chính là địa chỉ của biến mà nó tham chiếu đến.• Cú pháp:

<Kiểu giá trị> &Tên tham chiếu = Biến đã tồn tại;• Ví dụ: int a = 5;

int &b = a;

23

Tham số giá trị, tham số biến• Khi truyền tham số dưới dạng tham số giá trị, ta

truyền giá trị của biến đó. Bất kỳ sự thay đổi nàođược thực hiện với tham số đó bên trong hàm sẽkhông ảnh hưởng trực tiếp đến biến đó.Ví dụ: void hoanvi(int a, int b)

• Khi truyền tham số dưới dạng tham số biến, tađang truyền bản thân biến đó, bất kỳ sự thay đổinào được thực hiện với tham số đó bên trong hàmsẽ ảnh hưởng trực tiếp đến biến đó.Ví dụ: void hoanvi(int &a, int &b)

24

Ví dụ#include<iostream.h>void hoanvi(int &a, int &b);void main(){int a,b;cout<<"Nhap 2 so: ";cin>>a>>b;;hoanvi(a,b);cout<<"a = "<<a<<"\t b = "<<b;

}void hoanvi(int &a, int &b){int c;c=a;a=b;b=c;

}25

Nạp chồng hàm• C++ cho phép nhiều hàm có cùng tên nhưng các đối số có

kiểu dữ liệu khác nhau, được gọi là nạp chồng hàm(function overloading).

• Ví dụ:int max(int a, int b){

return (a>b ? a : b);}float max(float a, float b){

return (a>b ? a : b);}

26

Đối số mặc định• Cho phép chỉ định những giá trị mặc định sẽ được truyền

cho các đối số nếu chúng bị bỏ qua khi gọi hàm.• Gán một giá trị cho đối số khi khai báo hàm. Nếu giá trị của

tham số đó vẫn được truyền vào khi gọi hàm thì giá trị mặcđịnh sẽ bị bỏ qua.

• Tất cả đối số mặc định phải nằm cuối danh sách tham số.• Ví dụ:

int phepchia(int a, int b=1){

return a/b;}

27

Phạm vi biến (Tầm vực biến)• Phạm vi biến là nơi mà biến có thể sử dụng

được trong chương trình.• Có 2 loại: Phạm vi toàn cục: nằm ngoài các hàm. Phạm vi cục bộ: nằm trong dấu { } của bất kỳ

khối lệnh nào. Phạm vi cục bộ chỉ có ý nghĩabên trong khối lệnh nó được khai báo.

28

Phạm vi biến• Các loại lưu trữ biến: Biến toàn cục và biến cục bộ (Global variable vs

Local variable). Biến external và biến internal (External variable

vs internal variable). Biến tự động và biến tĩnh (Auto variable vs

Static variable). Biến register (Register variable).

29

Biến toàn cục, biến cục bộ• Biến toàn cục Có thể được sử dụng ở bất kỳ nơi nào trong

chương trình. Được khai báo ở bên ngoài hàm. Thường nằm phía dưới khai báo thư viện.

• Biến cục bộ (biến địa phương) Được khai báo ở bên trong một khối lệnh. Chỉ có ý nghĩa trong khối lệnh đó. Nếu biến cục bộ được khai báo bên trong một

hàm thì nó chỉ có ý nghĩa trong hàm đó.

30

Biến toàn cục, biến cục bộ• Toán tử :: Khi một biến cục bộ có cùng tên với biến toàn

cục, biến cục bộ sẽ được ưu tiên sử dụng. Trong phạm vi cục bộ, để truy xuất biến toàn

cục có cùng tên, sử dụng toán tử :: trước tênbiến. Toán tử :: báo compiler sử dụng biến toàn cục. Nên tránh dùng các tên giống nhau cho các

biến cục bộ và toàn cục.

31

Biến toàn cục, biến cục bộ• Ví dụ:#include <stdlib.h>#include <conio.h>int x=10;//Khai báo hàm increaseint increase(int n);void main(){

int x=20;x=increase(x);

printf("x = %d\n",x);printf("::x = %d",::x);getch();

}//Định nghĩa hàm increaseint increase(int n){

return ++n;}

32

Biến tự động• Biến được tạo khi chương trình chạy vào một khối

lệnh và bị hủy bỏ khi chương trình ra khỏi khối. Chỉcó các biến cục bộ của các hàm mới có thể là biếntự động. Mặc định là biến tự động. Dùng từ khóa auto để khai báo biến tự động.

• Từ khóa register Gợi ý đặt biến vào thanh ghi tốc độ cao có lợi cho các

biến thương xuyên được sử dụng. Thường là không cần thiết, trình biên dịch tự tối ưu hóa.

• Chỉ dùng một trong hai từ register hoặc auto.• Ví dụ: register int i = 1;

33

Biến tĩnh• Tồn tại trong suốt chương trình.• Có thể không phải nơi nào cũng sử dụng

được, do áp dụng quy tắc phạm vi.• Từ khóa static Dành cho biến cục bộ trong hàm. Giữ giá trị giữa các lần gọi hàm. Chỉ được biết đến trong hàm của biến đó.

34

Biến tĩnh#include<stdio.h>#include<conio.h>int func();void main(){

printf("%d",func());printf("\n%d",func());printf("\n%d",func());getch();

}int func(){

static int i=0;i++;return i;

}

Result:123

35

Extern• Biến toàn cục là biến khai báo bên ngoài hàm và được sử

dụng trong toàn chương trình.• Biến toàn cục có thể được khai báo với từ khóa static hoặc

extern.• Từ khóa extern: Cho phép mở rộng phạm vi toàn cục của

biến.• Thông thường, một project C++ gồm nhiều file, extern cho

phép biến toàn cục sử dụng giữa các file với nhau.

36

//file1int x;static float n;..void main(){ ... }

//file2double a;extern int m;int func();

//end of file2

Ví dụViết hàm tính chu vi và diện tích hình tròn với

tham số truyền vào là bán kính.float constant pi = 3.14;float CalculatePerimeter(float r){float perimeter = 2.0 * pi * r;return perimeter;

}float CalculateArea(float r){float area = pi * r * r;return area;

} 37

Đệ quy• Hàm có thể gọi chính nó trực tiếp hoặc

gián tiếp. Trực tiếp: func1 calls func1. Gián tiếp: func1 calls func2, func2 calls

func1.• Bài toán: Tính n!

38

Đệ quy• Tính giai thừa của n: IF n <= 1 THEN gt = 1. ELSE: gt= n * gt(n-1).

n! = 1*2*3*4*…*(n-1)*n= (n-1)! *n= n*(n-1)!

39

Đệ quy• Tính giai thừa của n:int GiaiThua(int n){

if(n <= 1)

return 1;

else

return (n*GiaiThua(n – 1));

}

40

Đệ quy• Giải thích:GiaiThua(3) = 3*GiaiThua(2)

= 3 * (2 *GiaiThua(1)) = 3 * (2 * (1 * GiaiThua(0))) = 3 * (2 * (1 * 1))) = 6

41

Đệ quy• Fibonacci Numbers

42

Đệ quy• Số Fibonacci :

Pseudo Code (Wikipedia.org):function Fibonacci is: input: integer n such that n >= 0

1. if n is 0, return 0 2. if n is 1, return 1 3. otherwise, return [Fibonacci(n-1) + Fibonacci(n-2) ]

end Fibonacci

43

Bài tậpViết các hàm sau:1. Xác định USCLN của 2 số tự nhiên.2. Xác định BSCNN của 2 số tự nhiên.3. Kiểm tra n có phải là số nguyên tố.4. Kiểm tra n có phải là số Fibbonaci.5. Giải phương trình bậc nhất ax + b = 0.6. Giải phương trình bậc 2: ax2 + bx + c = 0.

44

Bài tập7. In ra bảng cửu chương của n.8. Phân tích số n thành tích các thừa số

nguyên tố (Ví dụ: 60=2*2*3*5)9. Tính tổng các giá trị từ 1 đến n (n>0).10. Tính m^n.Viết chương trình thực thi các hàm trên.

45

Bài tập11. Cho biết kết quả sau khi chạy chương trình. Giải thích.

#include <iostream.h>void mul(int&,int,int&); int main( ) {

int x = 4, y = 3, z = 2; mul( y, z, x ); cout << "\nX = " << x; cout << "\nY = " << y; cout << "\nZ = " << z; return 0;

} void mul( int & a,int b, int & c ) {

a *= b; b *= c; c *= a;

} 46