Professional Documents
Culture Documents
.c
Lập trình
ng
co
an
Chương 2: Tổng quan về C/C++
th
o ng
du
2004, HOÀNG MINH SƠN
u
cu
1
CuuDuongThanCong.com https://fb.com/tailieudientucntt
Nội dung chương 2
2.1 Tổ chức chương trình C/C++
om
2.2 Biến và các kiểu dữ liệu cơ bản
.c
2.3 Các kiểu dữ liệu dẫn xuất trực tiếp
ng
co
2.4 Định nghĩa kiểu dữ liệu mới
an
2.5 Các lệnh điều khiển chương trình
th
2.6 Hàm và thư viện
o ng
du
u
cu
om
.c
ng
co
an
th
o ng
du
u
cu
om
Khai báo hàm
int gthua(int);
.c
Chương trình chính
void main() {
ng
char c = 'N'; Lời chú thích
int N = 1;
Khai báo biến
co
int kq;
do {
an
printf(“\n Nhap mot nguyen duong"); /* Viet ra man hinh*/
th
scanf("%d",&N); /* Nhap tu ban phim cho N*/
kq = gthua(N);
ng
printf(“\n Giai thua cua %d la %d", N, kq);
printf(“\n Ban co muon tiep tuc khong? Y/N");
o
c = getch();
du
int gthua(int n) {
int kq = 1;
while (n > 1) Định nghĩa hàm (thân hàm)
kq *= n--;
return kq;
}
om
int gthua(int);
.c
void main() {
ng
char c = 'N';
int N = 1;
co
do {
cout << “\nNhap mot so nguyen duong: “
an
cin >> N;
th
int kq = gthua(N);
cout << “\nGiai thua cua ” << N << “ la “ << kq
ng
cout << “\nBan co muon tiep tuc khong? Y/N";
c = getch();
o
} while (c == 'y' || c == 'Y');
du
}
u
int gthua(int n) {
cu
int kq = 1;
while (n > 1)
kq *= n--;
return kq;
}
om
Tránh sử dụng các từ khóa và tên kiểu cơ sở
Chỉ được dùng các ký tự sau: ‘A’..’Z’, ‘a’..’z’, ‘0’..’9’, ‘_’
.c
Chỉ được bắt đầu bằng chữ cái hoặc dấu _
ng
Phân biệt giữa chữ hoa và chữ thường.
co
Nên đặt tên ngắn gọn và có ý nghĩa (có tính mô tả)
an
2. Sau mỗi câu lệnh có chấm phảy (;)
th
ng
3. Đoạn { … } được coi là nhóm lệnh, không có dấu
o
chấm phảy sau đó, trừ khi khai báo kiểu
du
om
.c
auto double int struct
break else long switch
ng
case enum register typedef
co
char extern return union
an
const float short unsigned
th
continue for signed void
ng
default goto sizeof volatile
o
du
do if static while
u
cu
om
case catch char class
const const_cast continue default
.c
delete else extern do
ng
enum false double explicit
co
float dynamic_cast export for
friend goto if inline
an
int long mutable namespace
th
new operator private protected
ng
public register reinterpret_cast return
o
du
om
dịch riêng rẽ hoặc Build (F6) để kết hợp biên dịch và liên kết
cho toàn bộ dự án
.c
Các kiểu lỗi biên dịch (compile error):
ng
– Lỗi cú pháp: Sử dụng tên sai qui định hoặc chưa khai báo, thiếu
co
dấu chấm phảy ;, dấu đóng }
an
– Lỗi kiểu: Các số hạng trong biểu thức không tương thích kiểu, gọi
hàm với tham số sai kiểu
th
– …
ng
Các kiểu cảnh báo biên dịch (warning):
o
du
om
để tạo ra chương trình chạy cuối cùng *.exe
.c
Trong Visual studio .Net 2008: Gọi Build (F6)
ng
Lỗi liên kết có thể là do:
co
– Sử dụng hàm nhưng không có định nghĩa hàm
an
– Biến hoặc hàm được định nghĩa nhiều lần
th
– … ng
o
du
u
cu
om
without debugging hoặc Ctrl+F5
.c
Tìm lỗi:
ng
– Lỗi khi chạy là lỗi thuộc về phương pháp, tư duy, thuật toán,
co
không phải về cú pháp
– Lỗi khi chạy bình thường không được báo
an
th
– Lỗi khi chạy rất khó phát hiện, vì thế trong đa số trường hợp
cần tiến hành debug.
ng
Chạy Debug trong Visual studio .Net 2008:
o
du
om
Hệ điều hành
.c
Các CT khác
ng
Mã chương trình Đỉnh ngăn xếp
co
Dữ liệu toàn cục SP
an
n
th
Array_A
Vùng nhớ tự do
o ng
f
du
Ngăn xếp k
(tham biến, biến
u
i
cu
om
Biểu diễn dữ liệu: Thông qua biến hoặc hằng số, kèm
.c
theo kiểu
ng
Nội dung trong phần này:
co
– Các kiểu dữ liệu cơ bản
an
– Các phép toán áp dụng
th
– Tương thích và chuyển đổi kiểu
ng
– Khai báo biến, phân loại biến
o
du
u
cu
om
char 8 −127 to 127
.c
signed char 8 −127 .. 127
unsigned char 8 0 .. 255
ng
int 16/32 −32767 .. 32767
co
signed int 16/32 -nt-
unsigned int 16/32 0 .. 65535
an
short 16 −32767 .. 32767
th
signed short 16 ng nt
unsigned short 16 0 .. 65535
long 32 −2147483647 .. 2147483647
o
du
signed long 32 nt
unsigned long 32 0 .. 4294967295
u
om
Gán = X X X
+, -, *, /,
.c
Số học X X x
+=, -=, *=, /=
ng
%, %= X x
co
++, -- X x
an
So sánh >, <, >=, <=, X X X
th
==, != ng
Logic &&, ||, ! X X X
o
Logic bit &, |, ^, ~ X x
du
&=, |=, ^=
u
cu
om
chuyển đổi kiểu:
.c
– Giữa các kiểu số nguyên với nhau (lưu ý phạm vi giá trị)
ng
– Giữa các kiểu số thực với nhau (lưu ý độ chính xác)
co
– Giữa các kiểu số nguyên và số thực (lưu ý phạm vi giá trị và
độ chính xác)
an
– Kiểu bool sang số nguyên, số thực: true => 1, false => 0
th
– Số nguyên, số thực sang kiểu bool: 0 => true, 0 => false
ng
Nếu có lỗi hoặc cảnh báo => khắc phục bằng cách ép
o
du
– VD:
cu
i = int(5.1) % 2; //C
j = (int)5.1 + 2; // C++
om
int kq;
Chỉ khai báo, giá trị bất định
.c
double d;
long count, i=0; Khai báo kết hợp, chỉ i=0
ng
unsigned vhexa=0x00fa; Đặt giá trị đầu hexa
co
unsigned voctal=082; Đặt giá trị đầu octal -> 66 chứ không phải 82
an
C: Toàn bộ biến phải khai báo ngay đầu thân hàm
th
C++: Có thể khai báo tại chỗ nào cần
ng
Phân loại biến:
o
du
– Biến toàn cục: Khai báo ngoài hàm, lưu giữ trong vùng nhớ dữ liệu
chương trình
u
cu
– Biến cục bộ: Khai báo trong thân hàm, lưu giữ trong ngăn xếp
(vùng nhớ tự do)
– Tham biến: Khai báo trên danh sách tham số của hàm, lưu giữ
trong ngăn xếp
om
void main() {
char c = 'N';
.c
do {
cout<<“\nNhap so> 0:";
ng
cin>>N;
co
Biến cục bộ int kq = gthua(N);
...
an
} while (c == 'y' || c == 'Y')
th
}
Hai biến cục bộ ng
cùng tên ở hai phạm int gthua(int n) {
vi khác nhau,
o
int kq = 1;
du
return kq;
cu
Tham biến
om
Kiểu hằng
.c
Kiểu con trỏ
ng
Kiểu mảng
co
Kiểu tham chiếu (C++)
an
th
o ng
du
u
cu
om
– Cần hạn chế phạm vi sử dụng
.c
– Hoặc khi muốn sử dụng tên cụ thể thay cho hằng số nguyên
Ví dụ void main()
ng
{
co
enum Color {Red, Green, Blue};
enum WeekDay {Mon = 2,Tue, Wed, Thu, Fri, Sat, Sun = 1 };
an
//Tue=3, Wed=4…
th
int n=Red;
cout<<n; //in ra số 0
ng
Color c=Green;
o
n=c; //n=1;
du
}
u
cu
Lưu ý: không thể gán trực tiếp một giá trị nguyên cho một biến
enum mà phải ép kiểu
VD: c=2;//Error
c=Color(2);//OK
Chương 2: Tổng quan về C và C++ 20
CuuDuongThanCong.com https://fb.com/tailieudientucntt
2.3.2 Kiểu hằng (const)
Khi muốn một biến không bị thay đổi trong suốt
om
chương trình => khai báo hằng số
.c
ng
void main() {
co
const double pi = 3.1412;
an
const int x = 1;
pi = 3.14; // error
th
x = 2; // error
ng
}
o
du
u
cu
om
nhất định và lưu ở một vị trí cụ thể trong bộ nhớ
máy tính
.c
Con trỏ là một biến mang địa chỉ của một ô nhớ
ng
(của một biến khác hoặc một hàm)
co
Cách khai báo: Data_type* pointer_var_name;
an
int x = 2;
int* p = &x;
th
// p chua dia chi cua x
ng
*p = 3; // x=3
o
int y;
du
*p = 5; // y = 5, x = 3
cu
om
Nếu khai báo con trỏ mà không khởi tạo, mặc định con trỏ mang
.c
một địa chỉ bất định
ng
Để khởi tạo giá trị cho con trỏ, ta có thể cho nó trỏ vào một địa
co
chỉ nhớ cụ thể hoặc địa chỉ của một biến khác thông qua toán tử
lấy địa chỉ &
an
Con trỏ có thể mỗi lúc đại diện cho một biến dữ liệu khác, do đó
th
địa chỉ mà con trỏ mang có thể thay đổi được.
ng
Dùng toán tử * để truy nhập nội dung của biến mà con trỏ trỏ
o
du
tới, có thể đọc hoặc thay đổi nội dung của biến đó.
Không bao giờ sử dụng toán tử truy nhập nội dung, nếu con trỏ
u
cu
chưa mang một địa chỉ ô nhớ mà chương trình có quyền kiểm
soát
om
...
.c
ng
địa chỉ cuối
co
địa chỉ đầu
an
Số phần tử của mảng: N
th
Số lượng các phần tử của mảng (tĩnh) là cố định
ng
Các phần tử có cùng kiểu
o
du
om
Khai báo không khởi tạo:
.c
int a[5];
enum {index = 5};
ng
double b[index];
co
const int N = 2;
an
char c[N];
th
Khai báo với số phần tử và khởi tạo giá trị các phần tử
ng
int d[3]= {1, 2, 3};
o
double e[5]= {1, 2, 3};
du
om
động xác định
int a[]= {1, 2, 3, 4, 5};
.c
double b[]= {1, 2, 3};
ng
double c[]= {0};
co
char s[]= {‘a’};
an
Khai báo mảng nhiều chiều
th
double M[2][3]; ng
int X[3][]={{1,2},{3,4},{5,6}};
o
short T[3][2]={1,2,3,4,5,6};
du
u
cu
om
mà thực chất là một mảng
Phân biệt chuỗi ký tự thường và chuỗi ký tự kết 0
.c
ng
char s1[]= {‘H',‘E',‘L',‘L',‘O‘};
co
char s2[]= "HELLO";
wchar_t s3[]= L"HELLO";
an
th
Đa số các hàm trong thư viện C làm việc với chuỗi ký
ng
tự kết 0
o
Với C++, chuỗi ký tự được định nghĩa bằng lớp
du
0
cu
om
mảng.
.c
void main() {
ng
int a[3]; //a co 3 phan tu, gia tri chua xac dinh
co
int* p;
p = a; //p tro den a[0]
an
p = &a[0]; //tuong tu nhu tren
th
*p = 1; //a[0]=1 ng
++p; //p tro den a[1]
o
*p = 2; //a[1]=2
du
*p = 3; //a[2]=3
cu
om
Số phần tử của mảng (tĩnh) là cố định (khi khai báo phải là
hằng số), không bao giờ thay đổi được
.c
Có thể truy cập các phần tử mảng thông qua tên mảng kèm theo
ng
chỉ số hoặc thông qua biến con trỏ (theo địa chỉ của từng phần
co
tử)
Biến mảng (tĩnh) thực chất là một con trỏ hằng, mang địa chỉ
an
của phần tử đầu tiên
th
Có thể đặt giá trị đầu cho các phần tử của mảng qua danh sách
ng
khởi tạo.
o
Không gán được hai mảng cho nhau. Nếu cần sao chép hai
du
Không bao giờ được phép truy nhập với chỉ số nằm ngoài phạm
cu
om
của biến này)
Biến tham chiếu không được cấp phát bộ nhớ, không có địa chỉ
.c
riêng.
ng
Ý nghĩa: sử dụng chủ yếu trong truyền tham số cho hàm
co
void main() {
an
int a = 1;
th
int& r = a; //r tham chieu den a ng
r = 2; // a = 2
o
du
int b = 0;
r = b; //r = 0, a=0
r = 3; //r = a= 3, b=0
}
Chương 2: Tổng quan về C và C++ 30
CuuDuongThanCong.com https://fb.com/tailieudientucntt
Hằng tham chiếu
Có thể tham chiếu đến một biến hoặc một hằng
om
Không cho phép dùng hằng tham chiếu để thay đổi giá
.c
trị vùng nhớ mà nó tham chiếu.
ng
Ý nghĩa: thường được sử dụng làm đối của hàm để cho
co
phép hàm sử dụng giá trị của các tham số trong lời gọi
an
hàm nhưng tránh không làm thay đổi giá trị của các
th
tham số ng
VD: int n=10, m;
o
du
n++;//OK
cu
m=2*n;//m=20
r=r+1;//Error
Chương 2: Tổng quan về C và C++ 31
CuuDuongThanCong.com https://fb.com/tailieudientucntt
Kết luận về biến tham chiếu
Khi khai báo phải chỉ rõ nó tham chiếu đến biến nào.
om
Có thể tham chiếu đến một phần tử của mảng
.c
Không cho phép khai báo mảng tham chiếu
ng
Có thể tham chiếu đến một hằng. Khi đó nó sẽ sử dụng
co
vùng nhớ của hằng và nó có thể làm thay đổi giá trị
an
chứa trong vùng nhớ này.
th
o ng
du
u
cu
om
liệu có sẵn, không định nghĩa một kiểu mới
.c
Ý nghĩa: đưa tên mới dễ nhớ, phù hợp với ứng dụng
ng
cụ thể.
co
Cú pháp: typedef Kieu_dang_co Ten_moi
an
void main()
th
{
typedef int tuoi; /* Tạo tên mới cho kiểu int là “tuoi" */
ng
typedef char ten[30]; /*Tạo tên mới cho kiểu char là “ten"*/
o
tuoi sv_tuoi, gv_tuoi;
du
...
cu
om
– Tập hợp những dữ liệu dùng để mô tả một đối tượng, truy nhập
theo tên (biến thành viên).
.c
– Thông dụng nhất trong C, ý nghĩa được mở rộng trong C++
ng
Hợp nhất (union):
co
– Một tên kiểu chung cho nhiều dữ liệu khác nhau (chiếm cùng
an
chỗ trong bộ nhớ).
th
– Ít thông dụng trong cả C và C++
ng
Lớp (class):
o
du
– mở rộng struct cũ
u
om
.c
struct struct_name
{
ng
//khai báo các thành phần của struct
co
type1 field1;
type2 field2;
an
...
th
} [bien_co_kieu_struct_name];
ng
Cách truy nhập vào các thuộc tính:
o
du
Ten_bien_kieu_struct.Ten_thuoc_tinh.
u
Khởi tạo giá trị cho biến struct giống như với mảng,
cu
đặt các giá trị trong dấu { }, phân cách nhau bằng dấu
“,”.
om
#include <iostream.h>
.c
struct emp
ng
{
co
int MaSo;
char ten[35];
an
};
th
void main() ng
{
o
struct emp e1={100,”Nguyen X”};
du
cout<<“Ename: ”<<e1.ten;
cu
om
Định nghĩa kiểu cấu trúc bằng cách khai báo tên các biến
.c
thành viên. Định nghĩa kiểu cấu trúc chưa phải là định nghĩa
ng
các biến cụ thể, vì thế không được đặt giá trị đầu cho các biến
co
Kích cỡ của cấu trúc >= tổng kích cỡ các thành viên
Truy cập một biến cấu trúc:
an
tên_biến_cấu_trúc.tên_biến_thành_viên
th
Các kiểu cấu trúc có thể lồng vào nhau, trong cấu trúc có thể sử
ng
dụng mảng, một mảng có thể có các phần tử là cấu trúc, v.v...
o
du
Các biến có cùng kiểu cấu trúc có thể gán cho nhau, có thể sử
u
Có thể sử dụng con trỏ để truy nhập dữ liệu cấu trúc thông qua
toán tử toán tử (*.) hoặc (->)
om
//Khai báo các thành phần của union
.c
Type1 field1;
Type2 field2;
ng
...
co
};
an
Ví dụ: union VD
th
{
unsigned long u;
ng
unsigned char a[4];
o
};
du
void main()
{ VD vd1;
u
vd1.u=0xDDCCBBAA;
cu
cout<<vd1.a[0];
cout<<vd1.a [1];
cout<<vd1.a[2];
cout<<vd1.a [3];
}
Chương 2: Tổng quan về C và C++ 38
CuuDuongThanCong.com https://fb.com/tailieudientucntt
Kết luận về hợp nhất
Hợp nhất (union) là một tập hợp (không có cấu trúc chặt chẽ)
chứa các biến sử dụng chung ô nhớ, ở mỗi ngữ cảnh chỉ sử dụng
om
một biến riêng biệt
.c
Union thường được sử dụng khi dữ liệu đầu vào có thể có kiểu
ng
khác nhau
co
Các thành viên của một union không liên quan đến nhau, không
cùng nhau tạo thành một thực thể thống nhất
an
Kích cỡ của union bằng kích cỡ của biến lớn nhất
th
Khai báo kiểu union tương tự như khai báo struct, nhưng ý
ng
nghĩa khác hẳn
o
du
Truy nhập biến thành viên cũng tương tự như struct, có thể qua
u
Union có thể chứa struct, struct có thể chứa union, union có thể
chứa mảng, các phần tử của mảng có thể là union.
om
Lệnh switch ... case
.c
Lệnh while(dieu_kien)...
ng
Lệnh do ... while(dieu_kien)
co
Lệnh for ...
an
Lệnh break thoát khỏi một vòng lặp
th
ng
Lệnh continue
o
Lệnh goto
du
u
cu
om
.c
if ( expression )
stmt1;
ng
co
Hoặc
an
th
if ( expression ) ng
stmt1;
else
o
du
stmt2;
u
Khi số câu lệnh trong mỗi nhánh rẽ lớn hơn 1 thì đặt
cu
om
cout << "Passed";
if (npoints >= 80 && npoints <= 90) {
.c
grade = ‘A’;
ng
cout << grade;
}
co
an
if (npoints >= 90)
th
cout << ‘A’; ng
else if (npoints >= 80)
cout << ‘B’;
o
du
om
.c
switch( expression ) switch( c )
{ {
ng
case constant-expr1: case 'Y':
co
stmt; cout<< "Yes" ;
break;
break;
an
case constant-expr2:
stmt; case 'N':
th
break;
ng cout<<"No" ;
... break;
default: default:
o
du
om
.c
switch( c )
ng
{
co
case 'Y':
case 'y':
an
cout<< "Yes" ;
th
break;
case 'N': case 'n':
ng
/* 2 điều khiển trên cùng 1 dòng */
o
cout<< "No";
du
break;
u
default:
cu
cout<<"What?";
}
om
Cú pháp:
.c
while ( expression )
stmt ;
ng
co
Lệnh (khối lệnh) stmt chỉ được thực hiện khi
an
expression là đúng.
Ví dụ:
th
ng
x = 1;
o
du
while ( (x * 5) >= (x * x) )
{
u
cu
cout<<x;
x++;
}
om
do
.c
stmt ;
ng
while ( expression );
co
Lệnh (khối lệnh) stmt được thực hiện cho đến khi
an
expression còn đúng.
Ví dụ:
th
ng
lng = 0;
o
do
du
{
u
c = getchar();
cu
++lng;
}
while ( c != '\n' );
cout<< "line length is: “<<lng ;
Chương 2: Tổng quan về C và C++ 46
CuuDuongThanCong.com https://fb.com/tailieudientucntt
Cấu trúc for
Cú pháp:
om
for ( init-expr; cont-expr; loop-expr )
.c
stmt;
ng
Thực hiện:
co
Tính toán init-expr nếu có
an
Tính toán cont-expr nếu có
th
Nếu cont-expr là true hoặc được bỏ qua thì thực hiện stmt,
ng
sau đó loop-expr được thực hiện
o
Lặp lại bước 2 đến khi cont-expr là false
du
u
cu
om
.c
/* Bảng cửu chương*/ 9 times 0 is 0
ng
const int max=9 9 times 1 is 9
co
for ( i = 0; i <= max; i++ ) 9 times 2 is 18
9 times 3 is 27
an
{
th
for ( j = 0; j <= max; j++ ) 9 times 4 is 36
{
ng
9 times 5 is 45
cout<<i<< “ times”<<j<<“ is”<<i*j<“\n”;
o
9 times 6 is 54
du
} 9 times 7 is 63
u
}
9 times 8 is 72
cu
9 times 9 is 81
om
Một đơn vị tổ chức chương trình, một đoạn mã
.c
chương trình có cấu trúc để thực hiện một chức
năng nhất định, có giá trị sử dụng lại
ng
co
Các hàm có quan hệ với nhau thông qua lời gọi, các
biến tham số (đầu vào, đầu ra) và giá trị trả về
an
th
Cách thực hiện cụ thể một hàm phụ thuộc nhiều vào
ng
dữ kiện (tham số, đối số của hàm):
o
– Thông thường, kết quả thực hiện hàm mỗi lần đều giống
du
– Một hàm không có tham số thì giá trị sử dụng lại rất thấp
Trong C/C++: Không phân biệt giữa thủ tục và hàm,
cả đoạn mã chương trình chính cũng là hàm
Chương 2: Tổng quan về C và C++ 49
CuuDuongThanCong.com https://fb.com/tailieudientucntt
Ví dụ
Yêu cầu bài toán: Tính tổng một dãy số nguyên (liên
om
tục) trong phạm vi do người sử dụng nhập. In kết quả
.c
ra màn hình.
ng
Các nhiệm vụ:
co
– Nhập số nguyên thứ nhất:
an
Yêu cầu người sử dụng nhập
th
Nhập số vào một biến
ng
– Nhập số nguyên thứ hai
o
du
om
int a, b;
char c;
.c
do {
cout << “Nhap so nguyen thu nhat: ";
ng
cin >> a;
co
cout << “Nhap so nguyen thu hai: ";
cin >> b;
an
int tong = 0;
for (int i = a; i <= b; ++i)
th
tong += i;
ng
cout << "Tong tu " << a << " den " << b
<< " la " << tong << endl;
o
cout << “ban co muon tinh tiep? (Y/N):";
du
cin >> c;
} while (c == 'y' || c == 'Y');
u
}
cu
om
int Nhap();
.c
int Tinh_tong(int,int);
void Hien_thi(int a, int b, int kq);
ng
void main() {
co
char c;
do {
an
int a = Nhap();
th
int b = Nhap();
int T = Tinh_tong(a,b);
ng
Hien_thi(a,b,T);
cout << “Ban co muon tinh tiep? (Y/N):";
o
du
cin >> c;
} while (c == 'y' || c == 'Y');
u
}
cu
om
int Nhap() {
cout << “Nhap mot so nguyen: ";
.c
int N;
cin >> N;
ng
return N;
}
co
int Tinh_tong(int a, int b) {
an
int T = 0;
th
for (int i = a; i <= b; ++i)
T += i;
ng
return T;
o
}
du
cout << "Tong tu " << a << " den " << b
cu
om
Chương trình dễ mở rộng hơn
.c
Có giá trị sử dụng lại
ng
Mã nguồn dài hơn
co
Mã chạy lớn hơn
an
th
Chạy chậm hơn ng
o
du
om
Kiểu trả về Tên hàm Tham biến (hình thức)
.c
int Tinh_tong(int a, int b) {
ng
int T = 0;
co
for (int i = a; i <= b; ++i)
an
T += i;
return T;
}
th
ng
Khai báo hàm thuần túy: không tạo mã hàm
o
du
om
– Khi cần sử dụng hàm (gọi hàm)
.c
– Trình biên dịch cần lời khai báo hàm để kiểm tra lời gọi hàm
đúng hay sai về cú pháp, về số lượng các tham số, kiểu các
ng
tham số và cách sử dụng giá trị trả về.
co
int Tinh_tong(int a, int b);
an
– Có thể khai báo hàm độc lập với việc định nghĩa hàm (tất
th
nhiên phải đảm bảo nhất quán) ng
Có thể định nghĩa hàm sau lời gọi hàm
o
Gọi hàm: yêu cầu thực thi mã hàm với tham số thực tế (tham
du
trị)
u
int x = 5;
cu
om
Một hàm phải được khai báo trước lời gọi đầu tiên
.c
trong một tệp tin mã nguồn
ng
Nếu sử dụng nhiều hàm thì sẽ cần rất nhiều dòng mã
co
khai báo (mất công viết, dễ sai và mã chương trình
an
lớn lên?):
th
– Nếu người xây dựng hàm (định nghĩa hàm) đưa sẵn tất cả
ng
phần khai báo vào trong một tệp tin => Header file (*.h,
o
*.hx,...) thì người sử dụng chỉ cần bổ sung dòng lệnh
du
#include <filename>
u
cu
– Mã chương trình không lớn lên, bởi khai báo không sinh mã!
Một hàm có thể khai báo nhiều lần tùy ý!
om
hoặc tách ra một tệp tin riêng. Trong Visual C++:
.c
*.c => C compiler,
ng
*.cpp => C++ compiler
Một hàm đã có lời gọi thì phải được định nghĩa chính xác 1 lần
co
trong toàn bộ (dự án) chương trình, trước khi gọi trình liên kết
an
(lệnh Build trong Visual C++)
th
Đưa tệp tin mã nguồn vào dự án, không nên:
ng
#include “xxx.cpp”
o
Một hàm được định nghĩa sẵn bằng C, C++, hợp ngữ hoặc bằng
du
một ngôn ngữ khác và dùng trong C/C++ => Sử dụng hàm
u
om
...
} Tham biến
.c
(hình thức)
ng
int x = 5;
co
int k = Tinh_tong (x, 10);
an
...
th
Tham số
(thực tế)
o ng
du
int a = 2;
u
k = Tinh_tong (a,x);
cu
om
void main() {
.c
int x = 5;
ng
int k = Tinh_tong(x, 10);
co
... SP
b = 10
an
} a = 5
SP
th
k =k 45
// Dinh nghia ham x = 5
ng
int Tinh_tong(int a, int b) {
o
Ngăn xếp
...
du
u
cu
om
void Nhap(int N) {
cin >> N;
.c
}
ng
co
void main() {
an
int x = 5;
th
cout<< “Hay nhap so nguyen: ”;
Nhap(x);
ng
cout << “Bay gio x la " << x;
o
du
...
}
u
cu
om
Tham biến chỉ nhận được bản sao của biến đầu vào
.c
(tham số thực tế)
ng
Thay đổi tham biến chỉ làm thay đổi vùng nhớ cục bộ,
co
không làm thay đổi biến đầu vào
an
Tham biến chỉ có thể mang tham số đầu vào, không
chứa được kết quả (tham số ra)
th
ng
Truyền giá trị trong nhiều trường hợp kém hiệu quả
o
du
om
// Goi ham
.c
void main() {
SP
int a[] = {1, 2, 3, 4}; k =k 10
ng
int k = Tong_mang(a,4); N=4
co
... p=00A0
an
SP
} k =k 10
th
ng a[3]=4
a[2]=3
// Dinh nghia ham
a[1]=2
o
a[0]=1
int *p2 = p + N, k = 0; 00A0
u
cu
om
// Goi ham
.c
void main() {
int a[] = {1, 2, 3, 4};
ng
int k = Tong_mang(a,4);
co
... Bản chất giống truyền
an
địa chỉ
}
th
ng
// Dinh nghia ham
o
int *p2 = p + N, k = 0;
u
cu
om
void Nhap(int* pN) {
.c
cin >> *pN;
ng
}
co
void main() {
an
int x = 5;
cout<<“Nhap so nguyen:“;
th
ng
Nhap(&x);
o
du
}
Kết quả: x thay đổi giá trị sau đó
om
vào ô nhớ, không qua bản sao)
.c
Khi kích cỡ kiểu dữ liệu lớn => tránh sao chép dữ liệu
ng
vào ngăn xếp
co
Truyền tham số là một mảng => bắt buộc truyền địa
an
chỉ
th
Lưu ý: Sử dụng con trỏ để truyền địa chỉ của vùng
ng
nhớ dữ liệu đầu vào. Bản thân con trỏ có thể thay đổi
o
du
được trong hàm nhưng địa chỉ vùng nhớ không thay
u
đổi (nội dung của vùng nhớ đó thay đổi được)
cu
om
void Nhap(int& N) {
.c
cin >> N;
ng
}
co
an
void main() {
th
int x = 5;
cout<<“Nhap so nguyen:“;
ng
Nhap(x);
o
du
...
cu
}
Kết quả: x thay đổi giá trị sau đó
om
.c
ng
co
an
th
o ng
du
u
cu
om
Khi cần thay đổi "biến đầu vào" (truy nhập trực tiếp
.c
vào ô nhớ, không qua bản sao)
ng
Một tham biến tham chiếu có thể đóng vai trò là đầu
co
ra (chứa kết quả), hoặc có thể vừa là đầu vào và đầu
an
ra
th
Khi kích cỡ kiểu dữ liệu lớn => tránh sao chép dữ liệu
ng
vào ngăn xếp.
o
du
u
cu
om
Có thể trả về kiểu:
.c
– Giá trị
ng
– Con trỏ (địa chỉ)
co
– Tham chiếu
an
Tuy nhiên, cần rất thận trọng với trả về địa chỉ hoặc
th
tham chiếu: ng
– Không bao giờ trả về con trỏ hoặc tham chiếu vào biến cục
o
bộ
du
– Không bao giờ trả về con trỏ hoặc tham chiếu vào tham
u
om
int k = 0;
for (int i=a; i <= b; ++i)
.c
k +=i;
ng
return k; SP
k =45
co
} b = 10
an
a = 5
SP
th
void main() { kk==0
45
int x = 5, k = 0; x = 5
ng
k = Tinh_tong(x,10); Ngăn xếp
o
du
...
u
} 45
cu
om
Viết chương trình ứng dụng các hàm trên.
.c
ng
co
an
th
o ng
du
u
cu
om
chiếu:
.c
– Tránh sao chép dữ liệu lớn không cần thiết
– Để có thể truy cập trực tiếp và thay đổi giá trị đầu ra
ng
Có thể trả về con trỏ hoặc tham chiếu vào đâu?
co
– Vào biến toàn cục
an
th
– Vào tham số truyền cho hàm qua địa chỉ hoặc qua tham chiếu
ng
– Nói chung: vào vùng nhớ mà còn tiếp tục tồn tại sau khi kết
thúc hàm
o
du
u
cu
om
void func(int a, int b=0, int c=0)
.c
{ …… }
ng
void main()
co
{
an
int x=4, y=5, z=6;
func(x,y,z);//OK
th
o ng
func(x,y);//OK
du
func(x);//OK
u
cu
om
số (tính từ trái sang phải)
.c
Tham số thiếu vắng trong lời gọi hàm sẽ tương ứng với
ng
các tham biến mặc định cuối cùng (tính từ trái sang
co
phải)
an
th
o ng
du
u
cu
om
nhỏ nhất của một mảng. Viết một chương trình ứng
dụng hàm đó?
.c
ng
co
an
th
o ng
du
u
cu
om
dụ:
.c
int max(int a, int b);
ng
double max(double a, double b);
co
double max(double a, double b, double c);
an
double max(double *seq, int n);
th
Mục đích của nạp chồng tên hàm: ng
– Đơn giản hóa cho người xây dựng hàm trong việc chọn tên
o
(thay vì maxInt, maxDouble, maxDouble3,
du
maxDoubleSequence,...)
u
cu
– Đơn giản hóa cho người sử dụng hàm, chỉ cần nhớ 1 tên quen
thuộc thay cho nhiều tên phức tạp
om
}
double max(double a, double b) { // (2)
.c
return (a > b)? a : b;
ng
}
double max(double a, double b, double c); { // (3)
co
if (a < b) a = b;
an
if (a < c) a = c;
return a;
}
th
ng
double max(double *seq, int n) { // (4)
o
int i = 0, kq = seq[0];
du
while (i < n) {
u
++i;
}
return kq;
}
om
double max(double a, double b, double c); // (3)
.c
double max(double *seq, int n); // (4)
ng
void main() {
co
int k = max(5,7); // call?
double d = max(5.0,7.0); // call?
an
double a[] = {1,2,3,4,5,6};
th
d = max(d, a[1], a[2]); // call?
ng
d = max(a, 5); // call?
d = max(5,7); // call?
o
du
Đẩy trách nhiệm kiểm tra và tìm hàm phù hợp cho
compiler!
om
một file/ trong một thư viện hoặc sử dụng trong
.c
cùng một chương trình phải khác nhau ít nhất về:
ng
– Số lượng các tham số, hoặc
co
– Kiểu của ít nhất một tham số (int khác short, const int
khác int, int khác int&, ...)
an
Không thể chỉ khác nhau ở kiểu trả về
Tại sao vậy? th
o ng
– Compiler cần có cơ sở để quyết định gọi hàm nào
du
– Dựa vào cú pháp trong lời gọi (số lượng và kiểu các tham số
u
thực tế) compiler sẽ chọn hàm có cú pháp phù hợp nhất
cu
– Khi cần compiler có thể tự động chuyển đổi kiểu theo chiều
hướng hợp lý nhất (vd short=>int, int => double)
om
.c
không cao, đặc biệt khi mã thực thi hàm ngắn vì
ng
– Các thủ tục như nhớ lại trạng thái chương trình, cấp phát bộ
co
nhớ ngăn xếp, sao chép tham số, sao chép giá trị trả về, khôi
phục trạng thái chương trình mất nhiều thời gian
an
– Nếu mã thực thi hàm ngắn thì sự tiện dụng không bõ so
th
với sự lãng phí thời gian
o ng
du
u
cu
om
đầu dòng khai báo và định nghĩa hàm
.c
inline int max(int a, int b) {
ng
return (a > b)? a : b;
}
co
Hàm inline khác gì hàm bình thường?
an
– "Hàm inline" thực chất không phải là một hàm!
th
– Khi gọi hàm thì lời gọi hàm được thay thế một cách thông
ng
minh bởi mã nguồn định nghĩa hàm, không thực hiện
o
du
om
– Tiện dụng như hàm bình thường
– Hiệu suất như viết thẳng mã, không gọi hàm
.c
– Tin cậy, an toàn.
ng
Nhược điểm của hàm inline:
co
– Nếu gọi hàm nhiều lần trong chương trình, mã chương trình
an
có thể lớn lên nhiều (mã thực hiện hàm xuất hiện nhiều lần
th
trong chương trình)
ng
– Mã định nghĩa hàm phải để mở => đưa trong header file
o
du
– Mã định nghĩa hàm nhỏ (một vài dòng lệnh, không chứa
cu
vòng lặp)
– Yêu cầu về tốc độ đặt ra trước dung lượng bộ nhớ