Tài liệu Giáo trình: Lập trình cơ bản (Phần 2): Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
52 
CHƯƠNG 4: HÀM 
1. Khái niệm hàm 
1.1Khái niệm và phân loại 
Một chương trình viết trong ngôn ngữ C là một dãy các hàm, trong đó có một 
hàm chính(hàm main). Hàm chia các bài toán lớn thành các công việc nhỏ, có thể có 
những đoạn chương trình viết lặp đi lặp lại nhiều lần, để tránh rườm rà và mất thời 
gian khi viết chương trình; người ta thường phân chia chương trình thành nhiều 
module, mỗi module giải quyết một công việc vào đó. Thứ tự các hàm trong chương 
trình là bất kỳ, song chương trình bao giờ cũng đi thực hiện từ main(). 
 Trong C, chương trình con được gọi là hàm. Hàm trong C có thể trả về kết quả 
thông quan tên hàm hay có thể không trả về kết quả. 
 Hàm có hai loại: Hàm chuẩn và hàm tự định nghĩa. Trong chương này ta chú trọng 
đến cách định nghĩa hàm và cách sử dụng các hàm đó. 
 Hàm thư viện 
Hàm thư viện là những hàm đã được định nghĩa sẵn trong một thư viện nào đó, 
muốn sử dụng các hàm thư...
                
              
                                            
                                
            
 
            
                 53 trang
53 trang | 
Chia sẻ: honghanh66 | Lượt xem: 1151 | Lượt tải: 0 
              
            Bạn đang xem trước 20 trang mẫu tài liệu Giáo trình: Lập trình cơ bản (Phần 2), để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
52 
CHƯƠNG 4: HÀM 
1. Khái niệm hàm 
1.1Khái niệm và phân loại 
Một chương trình viết trong ngôn ngữ C là một dãy các hàm, trong đó có một 
hàm chính(hàm main). Hàm chia các bài toán lớn thành các công việc nhỏ, có thể có 
những đoạn chương trình viết lặp đi lặp lại nhiều lần, để tránh rườm rà và mất thời 
gian khi viết chương trình; người ta thường phân chia chương trình thành nhiều 
module, mỗi module giải quyết một công việc vào đó. Thứ tự các hàm trong chương 
trình là bất kỳ, song chương trình bao giờ cũng đi thực hiện từ main(). 
 Trong C, chương trình con được gọi là hàm. Hàm trong C có thể trả về kết quả 
thông quan tên hàm hay có thể không trả về kết quả. 
 Hàm có hai loại: Hàm chuẩn và hàm tự định nghĩa. Trong chương này ta chú trọng 
đến cách định nghĩa hàm và cách sử dụng các hàm đó. 
 Hàm thư viện 
Hàm thư viện là những hàm đã được định nghĩa sẵn trong một thư viện nào đó, 
muốn sử dụng các hàm thư viện thì phải khai báo thư viện trước khi sử dụng bằng 
lệnh #inlcude 
 Hàm người dùng 
Hàm người dùng là những hàm do người lập trình tự tạo ra nhằm đáp ứng nhu 
cầu xử lý của mình. 
Một hàm khi được định nghĩa thì có thể sử dụng bất cứ đâu trong chương trình. 
Trong C, một chương trình bắt đầu thực thi bằng hàm main. 
Chương trình con được dùng để tôí ưu hóa việc tổ chức chương trình, chia một 
chương trình lớn thành nhiều công việc độc lập nhỏ. Dùng chương trình con thực 
hiện các công việc nhỏ, tạo thành mô-đun. Khi đó nhiệm vụ chương trình chính chỉ là 
cung cấp dữ liệu đầu vào cho các mô-đun để hoàn thành công việc của mình. Một 
chương trình viết theo cách này gọi là chương trình cấu trúc. 
Có thể minh họa chương trình con như hình sau : 
Chương trình 
con thực hiện 
công việc A 
Dữ liệu đưa vào để thực 
hiện công việc A 
Dữ liệu kết quả 
của công việc A 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
53 
Hình 4.1.1 : Hình ảnh minh họa nhiệm vụ của chương trình con 
Để nhận các dữ liệu đưa vào cho chương trình con và nếu có thể chứa dữ liệu 
kết quả ra chúng ta phải sử dụng tham số (parameters) của chương trình con. 
 Tham số tồn tại dưới hai hình thức đó là tham số thực và tham số hình thức. 
Tham số hình thức là tham số để khai báo và xây dựng trương trình con, còn tham số 
thực để xác định dữ liệu đưa vào khi gọi chương trình con. 
 Trong một số ngôn ngữ lập trình cung cấp hai loại chương trình con riêng biệt 
đó là hàm(function) và thủ tục (procedures) nhưng trong C chỉ cung cấp một loại đó 
là hàm 
Để tạo một hàm chúng ta cần xác định 
- Hàm tạo ra sẽ thực hiện công việc gì ? 
- Sau khi thưc hiện song có cần trả về một dữ liệu hay nhiều dữ liệu không ? 
- Để thực hiện được công việc đó ta cần những dữ liệu nào ? 
1.2 Quy tắc hoạt động của hàm 
Khi gặp một lời gọi hàm, thì hàm sẽ được thực hiện theo trình tự sau: 
 Cấp phát bộ nhớ cho các đối và các biến cục bộ. 
 Gán giá trị của các tham số thực cho các đối tượng tương ứng. 
 Thực hiện các câu lệnh trong thân hàm. 
 Khi gặp câu lệnh return hoặc dấu } cuối cùng của thân hàm thì máy sẽ xóa các 
đối, các biến cục bộ và thoát khỏi hàm. 
Chú ý: 
 Số tham số thực sự phải bằng số tham số hình thức (đối của hàm) và kiểu của 
tham số thực phải cùng kiểu với tham số hình thức tương ứng. 
 Nếu trở về từ một câu lệnh return có chứa biểu thức thì giá trị của biểu thức 
được gán cho hàm. Giá trị của hàm sẽ được sử dụng trong biểu thức chứa nó. 
2. Xây dựng hàm 
2.1 Định nghĩa hàm 
 Khai báo hàm 
Khai báo hàm được thực hiện ở phần đầu chương trình, khai báo để chỉ cho 
máy biết các thông tin về hàm bao gồm : kiểu dữ liệu trả về có hay không, tên hàm, 
các tham số bao gồm kiểu và tên của từng tham số. 
Cú pháp khai báo như sau : 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
54 
Tên_kiểu_trả_về tên_hàm(kiểu1 tham_số1, kiểu2 tham_số2 ..... ) ; 
Trong đó : 
- Tên kiểu trả về : là một tên kiểu dữ liệu quy định kết quả trả về là khiểu gì. 
- Tên hàm : Tự đặt theo quy định đặt tên của ngôn ngữ C. 
- Kiểu1 tham_số1 : xác định tên của tham số thứ nhất và kiểu của tham số đó,... 
Nếu có nhiều tham số, mỗi tham số phân cách nhau bởi dấu phẩy (,) 
Ví dụ: 
 int sum(int a , int b) ; 
 float max(float x, float y); 
Nếu trong hàm không có dữ liệu trả về thì viết kiểu trả về là void nếu không có 
tham số thì bỏ trống và phải có cặp dấu đóng mở ngoăc () sau tên hàm. 
Ví dụ: 
 void hien(); 
 Xây dựng hàm 
Sau khi khai báo xong hàm chúng ta có thể viết lệnh thực hiện công việc đặt ra cho 
chương trình con. 
Cú pháp: 
Tên_kiểu_trả_về tên_hàm(kiểu1 tham_số1,kiểu2 tham_số2 ..... ) 
 { 
 Các câu lệnh thực hiện công việc đặt ra cho hàm. 
} 
Khi cần kết thúc thực hiện hàm và trả về dữ liệu nào đây, chúng ta viết lệnh return 
vào vị trí cần thiết nhất trong hàm. 
 Cú pháp: 
 return giá-trị-dữ-liệu-trả-về; 
Ví dụ: 
 int sum(int a, int b) 
 { 
 return a+b; 
} 
 Hoặc 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
55 
 float max(float x, float y) 
 { 
 if(x>y) 
 return x; 
 else 
 return y; 
} 
Đối với hàm có kiểu void có thể không cần lệnh return 
 Ví dụ: 
 void hien() 
 { 
 printf(“ho va ten: Nguyen Van Nam”); 
 printf(“Ngay sinh :12\08\2014”); 
 printf(“que quan : Yen Bai”); 
} 
Chú ý: 
Thông thường với những chương trình đơn giản có ít chương trình con thì người ta 
viết lệnh cho hàm ngay tại nơi khai báo. 
2.2 Sử dụng hàm 
Một hàm khi định nghĩa thì chúng vẫn chưa được thực thi trừ khi ta có một lời gọi 
đến hàm đó. Khi thực hiện chương trình máy sẽ thực hiện các lệnh trong chương 
trình chính(hàm main), do đó để yêu cầu máy thực hiện công việc của chương trình 
con ta phải viết lệnh gọi chương trình con với cú pháp sau. 
Cú pháp: 
 ([Danh sách các tham số]) 
Lời gọi này có thể là một câu lệnh độc lập hoặc đặt trong biểu thức, nếu đặt 
trong biểu thức thì hàm đó phải có giá trị trả về để thực hiện tính toán biểu thức đó. 
Ví dụ: 
 printf(“Tong hai so 5 va 6 la: %d”,tong(5,6)); 
 Hoặc: 
 float x ; 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
56 
 x = max(a,b) ; 
Hoăc: hien(); 
Chú ý: 
Thông thường lời gọi hàm được viết trong chương trình chính, tuy nhiên có thể 
viết trong chương trình con khác. Các chương trình con có thể gọi lẫn nhau. 
3. Các tham số của hàm 
3.1 Phân biệt các loại tham số 
Trong lập trình, tham số là biến được thu nhận bởi một chương trình con. Tại 
thời gian chạy, chương trình con sử dụng các giá trị được gán cho các tham số để 
thay đổi cách ứng xử của mình. Hầu hết các ngôn ngữ lập trình có thể định nghĩa 
các chương trình con không có tham số hoặc chấp nhận một vài tham số. 
Tham số hình thức: 
Là biến được liệt kê trong danh sách tham số (thường nằm tại phần đầu của 
định nghĩa chương trình con). 
Tham số thực sự : Là giá trị cụ thể của biến đó tại thời gian chạy. 
Để phân biệt rõ hai khái niệm trên, xét ví dụ dưới đây: 
int sum(int gt1, int gt2) 
{ 
return (gt1+gt2); 
} 
Hàm sum nhận hai tham số hình thức: gt1và gt2. Nó lấy tổng của các giá trị 
được truyền vào các tham số này và trả về kết quả cho nơi gọi hàm (bằng cách sử 
dụng một kỹ thuật được cung cấp tự động bởi trình biên dịch C). Mã gọi hàm sum có 
thể trông như dưới đây: 
int a=40; 
int b=2; 
int c = sum(a,b); 
Các biến a và b được khởi tạo với các giá trị 40 và 2. Các biến này không 
phải tham số hình thức hay tham số thực sự. Tại thời gian chạy, giá trị đã được gán 
cho các biến này được truyền vào cho hàm sum . Trong hàm sum, các tham số hình 
thức gt1 và gt2 được tính giá trị và lần lượt cho kết quả là hai tham số thực 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
57 
sự 40 và 2. Giá trị của các tham số thực sự được cộng lại, kết quả được trả về cho nơi 
gọi hàm - nơi nó được gán cho biến c 
Tham số hình thức thường được gọi tắt là tham số. Tham số thực sự còn được 
gọi là tham số thực, tham đối hoặc đối số. 
3.2 Cách truyền tham số 
 Có hai cách để truyền tham số cho hàm: Truyền theo tham trị và truyền theo 
tham chiếu. 
 Truyền bằng tham trị 
Trong cơ chế truyền tham số bằng giá trị (gọi là truyền tham trị), khi chương 
trình con được chạy, một bản sao của tham số thực sự được gán cho tham số hình 
thức (sao chép giá trị). Nghĩa là mọi sửa đổi của chương trình con đối với tham số 
hình thức không gây ảnh hưởng tới biến được truyền vào chương trình con theo kiểu 
truyền tham trị. 
Các tham số được truyền bằng giá trị được gọi là tham trị. Do chỉ có giá trị 
được truyền vào chương trình con, tham số thực sự không nhất thiết phải là một 
biến thông thường mà có thể là hằng giá trị, hằng biến, biểu thức trả về giá trị... 
Truyền bằng biến 
Trong cơ chế truyền tham số bằng biến (gọi là truyền tham biến), khi chương 
trình con được chạy, tham số hình thức trở thành một tham chiếu tham số thực sự. 
Nghĩa là mọi sửa đổi của chương trình con đối với tham số hình thức sẽ có tác dụng 
với tham số thực sự. Đây được gọi là hiệu ứng phụ của chương trình con. 
Các tham số được truyền bằng biến được gọi là tham biến. Ngược lại với cơ 
chế truyền bằng giá trị, cơ chế truyền bằng biến đòi hỏi tham số thực sự phải là một 
biến. 
Các đối số mặc định 
Một số ngôn ngữ lập trình cho phép một đối số mặc định (default argument) 
được cho trước một cách tường mình hay ngầm định trong phần khai báo của một 
chương trình con. Điều này cho phép nơi gọi bỏ qua đối số này khi gọi chương trình 
con đó. Nếu đối số mặc định được cho một cách tường mình, thì giá trị đó được sử 
dụng mỗi khi nó không được cung cấp bởi nơi gọi. Nếu đối số mặc định là ngầm định 
(mà đôi khi được khai báo bởi từ khóa như là "Optional" (không bắt buộc)) thì ngôn 
ngữ sẽ cung ứng một giá trị "ban đầu" thông dụng (như là null, tập rỗng, giá trị 0, xâu 
kí tự rỗng,...) nếu giá trị (của tham số) không được nơi gọi cung cấp. 
Chiều dài biến đổi được của danh sách tham số 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
58 
Một số ngôn ngữ cho phép các chương trình con được định nghĩa với số các 
đối số thay đổi được. Đối với các ngôn ngữ như vậy, các chương trình con phải duyệt 
qua danh mục của các đối số 
Các tham số danh định 
Một số ngôn ngữ lập trình cho phép các chương trình con có các tham số danh 
định (named parameter). Điều này cho phép mã nơi gọi chương trình con có tính tự 
mô tả (self-documenting) cao hơn. Nó cũng cung cấp cho nơi gọi khả năng uyển 
chuyển cao hơn, thường cho phép thay đổi thứ tự của các đối số hay bỏ qua một số 
đối số nếu cần thiết. 
3.3. Biến toàn cục và biến cục bộ 
Biến toàn cục là biến nhớ được khai báo ở ngoài mọi hàm(thường được khai báo 
ở trên cùng sau khai báo thư viện), có tác dụng đến toàn bộ chương trình cả 
chương trình chính và chương trình con. 
Biến cục bộ là biến nhớ được khai báo bên trong một chương trình con, chỉ có 
tác dụng ở trong chương trình con đó. Bên ngoài chương trình con đó thì biến đó 
không được sử dụng nữa. 
Ví du: 
 #include 
 #include 
 int a,b; 
 int sum() 
 { 
 int c = a + b; 
 return c; 
} 
int tich() 
{ 
 int c ; 
 c =a*b; 
 return c; 
} 
void main() 
{ 
 clrscr(); 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
59 
 printf(“nhap vao so a = ”); scanf(“%d”,&a); 
 printf(“nhap vao so b = ”);scanf(“%d”,&b); 
 printf(“\n tong hai so: %d”,sum()); 
 printf(“\n tich hai so la: %d”,tich()); 
 getch(); 
} 
Trong ví dụ trên hai biến a và b là biến toàn cục được sử dụng trong cả 3 hàm 
sum, max và main. Trong hàm sum và max đều có biến cục bộ là c nhưng biến c 
trong hàm sum sẽ độc lập và riêng biệt so với c trong hàm max. 
4. Hàm đệ quy 
4.1 Khái niệm đệ quy 
 Một hàm được gọi là đệ quy nếu bên trong thân hàm có lệnh gọi đến chính nó 
Ví dụ: Người ta định nghĩa giai thừa của một số nguyên dương n như sau: 
N!= 1*2*3*.*(n-1)*n=(n-1)! *n (với 0!=1) 
Như vậy, để tính n! ta thấy nếu n=0 thì n!=1 ngược lại thì n!=n*(n-1)! Với định 
nghĩa trên thì hàm đệ quy tính n! được viết: 
#include 
#include 
/*hàm tính n! bằng đệ quy*/ 
long giaithua_ dequy(int n) 
{ 
if(n==0) 
Return 1; 
else 
return n*giaithua_dequy(n-1); 
} 
4.2 Các bài toán dùng đệ quy 
 Phương pháp đệ quy thường dùng phổ biến trong ứng dụng mà cách giải 
quyết có thể được thể hiện bằng việc áp dụng liên tiếp cùng giải pháp cho những 
tập hợp con của bài toán. 
 Phương pháp đệ quy không phải bao giờ cũng là giải pháp hữu hiệu nhất. Giải 
pháp vòng lặp có hiệu quả về mặt thời gian và vùng nhớ. Còn với đệ quy mỗi lần 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
60 
gọi đệ quy máy phải dành một số vùng nhớ để trữ các trị, thông số và biến cục bộ. 
Do đó, đệ quy tốn nhiều vùng nhớ, thời gian truyền đối mục, thiết lập vùng nhớ 
trung gian và trả kết quảNhưng sử dụng phương pháp đệ quy trông chương trình 
đẹp mắt hơn vòng lặp và tính thuyết phục của nó. Điều cốt lõi khi thiết đặt chương 
trình phải làm thế nào hàm đệ quy có thể chấm dứt thông qua điều kiện cơ bản 
 Chính vì vậy, trong lập trình người ta cố tránh sử dụng thủ tục đệ quy nếu thấy 
không cần thiết. 
4.3 Cách xây dựng hàm đệ quy 
 Hàm đệ quy phải có 2 phần : 
+ Phần dừng hay phải có trường hợp nguyên tố.Trong ví dụ ở trên thì trường 
hợp n=0 là trường hợp nguyên tố. 
+ Phần đệ quy : Là phần có gọi lại hàm được định nghĩa. Trong ví dụ trên thì 
phần đệ quy là n>0 thì n !=n*(n-1) ! 
 Sử dụng hàm đề quy trong chương trình sẽ làm chương trình dễ đọc, dễ hiểu và 
vấn đề được nêu bật rõ ràng hơn.Tuy nhiên trong đa số trường hợp thì hàm đệ 
quy tốn bộ nhớ nhiều hơn và tốc độ thực hiện chương trình chậm hơn không 
đệ quy. 
 Tùy từng bài cụ thể mà người lập trình quyết định nên dùng đệ quy hay 
không(có trường hợp không dùng đệ quy thì không giải quyết được bài toán). 
4.4 Các ví dụ về hàm đệ quy 
 Ví dụ 1: Tính n! 
N!= 1*2*3**(n-2)*(n-1)*n với n>=1 và 0!=1 
long giaithua(int n) 
{ 
if(n==0) 
Return 1; 
else 
return n*giaithua(n-1); 
} 
Giải thích hoạt động của hàm đệ quy giaithua 
Ví dụ giá trị truyền vào hàm giaithua qua biến n = 5 
 Thứ tự gọi thực hiện hàm giai thừa 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
61 
giaithua(n) return(n * giaithua(n-1)) 
5 
4 
3 
2 
1 
5*giaithua(4) = 5 *? 
4*giaithua(3) = 4 *? 
3*giaithua(2) =3 *? 
2*giaithua(1) = 2*? 
1*giaithua(0) = 1 *? 
 Khi tham số n =0 thì return về giá trị (giá trị 1 kiểu long). Lúc này các giá trị? Bắt đầu 
định trị theo thứ tự ngược lại 
Giaithua(in) Return(in * giaithua(in-1)) 
1 
2 
3 
4 
5 
1*giaithua(0) = 1 *1 = 1 
2*giaithua(1) = 2 *1=2 
3*giaithua(2) =3 *2=6 
4*giaithua(3) = 4*6=24 
5*giaithua(4) = 5 *24=120 
Kết quả sau cùng 5!= 120 
Minh họa bằng hình ảnh. 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
62 
Hình 4.4.4: Hình ảnh minh họa tính 5! bằng giải thuật đệ quy 
 Ví dụ 2: dãy số Fibonaci 
 0,1,1,2,3,5,8,13,21,34.. Bắt đầu bằng 0 và 1, các số tiếp theo bằng tổng hai 
số đi trước 
 Dãy số fibonaci được khai báo đề quy như sau: 
 fibonaci(0)=0 
 fibonaci(1)=1 
 fibonaci(n)= fibonaci(n-1) + fibonaci(n-2) 
/* tinh so fibonaci thu n*/ 
# include 
# include 
void main(void) 
{ 
 long n; 
 long fibonaci(long); 
 printf(“nhap vao so n:”); 
 scanf(%ld”,&n); 
 print(“fibonaci(%ld)=%ld\n”,n,fibonaci(n)); 
 getch(); 
} 
long fibonaci(long in) 
{ 
 if (n==0|| n==1) 
 Return n; 
 else 
 return fibonaci(n -1 )+ fibonaci(n – 2); 
} 
Ket qua in ra man hinh 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
63 
Nhap vao so n:10 
Fibonaci(10)=55 
Ví dụ 3 : 
Tìm UCLN của 2 số a, b. Bài toán có thể được định nghĩa dưới dạng đệ qui như 
sau: 
− nếu a = b thì UCLN = a 
− nếu a > b thì UCLN(a, b) = UCLN(a-b, b) 
− nếu a < b thì UCLN(a, b) = UCLN(a, b-a) 
Từ đó ta có chương trình đệ qui để tính UCLN của a và b như sau. 
int UCLN(int a, int b) // qui uoc a, b > 0 
{ 
if (a < b) UCLN(a, b-a); 
if (a == b) return a; 
if (a > b) UCLN(a-b, b); 
} 
BÀI TẬP VẬN DỤNG 
Bài tập 1: 
Viết chương trình con tìm Max, Min 3 sô nguyên, chương trình chính nhập vào 
3 số nguyên, hiện số lớn nhất và nhỏ nhất ra màn hình. 
#include 
#include 
int max(int a,int b,int c) 
{ int max=a; 
 if(max<b)max=b; 
 if(max<c)max=c; 
 return max; 
} 
int min(int a, int b, int c) 
{ 
 int min=a; 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
64 
 if(min>b)min=b; 
 if(min>c)min=c; 
 return min; 
} 
void main() 
{ 
 int a,b,c; 
 clrscr(); 
 printf("\nnhap vao 3 so nguyen:"); 
 printf("\nso thu nhat: ");scanf("%d",&a); 
 printf("\nso thu hai: ");scanf("%d",&b); 
 printf("\nso thu ba : ");scanf("%d",&c); 
 printf("\n so lon nhat la: %d",max(a,b,c)); 
 printf("\n so nho nhat la: %d",min(a,b,c)); 
 getch() ; 
} 
Bài tập 2: 
 Viết chương trình kiểm tra một số nguyên có phải là số nguyên tố hay không. 
#include 
#include 
#include 
 int SNT(int n) 
 { 
 int i,kt=1; 
 for(i=2; i<=sqrt(n);i++) 
{ 
 if(n%i==0) 
 { 
 kt=0; 
 break; 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
65 
 } 
 } 
 return kt; 
} 
void main() 
{ 
 int n; 
 printf("Nhap So Can Kiem Tra: "); 
 scanf("%d", &n); 
 int kq; 
 kq = SNT(n); 
 if(kq==1) 
 printf("So: %d là so nguyen to.", n); 
 else 
 printf("So: %d khong là so nguyen to.", n); 
 printf("\n"); 
} 
Bài tập 3 
Viết chương trình đếm số chữ số của một số nào đó, Ví dụ: 21432 trả về: 5 vì có 
5 chữ số. 
//dem so chu so cua n vd: 12342 -> tra ve: 5 
int Dem(int n) 
{ 
 int dem=0; 
 while(n != 0) 
 { 
 n=n/10; 
 dem ++; 
 } 
 return dem; 
} 
void main() 
{ 
 int n; 
 printf("Nhap n: "); 
 scanf("%d", &n); 
 int dem = Dem(n); 
 printf(".:|Chu so cua so n la: %d", dem); 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
66 
 printf("\n"); 
} 
Bài tập 4 
Viết chương trình đảo ngược của 1 số: ví dụ nhập 123 -> trả về 321. 
int DaoSo(int n) 
{ 
 int kq=0; 
 while(n!=0) 
 { 
 kq=kq*10 + n%10; 
 n=n/10; 
 } 
 return kq; 
} 
void main() 
{ 
 int n; 
 printf("Nhap n: "); 
 scanf("%d", &n); 
 printf("\nSo Dao Nguoc La: %d", DaoSo(n)); 
} 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
67 
Chương 5: MẢNG 
1. Khái niệm mảng 
Mảng là cấu trúc dữ liệu cho phép quản lý một danh sách hữu hạn các dữ liệu 
cùng kiểu. 
Ví dụ: Để chứa 5 dữ liệu số nguyên sau 10, 12, 25, 30, 40 
Chúng ta có thể sử dụng 5 biến nhớ khác nhau 
 a = 10, b = 12, c = 25, d = 30, e = 40 
Tuy nhiên nếu số lượng dữ liệu tăng thì cách này không phù hợp, và chúng ta 
sẽ sử dụng cấu trúc mảng, minh hoạ như sau: 
10 12 25 30 40 .... 
Các dữ liệu trong mảng phải cùng kiểu (số nguyên, số thực, ký tự ... ). 
Mảng để chứa dữ liệu như trên là mảng 1 chiều, chúng ta có thể sử dụng 
mảng 2 chiều hoặc mảng nhiều chiều. 
 Ví dụ về mảng 2 chiều: 
10 2 5 .... 
45 23 56 .... 
8 5 20 .... 
.... .... .... .... 
Mảng hai chiều là một bảng các dữ liệu được xếp theo hàng và cột, mỗi dữ liệu 
sẽ chứa trong ô được xác định bằng cách chỉ ra ở hàng nào và cột nào. 
2. Khai báo mảng 
 Mảng một chiều 
Mảng một chiều giống như một vector. Mỗi phần tử của mảng một chiều có giá 
trị không phải là một mảng khác. 
 Khai báo với số phần tử xác định 
Cú pháp: 
Trong đó: 
+ Tên_mảng: Đây là tên mảng đạt theo đúng quy tắc đặt tên của danh biểu. Tên 
này cũng mang ý nghĩa là tên biến mảng. 
+ Số_phần_tử : Là một hằng số nguyên, cho biết số lượng phàn tử tối đa trong 
mảng là bao nhiêu (hay nói khác đi kích thước của mảng là gì). 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
68 
+ Kiểu : Mỗi phần tử của mảng có dữ liệu thuộc kiểu gì. 
Ở đây, ta khai báo một biến mảng gồm có Số_phần_tử phần tử, phần tử thứ nhất 
là tên_mảng [0], phần tử cuối cùng là tên_mảng[Số_phần_tử -1] 
VD: 
int a[10]; /*Khai báo biến mảng tên a, phần tử thứ nhất là a[0], phần tử cuối cùng 
là a[9].*/ 
Ta có thể coi mảng a là một dãy liên tiếp các phần tử trong bộ nhớ như sau: 
Vị trí 0 1 2 3 4 5 6 7 8 9 
Tên phần 
tử 
a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] 
 Khai báo với số phần tử không xác định (khai báo không tường minh) 
Cú pháp: 
Khi khai báo, không cho biết rõ số phần tử của mảng, kiểu khai báo này thường 
được áp dụng trong các trường hợp: vừa khai báo vừa gán giá trị, khai báo mảng là 
tham số hình thức của hàm. 
 Vừa khai báo vừa gán giá trị 
Cú pháp: 
 [] = {Các giá trị cách nhau bởi dấu phẩy} 
Nếu vừa khai báo vừa gán giá trị thì mặc nhiên C sẽ hiểu số phần tử của mảng là 
số giá trị mà chúng ta gán cho mảng trong cặp dấu {}. 
Ví dụ: 
 int S[] = {3,5,6}; 
 Mảng nhiều chiều 
Mảng nhiều chiều là mảng có từ hai chiều trở lên. Điều đó có nghĩa là mỗi phần tử 
của mảng là một mảng khác. 
Người ta thường sử dụng mảng nhiều chiều để lưu các ma trận, các tọa độ 2 
chiều, 3 chiều. 
Phần dưới đây là các vấn đề liên quan đến mảng 2 chiều; các mang 3, 4 chiều thì 
tương tự (chỉ cần tổng quát hóa lên). 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
69 
 Khai báo mảng hai chiều tường minh 
Cú pháp: 
VD: Người ta cần lưu trữ thông tin của một ma trận gồm các số thực. Lúc này ta 
có thể khai báo một mảng 2 chiều như sau: 
float m[8][9]; 
 /*Khai báo mảng hai chiều có 8*9 phần tử là số thực*/ 
Trong trường hợp này, ta đã khai báo cho một ma trận có tối đa là 8 dòng, mỗi 
dòng có tối đa là 9 cột. 
 0 1 2 3 4 5 6 7 8 
0 m[0][0] m[0][1] m[0][2] m[0][3] m[0][4] m[0][5] m[0][6] m[0][7] m[0][8] 
1 m[1][0] m[1][1] m[1][2] m[1][3] m[1][4] m[1][5] m[1][6] m[1][7] m[1][8] 
2 m[2][0] m[2][1] m[2][2] m[2][3] m[2][4] m[2][5] m[2][6] m[2][7] m[2][8] 
3 m[3][0] m[3][1] m[3][2] m[3][3] m[3][4] m[3][5] m[3][6] m[3][7] m[3][8] 
4 m[4][0] m[4][1] m[4][2] m[4][3] m[4][4] m[4][5] m[4][6] m[4][7] m[4][8] 
5 m[5][0] m[5][1] m[5][2] m[5][3] m[5][4] m[5][5] m[5][6] m[5][7] m[5][8] 
6 m[6][0] m[6][1] m[6][2] m[6][3] m[6][4] m[6][5] m[6][6] m[6][7] m[6][8] 
7 m[7][0] m[7][1] m[7][2] m[7][3] m[7][4] m[7][5] m[7][6] m[7][7] m[7][8] 
 Khai báo mảng 2 chiều không tường minh 
 Để khai báo mảng 2 chiều không tường minh, ta vẫn phải chỉ ra số phần tử của 
chiều thứ hai (chiều cuối cùng). 
Cú pháp: 
 Cách khai báo này cũng được áp dụng trong trường hợp vừa khai báo, vừa gán trị 
hay đặt mảng 2 chiều là tham số hình thức của hàm. 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
70 
3. Truy xuất mảng 
3.1 Truy xuất mảng 1 chiều 
Đối với mảng một chiều các phần tử chứa dữ liệu được sắp xếp liên tục trong 
bộ nhớ máy, và mỗi phần tử sẽ có một chỉ số (là số thứ tự) của phần tử đó trong 
mảng. 
 Phần tử đầu tiên có chỉ số là 0, tiếp theo là 1 và tiếp tục cho đến hết, vậy sẽ 
dừng lại ở chỉ số bằng số lượng phần tử -1. 
Minh hoạ bằng hình sau: 
10 25 15 30 ..... 
0 1 2 3 .... 
Kích thước của mảng (tính bằng byte) sẽ là: số lượng phần tử của mảng nhân 
với kích thước của kiểu dữ liệu của mảng đó. 
 Ví dụ: 
 int a[20]; 
Thì mảng sẽ chiếm kích thước bộ nhớ là: 20 x 2 = 40 byte 
 Để truy nhập đến các phần tử ta sử dụng tên và các chỉ số của phần tử đó theo 
cú pháp sau: 
 Tên_mảng[chỉ_số_phần_tử_cần_truy_nhập]; 
 Ví dụ: 
 a[0]=10; 
Truy xuất đến phần tử đầu tiên của mảng a rồi gán giá trị cho phần tử đó bằng 
10. 
3.2 Truy xuất mảng 2 chiều 
Để truy nhập đến các phần tử của mảng hai chiều ta sử dụng tên mảng và chỉ số 
hàng và chỉ số cột theo cú pháp sau: 
Tên_mảng_hai_chiều[chỉ_số_hàng] [chỉ_số_cột]; 
 Ví dụ: 
 a[1][2] = 5; 
Chú ý: 
 Số lượng dữ liệu lưu trong mảng có thể ít hơn số lượng phần tử đã khai báo, 
nhưng không vượt quá số lượng phần tử đã khai báo đó. Thông thường sử dụng 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
71 
mảng sẽ có một số nguyên n để lưu số lượng dữ liệu được lưu trong mảng tương 
ứng. 
 Danh sách các dữ liệu lưu trong mảng phải liên tục nhau để quản lý và sử lý dễ 
dàng. 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
72 
BÀI TẬP THỰC HÀNH 
Bài tập 1: 
 Viết chương trình nhập vào từ bàn phím một mảng gồm n số nguyên. Hiện 
mảng vừa nhập lên màn hình. 
#include 
#include 
void nhap(int n,int C[]) 
 { 
for(int i=0;i<n;i++) 
 { 
 printf("\n Nhap so thu %d ",i+1); 
 scanf("%d",&C[i]); 
 } 
 } 
void hien(int n,int C[]) 
 { 
 for(int i=0;i<n;i++) 
 { 
 printf(" %d",C[i]); 
 } 
 } 
void main() 
{ 
 clrscr(); 
 int A[100],n; 
 printf("\nnhap so luong phan tu cua mang: n= "); 
 scanf("%d",&n); 
 nhap(n, A); 
 printf("\n Mang vua nhap : "); 
 hien(n, A); 
 getch(); 
} 
Bài tập 2: 
 Lập trình đọc vào từ bàn phím hai dãy số nguyên. Dãy A có n số, dãy B có m số. 
Tính tổng của mỗi dãy, so sánh xem dãy nào có tổng lớn hơn. Đưa kết quả ra màn 
hình bao gồm: dãy A, dãy B, tổng dãy A,B, so sánh. 
#include 
#include 
void nhap(int n,int C[]) 
 { 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
73 
for(int i=0;i<n;i++) 
 { 
 printf("\n Nhap so thu %d ",i+1); 
 scanf("%d",&C[i]); 
 } 
 } 
void hien(int n,int C[]) 
 { 
 for(int i=0;i<n;i++) 
 { 
 printf(" %d",C[i]); 
 } 
 } 
int tong(int n,int C[]) 
 { 
int sum=0; 
 for(int i=0;i<n;i++) 
 sum=sum+C[i]; 
 return sum; 
 } 
void main() 
{ 
 clrscr(); 
 int A[100],B[100],m,n; 
 printf("\nnhap so luong phan tu day A: n= "); 
 scanf("%d",&n); 
 printf("\nnhap so luong phan tu day B: m= "); 
 scanf("%d",&m); 
 printf("\n Nhap gia tri cho day A:"); 
 nhap(n,A); 
 printf("\n Nhap gia tri cho day B"); 
 nhap(m,B); 
 printf("\n Day A vua nhap la:"); 
 hien(n,A); 
 printf("\n Day B vua nhap la:"); 
 hien(m,B); 
 printf("\n tong day A la: %d",tong(n,A)); 
 printf("\n tong day B la: %d",tong(m,B)); 
 printf("\n Day lon hon la: "); 
 if(tong(n,A)>tong(m,B)) printf("A"); 
 else printf("B"); 
 getch() ; 
} 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
74 
Bài tập 3: Nhập ma trận A có m hàng n cột đưa ra màn hình ma trận A vừa nhập để 
kiểm tra. 
#include 
#include 
void main() 
{ 
 int n,m,i,j,A[100][100]; 
 clrscr(); 
 printf("nhap so hang cua ma tran: n= "); 
 scanf("%d",&n); 
 printf("nhap so cot cua ma tran: m= "); 
 scanf("%d",&m); 
 //nhap gia tri cho ma tran 
 for(i=0;i<n;i++) 
 { 
 for(j=0;j<m;j++) 
 { 
 printf("A[%d][%d]= ",i+1,j+1); 
 scanf("%d",&A[i][j]); 
 } 
 } 
 // hien ma tran vua nhap 
 printf("\nMa tran ban vua nhap la:"); 
 for(i=0;i<n;i++) 
 { 
 printf("\n"); 
 for(j=0;j<m;j++) 
 { 
 printf("%d ",A[i][j]); 
 } 
 } 
 getch(); 
} 
Bài tập 4 
Nhập vào từ bàn phím một dãy số nguyên. Tìm số lớn nhất, nhỏ nhất và vị trí 
của số đó trong mảng. 
#include 
#include 
void main() 
{ 
 int i,n,A[100],max=0,min=0; 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
75 
 clrscr(); 
 printf("nhap so luong phan tu cua day: "); 
 scanf("%d",&n); 
 //nhap gia tri cho day 
 for(i=0;i<n;i++) 
 { 
 printf("\n Nhap A[%d] = ",i+1); 
 scanf("%d",&A[i]); 
 } 
 //tim Max, Min 
 for(i=1;i<=n;i++) 
 { 
 if(A[max]<A[i]) max=i; 
 if(A[min]>A[i]) min=i; 
 } 
 printf("\nSo lon nhat trong day la: %d",A[max]); 
 printf("\t Vi tri so do la: %d",max+1); 
 printf("\nSo nho nhat trong day la: %d",A[min]); 
 printf("\t Vi tri so do la: %d",min+1); 
 getch(); 
} 
Bài tập 5 
 Nhập và từ bàn phím một dãy số nguyên, xắp xếp dãy đó theo chiều tăng dần 
và giảm dần. Hiện lên màn hình: dãy số vừa nhập, dãy đã sắp xếp. 
#include 
#include 
void nhap(int n,int C[]) 
 { 
 for(int i=0;i<n;i++) 
 { 
 printf("\n Nhap so thu %d ",i+1); 
 scanf("%d",&C[i]); 
 } 
 } 
void hien(int n,int C[]) 
 { 
 for(int i=0;i<n;i++) 
 { 
 printf(" %d",C[i]); 
 } 
 } 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
76 
void tang(int n, int C[]) 
 { 
int tg; 
 for(int i=0;i<n;i++) 
 for(int j=0;j<n-1;j++) 
 if(C[j] >C[j+1]) 
 { 
 tg=C[j]; 
 C[j]=C[j+1]; 
 C[j+1]=tg; 
 } 
 } 
void giam(int n, int C[]) 
 { 
int tg; 
 for(int i=0;i<n;i++) 
 for(int j=0;j<n-1;j++) 
 if(C[j] <C[j+1]) 
 { 
 tg=C[j]; 
 C[j]=C[j+1]; 
 C[j+1]=tg; 
 } 
 } 
void main() 
{ 
 clrscr(); 
 int A[100],n; 
 printf("\nnhap so luong phan tu day : n= "); 
 scanf("%d",&n); 
 printf("\n Nhap gia tri cho day :"); 
 nhap(n,A); 
 printf("\n Day vua nhap la:"); 
 hien(n,A); 
 //hien day da xap xep tang dan 
 printf("\n Day da xap xep tang dan la:"); 
 tang(n,A); 
 hien(n,A); 
 //hien day da xap xep giam dan 
 printf("\n Day da xap xep giam dan:"); 
 giam(n,A); 
 hien(n,A); 
 getch() ;} 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
77 
CHƯƠNG 6: CON TRỎ 
1. Khái niệm về con trỏ và địa chỉ 
 Một con trỏ (pointer) là một biến mà nội dung của nó là địa chỉ của một đối 
tượng khác. Đối tượng ở đây có thể là một biến hoặc một hàm và không phải là một 
hằng. Việc sử dụng các biến con trỏ sẽ giúp chúng ta khai thác đến 1 biến thông qua 
địa chỉ của nó. Khả năng đó cộng với khả năng tính toán linh hoạt trên các con trỏ 
của C đã khiến con trỏ trở thành một công cụ mạnh để thực hiện nhiều thao tác mà 
thiếu nó thì không thể làm được hoặc rất khó khăn. 
 Bộ nhớ máy tính bao gồm một bảng các ô nhớ liên tiếp có thể đánh địa chỉ 
được. Chúng ta có thể thao tác trên từng ô nhớ riêng rẽ hoặc trên các ô nhớ liên tiếp. 
Khi chúng ta khai báo một biến, máy sẽ cấp phát cho biến đó một số ô nhớ liên tiếp 
đủ để chứa nội dung của biến, ví dụ một biến ký tự được cấp phát một byte, một 
biến nguyên được cấp phát 2 byte, một biến thực được cấp phát 4 byteĐịa chi của 
biến được tính là số thứ tự của byte đầu tiên trong dãy các byte được cấp phát cho 
biến. Vì vậy người ta phân biệt các con trỏ theo kiểu địa chỉ chứa trong các con trỏ. 
Con trỏ được minh họa bằng hình sau. 
Hình 6.1: Hình ảnh mô tả giá trị của biến con trỏ 
Có hai kiểu biến trỏ: Biến trỏ có kiểu và biến trỏ không kiểu 
 Biến trỏ có kiểu : loại biến trỏ này chỉ chứa địa chỉ vùng nhớ của một kiểu dữ 
liệu nào đó, kiểu dữ liệu này được xác định khi khai báo biến trỏ. Và kiểu của biến trỏ 
xác định kích thước của vùng nhớ mà biến trỏ đến 
Ví dụ biến trỏ kiểu int sẽ trỏ đến vùng nhớ có kích thước là 2 bytes, kiểu floast sẽ trỏ 
đến vùng nhớ có kích thước là 4 bytes. 
Địa chỉ vùng nhớ 
của biến a (0100) 
Biến a 
Địa chỉ vùng 
nhớ: 0100 
Biến b Biến 
trỏ 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
78 
 Biến trỏ không kiểu: loại biến trỏ này có thể chứa địa chỉ vùng nhớ có kích 
thước bất kỳ. 
Vùng nhớ động: Là vùng nhớ được cấp phát khi cần và giải phóng khỏi bộ nhớ khi sử 
dụng song. Để truy cập đến vùng nhớ động chúng ta phải dùng biến trỏ. 
2. Khai báo về sử dụng biến con trỏ 
2.1 Khai báo biến con trỏ 
 biến trỏ có kiểu 
 Kiểu_dữ_liệu *tên_con_trỏ; 
 Ví dụ: *pn /*Khai báo con trỏ pn chứa địa chỉ của biến nguyên*/ 
- biến trỏ không kiểu: 
void *tên_biến_trỏ 
ví dụ: void *i; 
 Với câu lệnh khai báo trên, con trỏ chưa trỏ đến địa chỉ nào cả và nó có giá trị 
bằng NULL. NULL là một hằng số biểu thị giá trị của con trỏ khi chưa được gán địa chỉ 
nào. 
2.2. Các thao tác trên con trỏ 
2.2.1. Gán địa chỉ của biến cho con trỏ 
Toán tử & dùng để định vị con trỏ đến địa chỉ của một biến đang làm việc. 
Cú pháp : =& 
Giải thích: 
Ta gán địa chỉ của biến a cho con trỏ pa, Ta gán địa chỉ của biến b cho con trỏ pb 
pa=&a ; pb=&b ; 
Lúc này hình ảnh của các biến trong bộ nhớ được mô tả : 
Lưu ý : 
Khi gán địa chỉ của biến tĩnh cho con trỏ cần phải lưu ý kiểu dữ liệu của chúng. Ví 
dụ sau đây không đúng do không tương thích kiểu : 
int biennguyen ; 
float *controthuc ; 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
79 
. 
controthuc=&biennguyen ; 
Phép gán ở đây là sai vì controthuc là một con trỏ kiểu float(nó chỉ có thể chứa 
được địa chỉ của biến kiểu float) ; trong khi đó biến nguyên kiểu int. 
2.2.2. Nội dung của ô nhớ con trỏ chỉ tới 
Để truy cập đến nọi dung của ô nhớ mà con trỏ chỉ tới, ta sử dụng cú pháp : 
* 
Với cách truy cập này thì * có thể coi là một biến có kiểu được mô 
tả trong phần khai báo biến con trỏ. 
Ví dụ : Cho phép khai báo, gán địa chỉ cũng như lấy nội dung vùng nhớ của biến con 
trỏ : 
Int x= 100 ; 
int *ptr ; 
ptr = &x ; 
int y= *ptr ; 
Lưu ý : 
Khi gán địa chỉ của một biến cho biến con trỏ, mọi sự thay đổi trên nội dung ô 
nhớ con trỏ chỉ tới sẽ làm giá trị của biến thay đổi theo( thực chất nội dung ô nhớ và 
biến là một) 
Ví dụ : Đoạn chương trình sau thấy rõ sự thay đổi 
#include 
#include 
int main () 
{ 
int a,b, *pa, *pb ; 
a=2 ; 
b=3 ; 
clrscr() ; 
printf (‘\n gia tri cua bien a=%d \n gia tri cua bien 
b=%d’, a,b) ; 
pa=&a ; 
pb=&b ; 
printf (‘\n noi dung cua o nho con tro pa tro toi=%d’, 
*pa) ; 
printf (‘\n noi dung cua o nho con tro pa tro toi=%d’, 
*pb) ; 
*pa=20 ; 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
80 
*pb=20 ; 
printf (‘\n gia tri moi cua bien a=%d \n gia tri moi 
cua bien b=%d’, a,b) ; 
getch() ; 
return 0; 
} 
Kết quả thực hiện chương trình 
2.2.3. Cấp phát và giải phóng vùng nhớ 
Trước khi sử dụng biến con trỏ, ta nên cấp phát vùng nhớ cho biến con trỏ này 
quản lý địa chỉ. Việc cấp phát được thực hiện nhờ các hàm malloc(), calloc() trong 
thư viện alloc.h 
Cú pháp các hàm : 
 Void *malloc(size_t size) : Cấp phát vùng nhớ có kích thước là size. 
 Void *calloc(size_t nitems,size_t size) : Cấp phát vùng nhớ có kích thước là 
nitems*size. 
Ví dụ: Giả sử ta có khai báo 
int a, *pa, *pb; 
pa=(int*)malloc(sizeof(int));/*cấp phát vùng nhớ có kích thước bằng với kích 
thước của một số nguyên */ 
pb=(int*)calloc(10,sizeof(int));/*cấp phát vùng nhớ có thể chứa được 10 số 
nguyên */ 
Lúc này hình ảnh trong bộ nhớ như sau: 
Lưu ý: 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
81 
 Khi sử dụng hàm malloc() hay calloc(), ta phải ép kiểu vì nguyên mẫu các hàm 
này trả về con trỏ kiểu void. 
Trong quá trình thao tác trên biến con trỏ, nếu ta cần cấp phát thêm vùng nhớ 
có kích thước lớn hon vùng nhớ đã cấp phát, ta sử dụng hàm realloc(). 
Cú pháp: void *realloc(void *block,size_t size) 
Ý nghĩa: 
Cấp phát lại 1 vùng nhớ cho con trỏ block quản lý, vùng nhớ này có kích thước 
mới là size; khi cấp phát lại thì nội dung vùng nhớ trước đó vẫn tồn tại. 
Kết quả trả về của hàm là địa chỉ đầu tiên của vùng nhớ mới. Địa chỉ này có thể 
khác với địa chỉ được chỉ ra khi cấp phát ban đầu. 
Ví dụ: Trong ví dụ trên ta có thể cấp phát lại vùng nhớ do con trỏ pa quả lý như 
sau: 
int a, *pa; 
pa=(int *)malloc(sizeof(int)) ;/*cấp phát vùng nhớ có kích thước 2 byte*/ 
pa=realloc(pa,6) ;/*cấp phát lại vùng nhớ có kích thước 6byte*/ 
Một vùng nhớ đã cấp phát cho biến con trỏ, khi không còn sử dụng nữa, ta sẽ thu 
hồi lại vùng nhớ này nhờ hàm free() 
Cú pháp: void free(void *block) 
Ý nghĩa: Giải phóng vùng nhớ được quản lý bởi con trỏ block. 
Ví dụ: Ở ví dụ trên, sau khi thực hiện xong, ta giải phóng vùng nhớ cho 2 biến con trỏ 
pa & pb: 
free(pa); 
 free(pb); 
2.2.4. Một số phép toán 
 Phép gán con trỏ: 
Hai con trỏ cùng kiểu có thể gán cho nhau: 
Ví dụ: 
int a, *p, *a; float *f; 
A=5; p =&a; q=p; /*đúng*/ 
f=p;/* sai do khác kiểu*/ 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
82 
Ta cũng có thể ép kiểu con trỏ theo cú pháp: 
(*) 
Chẳng hạn, ví dụ trên được viết lại: 
int a, *p, *q; float *f; 
a=5; p =&a; q=p; /*đúng*/ 
f=(float*)p;/* đúng nhờ ép kiểu*/ 
 Cộng, trừ con trỏ với một số nguyên 
Ta có thể cộng (+), trừ (-) 1 con trỏ với 1 số nguyên N nào đó; kết quả trả về là 1 
con trỏ. Con trỏ này chỉ đến vùng nhớ cách vùng nhớ cảu con trỏ hiện tại N phần tử. 
Ví dụ: Cho đoạn chương trình sau: 
int *pa; 
/*cấp phát vùng nhớ 20byte = 10 số nguyên*/ 
pa =(int*)malloc(20); 
int *pb, *pc; 
pb = pa +7; 
pc=pb -3 ; 
Lúc này hình ảnh của pa, pb, pc như sau : 
 Con trỏ Null : 
Là con trỏ không chứa địa chỉ nào cả. Ta có thể gán giá trị NULL cho 1 con trỏ có 
kiểu bất kỳ. 
Lưu ý : 
- Ta không thể cộng 2 con trỏ với nhau 
- Phép trừ 2 con trỏ cùng kiểu sẽ trả về 1 giá trị nguyên (int). Đây chính là khoảng 
cách(số phần tử) giữa 2 con trỏ đó. 
Chẳng hạn, trong ví dụ trên pc – pa = 4 
3. Con trỏ và mảng 1 chiều 
Giữa mảng và con trỏ có một sự liên hệ rất chặt chẽ. Những phần tử của mảng 
có thể được xác định bằng chỉ số trong mảng, bên cạnh đó chúng cũng có thể được 
xác lập qua biến con trỏ. 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
83 
3.1 Phép toán lấy địa chỉ 
Ta có các quy tắc sau: 
&[0] tương đương với 
&[] tương đương với+ 
[] tương đương với *(+) 
Ví dụ : 
Cho 1 mảng 1 chiều các số nguyên a có 5 phần tử, truy cập các phần tử theo 
kiểu mảng và theo kiểu con trỏ. 
#include 
#include 
/*nhap mang binh thuong*/ 
void nhapmang(int a[], int n) 
{ 
int i; 
for ( i=0; i<n; i++) 
{ 
printf (“phan tu thu %d:”, i); 
scanf(“%d”, & a[i]); 
} 
} 
/* nhap mang theo dang con tro*/ 
void nhapcontro(int a[], int n) 
{ 
int i; 
for (i=0; i<n;i++) 
{ 
printf(“phan tu thu %d:”,i); 
scanf(“%d”, a+i); 
} 
} 
int main() 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
84 
{ 
int a[20], n, i; 
clrscr(); 
printf(“so phan tu n=”); 
scanf(“%d”,&n); 
nhapmang(a,n); 
printf(“truy cap theo kieu mang:”); 
for (i=0;i<n;i++) 
printf(“%d”,a[i]); 
printf(“truy cap theo kieu con tro:”); 
for (i=0;i<n;i++) 
Printf(“%d”,*(a+i)); 
Getch(); 
Return 0; 
} 
Kết quả thực thi chương trình 
3.2 Tên mảng là 1 hằng địa chỉ 
[] tương đương với *(+) 
&[] tương đương với (+) 
Trong đó là biến con trỏ, là 1 biểu thức số nguyên. 
Ví dụ: giả sử có khai báo: 
#include 
#include 
#include 
int main() 
{ 
int *a; 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
85 
int i; 
clrscr(); 
a=(int*)malloc(sizeof(int)*10); 
for (i=0;i<10;i++) 
a[i] = 2*i; 
printf(“truy cap theo kieu mang:”); 
for (i=0;i<10;i++) 
printf(“%d”,a[i]); 
printf(“truy cap theo kieu con tro:”); 
 for (i=0;i<10;i++) 
printf(“%d”,a + i);; 
getch(); 
retrun 0; 
} 
Với khai báo ở trên, hình ảnh của con trỏ a trong bộ nhớ 
3.3 Con trỏ trỏ tới các phần tử của mảng 1 chiều 
Giả sử con trỏ ptr chỉ đến phần tử a[i] nào đó của mảng a thì: 
ptr + j chỉ đến phần tử đứng sau a[i], tức là a[i + j] 
ptr - j chỉ đến phần tử đứng trước a[i], tức là a[i - j] 
Ví dụ: 
Giả sử có 1 mảng mang_int, cho con trỏ contro_int chỉ đến phần tử thứ 5 trong 
mảng. In ra các phần tử của contro_int & mang_int. 
#include 
#include 
#include 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
86 
int main() 
{ 
int i, mangint[10]; 
int *controint; 
clrscr() 
for(i=0;i<=9;i++) 
mangint[i]=i*2; 
controint=&mangint[5]; 
printf(“\n noi dung cua mang int ban dau=”); 
for (i=0;i<=9;i++) 
printf(“%d”, mangint[i]); 
printf(“\n noi dung cua contro int ban dau=”); 
for (i=0;i<=5;i++) 
printf(“%d”, controint[i]); 
for i=0;i<5;i++) 
controint [i]++; 
printf(“\n -----------------------------------------
“); 
printf(“\n noi dung cua mang int sau khi tang 1=”); 
for (i=0;i<=9;i++) 
printf(“%d”, mangint[i]); 
printf(“\n noi dung cua contro int sau khi tang 
1=”); 
for (i=0;i<5;i++) 
printf(“%d”, controint[i]); 
for i=0;i<5;i++) 
if(controint !=null) 
free(controint); 
getch(); 
return 0; 
} 
Kết quả của chương trình 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
87 
4. Con trỏ và hàm 
Khi tham số hình thức của hàm là một con trỏ thì theo nguyên tắc gọi hàm ta 
dùng tham số thực tế là 1 con trỏ có kiểu giống với kiểu của tham số hình thức. Nếu 
lúc thực thi hàm ta có sự thay đổi trên nội dung vùng nhớ được chỉ bởi con trỏ tham 
số hình thức thì lúc đó nội dung vùng nhớ được chỉ bởi tham số thực tế cũng sẽ bị 
thay đổi theo. 
Ví dụ: xét hàm hoán vị được viết như sau: 
#include 
#include 
void hoanvi(int *a, int *b) 
{ 
int c=*a; 
*a=*b; 
*b=c; 
} 
int main() 
{ 
 int m=20, n=30; 
clrscr(); 
printf(“truoc khi goi ham m=%d, n=%d\n”,m,n); 
hoanvi(&m,&n); 
printf(“sau khi goi ham m=%d, n=%d”,m,n); 
getch(); 
return 0; 
} 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
88 
Kết quả thực thi chương trình 
Truớc khi gọi hàm Khi gọi hàm Sau khi gọi hàm 
m=20 , n=30 
&m, &n 
a=&m; b=&n; 
Lúc này 
*a=m; *b=n; 
m=20 , n=30 
Đổi chỗ ta được 
a=30, b= 20 
m = 30 , n= 20 
&m, &n 
Con trỏ a,b bị giải phóng 
m,n đã thay đổi: 
m=30, n=20 
&m, &n 
BÀI TẬP THỰC HÀNH 
Bài tập 1 
 Khai báo 1 biến nguyên a và biến trỏ kiểu nguyen p, cho p trỏ đến a. in ra màn 
hình địa chỉ của a, nội dung trong p, địa chỉ của biến trỏ p. 
 #include 
#include 
#include 
void main() 
{ 
 int a, *p; 
 clrscr(); 
 p=&a; 
 printf("\nDia chi cua bien nho a= %x",&a); 
 printf("\nNoi dung cua bien tro p= %x",p); 
 printf("\n dia chi cu bien tro p= %x",&p); 
 getch(); 
} 
Bài tập 2 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
89 
Viết chương trình nhập vào từ bàn phím n số nguyên, cấp phát một vùng nhớ 
động để lưu trữ n số nguyên đó, hiện các số vừa nhập, tính tổng, trung bình cộng, 
max, min của dãy số đó. 
#include 
#include 
#include 
void main() 
{ 
 clrscr(); 
 int *a,n ,i; 
 printf("\n nhap so luong phan tu n= "); 
 scanf("%d",&n); 
 // cap phat bo nho 
 a=(int*)malloc(n*sizeof(int)); 
 //nhap du lieu 
 for(i=0;i<n;i++) 
 { 
 printf("\n Nhap so thu %d ",i+1); 
 scanf("%d",a+i); 
 } 
 // hien du lieu 
 printf("\n day so vua nhap la: "); 
 for(i=0; i<n; i++) 
 { 
 printf(" %d",*(a+i)); 
 } 
 //tinh tong 
 int tong=0; 
 for(i=0; i<n; i++) 
 { 
 tong=tong + *(a+i); 
 } 
 printf("\n tong cua day so do la: %d",tong); 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
90 
 //tinh tb cong 
 printf("\n Trung binh cong cua day do la: 
%f",tong/(n*1.0)); 
 // tim max 
 int max= *a; 
 for(i=0; i<n; i++) 
 { 
 if(max< *(a+i)) 
 max= *(a+i); 
 } 
 printf("\n so lon nhat la: %d",max); 
 //tim min 
 int min = *a; 
 for(i=0; i<n; i++) 
 { 
 if(min >*(a+i)) 
 min = *(a+i); 
 } 
 printf("\n so nho nhat la: %d", min); 
 getch(); 
} 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
91 
Chương 7 : CHUỖI KÝ TỰ 
1. Khái niệm 
Trong C không có kiểu xâu, do vậy ngôn ngữ C sử dụng mảng để lưu trữ chuỗi ký 
tự, mỗi phần tử của mảng sẽ là một kiểu dữ liệu kiểu char 
Chuỗi ký tự là một dãy các ký tự hoặc một mảng các ký tự. Các ký tự được lưu 
theo thứ tự từ trái sang phải của chuỗi và bắt đầu bằng phần tử có chỉ số 0 cho đến 
hết chuỗi. Kết thúc chuỗi là ký tự ‘\0’ (còn được gọi là ký tự NULL trong bảng mã 
ASCII). 
Các hằng chuỗi ký tự được đặt trong cặp dấu nháy kép ””. 
2. Khai báo 
2.1 Khai báo theo mảng 
 Cú pháp: char [Chiều dài tối đa] 
VD: Trong chương trình, ta có khai báo: 
 char Ten[12]; 
Trong khai báo trên, bộ nhớ sẽ cung cấp 12+1 bytes để lưu trữ nội dung của chuỗi 
ký tự Ten; byte cuối cùng để lưu ký tự ‘\0’ để chấm dứt chuỗi. 
Ghi chú: 
 Chiều dài tối đa của biến chuỗi là một hằng nguyên nằm trong khoẳng từ 1 đến 
255 bytes. 
 Chiều dài tối đa không nên khai báo thừa để tránh lẵng phí bộ nhớ, nhưng cũng 
không nên khai báo thiếu. 
2.2 Khai báo theo con trỏ 
Cú pháp: char *; 
VD: Trong chương trình, ta có khai báo: 
char *Ten; 
Trong khai báo trên, bộ nhớ sẽ dành 2 bytes để lưu trữ địa chỉ của biến con trỏ 
Ten đang chỉ đến, chưa cung cấp nơi để lưu trữ dữ liệu. Muốn có chỗ để lưu trữ dữ 
liệu, ta phải gọi đến hàm malloc() hoặc calloc có trong alloc.h, sau đó mới gán dữ liệu 
cho biến. 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
92 
3. Các thao tác trên chuỗi 
3.1 Nhập chuỗi từ bàn phím 
 Để nhập một chuỗi ký tự từ nàn phím, ta sử dụng hàm gets() với cú pháp như 
sau: 
 gets() 
VD: char Ten[20]; 
 gets(Ten); 
Ta cũng có thể sử dụng hàm scanf() để nhập dữ liệu cho biến chuỗi, tuy nhiên 
lúc này ta chỉ có thể nhập được một chuỗi không có dấu khoẳng trắng. 
 Ngoài ra, hàm cgets() (trong conio.h) cũng được sử dụng để nhập chuỗi. 
Chú ý: 
Nếu trước lệnh nhập chuỗi có lệnh nhập số thì phải xóa vùng đệm bàn phím 
trước khi nhập chuỗi bằng lệnh sau: 
 fflush(stdin); 
Ví dụ 
 int n; 
 char s[50]; 
 printf(“nhap so n =”); 
 scanf(“%d”,&n); 
 printf(“nhap chuoi s = ”); 
 fflush(stdin); gets(s); 
3.2 Xuất chuỗi ra màn hình 
 Để xuất chuỗi (biểu thức chuỗi) lên màn hình, ta sử dụng hàm puts(), với cú pháp 
như sau: 
 puts() 
 VD: Nhập vào một chuỗi và hiển thị trên màn hình chuỗi vừa nhập. 
#include 
#include 
#include 
int main() 
{ 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
93 
 char Ten[12]; 
printf(“Nhap chuoi:”); gets(Ten); 
printf(“Chuoi vua nhap”);puts(Ten); 
getch(); 
return 0; 
} 
 Ngoài ra, ta có thể sử dụng hàm printf(), cputs() (trong conio.h) để hiển thị 
chuỗi lên màn hình. 
3.3 Một số hàm xử lý chuỗi 
 Hàm cho biết độ dài thực sự (số ký tự) của chuỗi ký tự lưu trong mảng 
 int strlen(s); 
ví dụ: 
 char s[100] = “Ha Noi Viet Nam”; 
 int a = strlen(s); 
sẽ trả về độ dài thực của sâu s gán vào biến nhớ a, cụ thể là a = 15 
 Lệnh gán chuỗi từ sâu này vào sâu khác 
 strcpy(s1, s2 ); 
sẽ thưc hiện chép chuỗi ký tự trong sâu s2 vào s1. 
Chú ý: 
Trong ngôn ngữ C không thể sử dung phép gán ( = ) để gán hai chuỗi do đó phải 
sử dụng lệnh strcpy này. 
 Lệnh nối hai sâu lại với nhau 
 strcat( s1,s2); 
sẽ thưc hiện nối sâu S2 vào sâu S1 
ví dụ: 
 char s1[100] = “Ha Noi”; 
 char s2[100] =”Viet Nam”; 
strcat (s1,s2); 
kết quả xâu s1 sẽ thay đổi và đó là:”Ha NoiViet Nam” 
 Lệnh chuyển sâu thành chữ hoa 
 strupr(s); 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
94 
 Lệnh chuyển sâu thành chữ thường. 
 strlwr(s); 
3.4 Một số thao tác cơ bản trên chuỗi 
 Đêm ký tự, đếm từ 
Cho một chuỗi s và đếm xem trong chuỗi có bao nhiêu chữ thỏa mãn một điều 
kiện nào đó: 
 int dem = 0 
 for( i =0; i<strlen(s);i++) 
 if(s[i] thỏa mãn điều kiện) dem ++; 
 printf(“so ky tu dem duoc la: %d”,dem) ; 
Thuật toán đếm số từ co trong chuỗi s theo tiêu chuẩn nhận biết đầu từ( là 
cặp ký tự thỏa mãn ký tự trước là dấu cách, ký tự sau khác dấu cách). 
int dem; 
if(s[0] = = ‘ ’ ) dem = 0 ; 
else dem = 1; 
for( i = 1;i < strlen(s);i++ ) 
{ 
 if(s[i] = =’ ’&& s[i+1]!=’ ’) 
 dem ++; 
} 
printf(“so tu dem duoc là: %d”,dem) ; 
 Chuẩn hóa chuỗi ký tự 
Một chuỗi ký tự ở dạng chuẩn nếu không có dấu cách ở đầu, không có dấu cách 
ở cuối và giữa hai từ có duy nhất một dấu cách. 
 Thuật toán chuẩn hóa được chia làm 3 bước như sau 
Bước 1: Xóa dấu cách ở đầu 
 int i = 0 ; 
 while (s[i] = =’ ’&&i < strlen(s)) 
{ 
 i++ ; 
 strcpy(&s[0],&s[i]); 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
95 
 } 
Bước 2: Xóa dấu cách thừa giữu hai từ 
 int i = 0; 
while(i<strlen(s)-1) 
 { 
 if(s[i] == ‘ ‘&& s[i+1] == ‘ ‘ ) 
 strcpy(&s[i],&s[i+1]); 
 i++; 
} 
Bước 3: xóa dấu cách ở cuối chuỗi 
 while(s[strlen(s)-1] ==’ ’ ) s[strlen(s)-1]= ‘\0’; 
 Tách từ 
+ Tách từ đầu tiên 
 i=0; 
 while(s[i] = =' ')i++; 
 for(j=0;(i<strlen(s))&&(s[i]!=' ');i++,j++) 
 tudau[j] = s[i]; 
 tudau[j]='\0'; 
 Tách từ cuối cùng 
 i = strlen(s)-1; 
 while(s[i] = =' ')i--; 
 j=i; 
 while(s[i]!=' ')i--; 
 i++; 
 for(int x = 0;i<=j;i++) 
 { 
 tucuoi[x] = s[i]; 
 x++; 
 } 
 tucuoi[x] = '\0'; 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
96 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
97 
BÀI TẬP THỰC HÀNH 
Bài tập 1 
Lập trình đọc vào một sâu. Đọc vào từ bàn phím một kí tự bất kì, rồi đếm xem 
số lần xuất hiện ký tự này trong sâu. Báo kết quả ra màn hình. 
#include 
#include 
#include 
int dem(char s[],char a) 
{ 
 int d=0;//so ki tu 
 int l=strlen(s); 
 for(int i=0;i<l;i++) 
 { 
 if(s[i] == a) 
 d++; 
 } 
 return d; 
} 
void main() 
{ 
 int i; 
 char s[100],ch; 
 clrscr(); 
 printf("\n nhap vao mot cau: "); 
 fflush(stdin);gets(s); 
 printf("\n Nhap vao mot ki tu bat ki:"); 
 ch = getche(); 
 //dem so lan xuat hien cua ki tu 
 printf("\nki tu %c xuat hien %d lan trong xau 
",ch,dem(s,ch)); 
 getch(); 
} 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
98 
Bài tập 2 
Viết chương trình đọc vào một xâu. Đếm số từ của một sâu. Từ được hiểu là 
xâu khác rỗng và không có dấu cách. 
#include 
#include 
#include 
int sotu(char S[]) 
{ 
 int dem=0,n; 
 n=strlen(S); 
 if(S[0]!=' ')dem=1; 
 for(int i=1;i<n;i++) 
 { 
 if(S[i]= =' '&& S[i+1]!=' ')dem++; 
 } 
 return dem; 
} 
void main() 
{ 
 int i; 
 char s[100]; 
 clrscr(); 
 printf("\n nhap vao mot sau ki tu: "); 
 fflush(stdin);gets(s); 
 //dem so tu cua mot sau 
 printf("sau ban vua nhap co: %d tu",sotu(s)); 
 getch(); 
} 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
99 
Bài tập 3 
Lập trình đọc vào một câu từ bàn phím rồi đưa ra màn hình dưới dạng một cột. 
thí dụ đọc vào TIÊN HỌC LỄ HẬU HỌC VĂN kết quả đưa ra thành 
 TIÊN 
 HỌC 
 LỄ 
 HẬU 
 HỌC 
 VĂN 
#include 
#include 
#include 
void hien(char s[]) 
{ 
 int l=strlen(s),n=0; 
 while(s[n]= =' ')n++; 
 for(int i = n ; i<l ; i++) 
 { if(s[i]!=' ') 
 printf("% c",s[i]); 
 else 
 printf("\n"); 
 } 
} 
void main() 
{ int i; 
 char s[100]; 
 clrscr(); 
 printf("\n nhap vao mot cau: "); 
 fflush(stdin);gets(s); 
 printf("hien cau moi tu tren mot dong la:\n"); 
 hien(s); 
 getch(); 
} 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
100 
Bài tập 4 
Nhập vào từ bàn phím họ tên của một người. Hiện tên và họ của người đó lên 
màn hình. 
#include 
#include 
#include 
void main() 
{ 
 char s[100],ten[10],ho[10]; 
 int i=0,j=0; 
 clrscr(); 
 printf("\n nhap vao ten cua mot nguoi: "); 
 fflush(stdin);gets(s); 
 // tach ho 
 while(s[i]= =' ')i++; 
 do{ 
 ho[j]=s[i]; 
 i++; j++; 
 }while(s[i]!=' '); 
 ho[j]='\0'; 
 printf("\n ho cua nguoi nay la: %s",ho); 
 // tach ten 
 j=0; 
 i=strlen(s); 
 while(s[i]= =' ')i--; 
 int i1=i; 
 while(s[i1]!=' ')i1--; 
 do{ 
 ten[j]=s[i1]; 
 i1++; j++; 
 }while(i1<=i); 
 ten[j]='\0'; 
 printf("\n ten cua nguoi nay la: %s",ten); 
 getch(); } 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
101 
PHỤ LỤC 
HƯỚNG DẪN DEBUG TRÊN MÔI TRƯỜNG BORLAND C 
Mặc dù chương trình không còn lỗi nhưng khi chạy chương trình vẫn ra kết quả 
sai, những lỗi đó có thể là: 
• Dùng chấm phẩy sau: if, else, for, while,  mà chưa thực hiện lệnh. 
• Định dạng nhập xuất sai hay khai báo sai kiểu dữ liệu. 
• Chia cho 0. 
• Không có điều kiện dừng (điều kiện dừng sai). 
• Phân tích thuật toán thiếu (chưa vét hết các trường hợp) hoặc sai. 
Các thao tác debug: 
Nhấn F7 hoặc F8 để chạy từng bước (nếu không có lỗi khi biên dịch) 
- F7: Đi từng lệnh của hàm con nếu có gọi hàm. 
- F8: không vào chi tiết từng lệnh khi gọi đến hàm con (chỉ đưa ra kết quả của hàm 
con). 
 Quan sát vệt sáng để biết chương trình đang thực hiện đến vị trí lệnh nào. 
- Nhấn Ctrl+F7 (hoặc nhấn phím Insert nếu đã có cửa sổ Watch): Nhập vào biến 
cần theo dõi giá trị các biến khi thực hiện xong lệnh hay hàm nào đó. 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
102 
- Có thể xóa biến trên cửa sổ Watch bằng cách chọn biến trên cửa sổ Watch và 
nhấn phím Delete. 
- Nếu không thấy cửa sổ hiển thị giá trị biến (Watch) nhấn Alt+W+W hoặc vào 
menu Window chọn Watch. 
Nếu muốn bỏ qua một đoạn nào đó (tức không cần kiểm tra đọan đó) thì 
nhấn F4 để chương trình thực thi tới vị trí dòng của dấu nháy rồi dừng lại đó (dấu 
nháy phải tại vị trí những dòng phía sau của vệt sáng, nhấn F6 để chuyển qua lại các 
cửa sổ). 
- Muốn thay đổi giá trị của biến ta dùng phím Ctrl+F4 để hiển thị cửa sổ. 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
103 
Nhập vào tên biến ở ô Expression, chọn nút Evaluate (hoặ nhấn Enter), ô Result 
sẽ hiển thị kết quả tại thời điểm đó, sau đó nhập giá trị mới cho biến tại ô New Value 
  Enter (dùng phím tab để di chuyển vị trí chọn). 
Ngoài ra có thể đánh dấu để chương trình thực thi đến vị trí đánh dấu (khi chưa chạy 
từng bước) dùng phím F8 để đánh dấu ngay vị trí dấu nháy. Vị trí đánh dấu sẽ có vệt 
sáng màu đỏ. 
Có thể đánh dấu nhiều vị trí khác nhau. Nhấn Ctrl+F9 để chương trình thực thi 
đến vị trí đánh dấu theo thứ tự từ trên xuống dưới, đồng thời cũng có thể dùng phím 
F7 hoặc F8 giống như trên để chạy từng bước. 
Giáo trình: Lập trình cơ bản Trường Cao đẳng nghề Yên Bái 
104 
Ngoài ra, có thể dùng phím ALT+F5 để xem kết quả xuất trong quá trình debug 
(để kiểm tra nhập xuất). 
Trong quá trình chạy từng bước có thể kết thúc bằng cách nhấn Ctrl+F2. 
 Các thao tác liên quan đến cửa sổ Watch 
- Di chuyển cửa sổ Watch: Chọn cửa sổ Watch, nhấn Ctrl+F5. Sau đó dùng phím 
mũi tên để di chuyển cửa sổ tới vị trí mới. Nhấn phím Enter. 
- Thay đổi kích thứơc cửa sổ Watch (khi đang chọn bằng Ctrl+F5 trên cửa sổ 
Watch) nhấn Shift + phím mũi tên rồi nhấn phím Enter. 
TÀI LIỆU THAM KHẢO 
 PHẠM VĂN ẤT: “Kỹ thuật lập trình C: cơ sở và nâng cao”. Nhà Xuất BảnKhoa Học 
Kỹ Thuật – 1996. 
 Lê Mạnh Thạnh, Giáo trình môn lập trình C, NXB Giáo dục, 2000; 
 Nguyễn Linh Giang, Nguyễn Xuân Thực, Lê Văn Thái, Giáo trình kỹ thuật lập trình 
C, NXB Giáo dục, 2005; 
 Ngô Trung việt, Giáo trình ngôn ngữ lập trình C và C++ , NXB Giao thông vận tải, 
1995; 
 B. Kernighan and D. Ritchie, The C programming language, Prentice Hall, 1990. 
            Các file đính kèm theo tài liệu này:
 lap_tr_nh_co_ban_p2_5647.pdf lap_tr_nh_co_ban_p2_5647.pdf