Giáo trình Lập trình ứng dụng (Phần 2)

5.1 HÀM

Hàm nhận (hoặc không) các đối số và trả lại (hoặc không) một giá trị cho chương trình gọi nó.

Trong trường hợp không trả lại giá trị, hàm hoạt động như một thủ tục trong các ngôn ngữ lập trình

khác. Một chương trình là tập các hàm, trong đó có một hàm chính với tên gọi main(), khi chạy

chương trình, hàm main() sẽ được chạy đầu tiên và gọi đến hàm khác. Kết thúc hàm main() cũng

là kết thúc chương trình.

Hàm giúp cho việc phân đoạn chương trình thành những môđun riêng rẽ, hoạt động độc lập

với ngữ nghĩa của chương trình lớn, có nghĩa một hàm có thể được sử dụng trong chương trình

này mà cũng có thể được sử dụng trong chương trình khác, dễ cho việc kiểm tra và bảo trì chương

trình. Hàm có một số đặc trưng:

- Nằm trong hoặc ngoài văn bản có chương trình gọi đến hàm. Trong một văn bản có thể

chứa nhiều hàm;

- Được gọi từ chương trình chính (main()), từ hàm khác hoặc từ chính nó (đệ quy);

- Không lồng nhau;

- Có 3 cách truyền giá trị: Truyền theo tham trị, tham biến và tham trỏ.

5.1.1 Khai báo và định nghĩa hàm

1. Khai báo

Một hàm thường làm chức năng: tính toán trên các tham đối và cho lại giá trị kết quả, hoặc chỉ

đơn thuần thực hiện một chức năng nào đó, không trả lại kết quả tính toán. Thông thường kiểu của

giá trị trả lại được gọi là kiểu của hàm. Các hàm thường được khai báo ở đầu chương trình. Các

hàm viết sẵn được khai báo trong các file nguyên mẫu *.h. Do đó, để sử dụng được các hàm này,

cần có chỉ thị #include <*.h> ở ngay đầu chương trình, trong đó *.h là tên file cụ thể có chứa khai

báo của các hàm được sử dụng (ví dụ để sử dụng các hàm toán học ta cần khai báo file nguyên

mẫu math.h). Đối với các hàm do người lập trình tự viết, cũng cần phải khai báo. Khai báo một

hàm như sau:

(d/s kiểu đối) ;

trong đó, kiểu giá trị trả lại còn gọi là kiểu hàm và có thể nhận kiểu bất kỳ chuẩn của C++ và cả

kiểu của NSD tự tạo. Đặc biệt nếu hàm không trả lại giá trị thì kiểu của giá trị trả lại được khai

báo là void. Nếu kiểu giá trị trả lại được bỏ qua thì chương trình ngầm định hàm có kiểu là int

(phân biệt với void!). Ví dụ sau đây là một vài khai báo hàm:

int bp(int); // Khai báo hàm bp, có đối kiểu int và kiểu hàm là int

int rand100(); // Không đối, kiểu hàm (giá trị trả lại) là int

void alltrim(char[ ]); // đối là xâu kí tự, hàm không trả lại giá trị (không kiểu).

cong(int, int); // Hai đối kiểu int, kiểu hàm là int (ngầm định).

Thông thường để chương trình được rõ ràng chúng ta nên tránh lạm dụng các ngầm định. Ví94

dụ trong khai báo cong(int, int); nên khai báo rõ cả kiểu hàm (trong trường hợp này kiểu hàm

ngầm định là int) như sau : int cong(int, int);.

pdf 72 trang yennguyen 1440
Bạn đang xem 20 trang mẫu của tài liệu "Giáo trình Lập trình ứng dụng (Phần 2)", để tải tài liệu gốc về máy hãy click vào nút Download ở trên

Tóm tắt nội dung tài liệu: Giáo trình Lập trình ứng dụng (Phần 2)

Giáo trình Lập trình ứng dụng (Phần 2)
 93 
CHƯƠNG 5. HÀM VÀ CON TRỎ HÀM 
5.1 HÀM 
Hàm nhận (hoặc không) các đối số và trả lại (hoặc không) một giá trị cho chương trình gọi nó. 
Trong trường hợp không trả lại giá trị, hàm hoạt động như một thủ tục trong các ngôn ngữ lập trình 
khác. Một chương trình là tập các hàm, trong đó có một hàm chính với tên gọi main(), khi chạy 
chương trình, hàm main() sẽ được chạy đầu tiên và gọi đến hàm khác. Kết thúc hàm main() cũng 
là kết thúc chương trình. 
Hàm giúp cho việc phân đoạn chương trình thành những môđun riêng rẽ, hoạt động độc lập 
với ngữ nghĩa của chương trình lớn, có nghĩa một hàm có thể được sử dụng trong chương trình 
này mà cũng có thể được sử dụng trong chương trình khác, dễ cho việc kiểm tra và bảo trì chương 
trình. Hàm có một số đặc trưng: 
- Nằm trong hoặc ngoài văn bản có chương trình gọi đến hàm. Trong một văn bản có thể 
chứa nhiều hàm; 
- Được gọi từ chương trình chính (main()), từ hàm khác hoặc từ chính nó (đệ quy); 
- Không lồng nhau; 
- Có 3 cách truyền giá trị: Truyền theo tham trị, tham biến và tham trỏ. 
5.1.1 Khai báo và định nghĩa hàm 
1. Khai báo 
Một hàm thường làm chức năng: tính toán trên các tham đối và cho lại giá trị kết quả, hoặc chỉ 
đơn thuần thực hiện một chức năng nào đó, không trả lại kết quả tính toán. Thông thường kiểu của 
giá trị trả lại được gọi là kiểu của hàm. Các hàm thường được khai báo ở đầu chương trình. Các 
hàm viết sẵn được khai báo trong các file nguyên mẫu *.h. Do đó, để sử dụng được các hàm này, 
cần có chỉ thị #include ở ngay đầu chương trình, trong đó *.h là tên file cụ thể có chứa khai 
báo của các hàm được sử dụng (ví dụ để sử dụng các hàm toán học ta cần khai báo file nguyên 
mẫu math.h). Đối với các hàm do người lập trình tự viết, cũng cần phải khai báo. Khai báo một 
hàm như sau: 
 (d/s kiểu đối) ; 
trong đó, kiểu giá trị trả lại còn gọi là kiểu hàm và có thể nhận kiểu bất kỳ chuẩn của C++ và cả 
kiểu của NSD tự tạo. Đặc biệt nếu hàm không trả lại giá trị thì kiểu của giá trị trả lại được khai 
báo là void. Nếu kiểu giá trị trả lại được bỏ qua thì chương trình ngầm định hàm có kiểu là int 
(phân biệt với void!). Ví dụ sau đây là một vài khai báo hàm: 
int bp(int); // Khai báo hàm bp, có đối kiểu int và kiểu hàm là int 
int rand100(); // Không đối, kiểu hàm (giá trị trả lại) là int 
void alltrim(char[ ]); // đối là xâu kí tự, hàm không trả lại giá trị (không kiểu). 
cong(int, int); // Hai đối kiểu int, kiểu hàm là int (ngầm định). 
Thông thường để chương trình được rõ ràng chúng ta nên tránh lạm dụng các ngầm định. Ví 
 94 
dụ trong khai báo cong(int, int); nên khai báo rõ cả kiểu hàm (trong trường hợp này kiểu hàm 
ngầm định là int) như sau : int cong(int, int);. 
2. Định nghĩa hàm 
Cấu trúc một hàm bất kỳ được bố trí cũng giống như hàm main() trong các phần trước. 
Hàm có trả về giá trị 
Cú pháp: 
 (danh sách tham đối hình thức) 
{ 
khai báo cục bộ của hàm ; // chỉ dùng riêng cho hàm này 
dãy lệnh của hàm ; 
return (biểu thức trả về); // có thể nằm đâu đó trong dãy lệnh. 
} 
Trong đó: 
- Danh sách tham đối hình thức còn được gọi ngắn gọn là danh sách đối gồm dãy các đối 
cách nhau bởi dấu phẩy, đối có thể là một biến thường, biến tham chiếu hoặc biến con trỏ, 
hai loại biến sau ta sẽ trình bày trong các phần tới. Mỗi đối được khai báo giống như khai 
báo biến, tức là cặp gồm . 
- Với hàm có trả lại giá trị cần có câu lệnh return kèm theo sau là một biểu thức. Kiểu của 
giá trị biểu thức này chính là kiểu của hàm đã được khai báo ở phần tên hàm. Câu lệnh 
return có thể nằm ở vị trí bất kỳ trong phần câu lệnh, tuỳ thuộc mục đích của hàm. Khi gặp 
câu lệnh return chương trình tức khắc thoát khỏi hàm và trả lại giá trị của biểu thức sau 
return như giá trị của hàm. 
Ví dụ 5.1: Viết hàm tính luỹ thừa n (với n nguyên) của một số thực bất kỳ. 
double luythua(float x, int n) 
{ 
int i ; // biến chỉ số 
double kq = 1 ; // để lưu kết quả 
for (i=1; i<=n; i++) kq *= x ; 
return kq; 
} 
Có nhiều cách giải quyết cho yêu cầu trong ví dụ này, tuy nhiên ở đây nêu ra cách giải quyết 
gần nhất với định nghĩa của lũy thừa. Lệnh kq *= x tương đương với kq=kq*x nên khi kết thúc 
vòng for (i=1; i<=n; i++) giá trị của kq chính là giá trị cần tính xn. 
Hàm không trả về giá trị 
Cú pháp: 
void (danh sách tham đối hình thức) 
 95 
{ 
khai báo cục bộ của hàm ; // chỉ dùng riêng cho hàm này 
dãy lệnh của hàm ; 
[return;] 
} 
Nếu hàm không trả lại giá trị (tức kiểu hàm là void), khi đó có thể có hoặc không có câu lệnh 
return, nếu có thì đằng sau return sẽ không có biểu thức giá trị trả lại. 
Ví dụ 5.2: Viết hàm cho hiển thị lên màn hình 10 lần dòng chữ "Ky thuat lap trinh". 
void hienthi() 
{ 
int i; 
for (i=1; i<=10; i++) 
printf("Ky thuat lap trinh"); 
return; 
} 
Hàm này chỉ thực hiện việc in lên màn hình dòng chữ "Ky thuat lap trinh" 10 lần, vì không trả 
về giá trị nào nên hàm khai báo có kiểu là void, hàm không trả về giá trị nào nên lệnh trả về là 
return không có tham số. 
Hàm main() 
Trong hầu hết các trình biên dịch hàm main() cho phép có hoặc không có giá trị trả về khi 
chương trình chạy xong, trình biên dịch DevC++ cho phép làm điều này vì vậy có thể khai báo 
hàm là int main() hoặc void main() và câu lệnh cuối cùng trong hàm là return 1 (return 0) hoặc 
return. Trường hợp bỏ qua từ khoá void nhưng trong thân hàm không có câu lệnh return thì chương 
trình sẽ ngầm hiểu hàm main() trả lại một giá trị nguyên nhưng vì không có nên khi biên dịch 
chương trình ta sẽ gặp lời cảnh báo “Cần có giá trị trả lại cho hàm” (một lời cảnh báo không phải 
là lỗi, chương trình vẫn chạy bình thường). Để tránh bị quấy rầy về những lời cảnh báo “không 
mời” này chúng ta có thể đặt thêm câu lệnh return 0; (nếu không khai báo void main()) hoặc khai 
báo kiểu hàm là void main() và đặt câu lệnh return vào cuối hàm. 
Chú ý: 
- Danh sách đối trong khai báo hàm có thể chứa hoặc không chứa tên đối, thông thường ta 
chỉ khai báo kiểu đối chứ không cần khai báo tên đối, trong khi ở dòng đầu tiên của định 
nghĩa hàm phải có tên đối đầy đủ; 
- Cuối khai báo hàm phải có dấu chấm phẩy (;), trong khi cuối dòng đầu tiên của định nghĩa 
hàm không có dấu chấm phẩy; 
- Hàm có thể không có đối (danh sách đối rỗng), tuy nhiên cặp dấu ngoặc sau tên hàm vẫn 
phải được viết. Ví dụ lamtho(), vietgiaotrinh(),  ; 
- Một hàm có thể không cần phải khai báo nếu nó được định nghĩa trước khi có hàm nào đó 
 96 
gọi đến nó. Ví dụ có thể viết hàm main() trước (trong văn bản chương trình), rồi sau đó 
mới viết đến các hàm “con”. Do trong hàm main() chắc chắn sẽ gọi đến hàm con này nên 
danh sách của chúng phải được khai báo trước hàm main(). Trường hợp ngược lại nếu các 
hàm con được viết (định nghĩa) trước thì không cần phải khai báo chúng nữa (vì trong định 
nghĩa đã hàm ý khai báo). Nguyên tắc này áp dụng cho hai hàm A, B bất kỳ chứ không 
riêng cho hàm main(), nghĩa là nếu B gọi đến A thì trước đó A phải được định nghĩa hoặc 
ít nhất cũng có dòng khai báo về A. 
5.1.2 Lời gọi và sử dụng hàm 
Lời gọi hàm được phép xuất hiện trong bất kỳ biểu thức, câu lệnh của hàm khác  Nếu lời 
gọi hàm lại nằm trong chính bản thân hàm đó thì ta gọi là đệ quy. Để gọi hàm ta chỉ cần viết tên 
hàm và danh sách các giá trị cụ thể truyền cho các đối đặt trong cặp dấu ngoặc tròn (). 
Cú pháp: 
Tên_hàm(danh sách tham đối thực sự) ; 
Trong đó: 
- Danh sách tham đối thực sự còn gọi là danh sách giá trị gồm các giá trị cụ thể để gán lần 
lượt cho các đối hình thức của hàm. Khi hàm được gọi thực hiện thì tất cả những vị trí xuất 
hiện của đối hình thức sẽ được gán cho giá trị cụ thể của đối thực sự tương ứng trong danh 
sách, sau đó hàm tiến hành thực hiện các câu lệnh của hàm (để tính kết quả); 
- Danh sách tham đối thực sự truyền cho tham đối hình thức có số lượng bằng với số lượng 
đối trong hàm và được truyền cho đối theo thứ tự tương ứng. Các tham đối thực sự có thể 
là các hằng, các biến hoặc biểu thức. Biến trong giá trị có thể trùng với tên đối. Ví dụ ta có 
hàm in n lần kí tự c với tên hàm inkitu(int n, char c); và lời gọi hàm inkitu(12, 'A'); thì n 
và c là các đối hình thức, 12 và 'A' là các đối thực sự hoặc giá trị. Các đối hình thức n và c 
sẽ lần lượt được gán bằng các giá trị tương ứng là 12 và 'A' trước khi tiến hành các câu 
lệnh trong phần thân hàm. Giả sử hàm in kí tự được khai báo lại thành inkitu(char c, int 
n); thì lời gọi hàm cũng phải được thay lại thành inkitu('A', 12); 
- Các giá trị tương ứng được truyền cho đối phải có kiểu cùng với kiểu đối (hoặc C++ có 
thể tự động chuyển kiểu được về kiểu của đối); 
- Khi một hàm được gọi, nơi gọi tạm thời chuyển điều khiển đến thực hiện dòng lệnh đầu 
tiên trong hàm được gọi. Sau khi kết thúc thực hiện hàm, điều khiển lại được trả về thực 
hiện tiếp câu lệnh sau lệnh gọi hàm của nơi gọi. 
Ví dụ 5.3: Viết chương trình tính giá trị của biểu thức 2x3 - 5x2 - 4x + 1 bằng cách sử dụng hàm 
luythua() để tính các thành phần x3 và x2. 
#include 
#include 
double luythua(float x, int n) // trả lại giá trị xn 
{ 
int i ; // biến chỉ số 
double kq = 1 ; // để lưu kết quả 
 97 
for (i=1; i<=n; i++) kq *= x ; 
return kq; 
} 
main() // tính giá trị 2x3
- 5x2
- 4x + 1 
{ 
float x ; // tên biến có thể trùng với đối của hàm 
double f ; // để lưu kết quả 
printf("x = "); 
scanf("%d" ,&x ) ; 
f = 2*luythua(x,3) - 5*luythua(x,2) - 4*x + 1; 
printf("%d",f) ; 
getch(); 
return 0; 
} 
Ví dụ này cho thấy lợi ích của lập trình cấu trúc, chương trình trở nên gọn hơn, chẳng hạn hàm 
luythua() chỉ được viết một lần nhưng có thể sử dụng nó nhiều lần (2 lần trong ví dụ này) chỉ bằng 
một câu lệnh gọi đơn giản cho mỗi lần sử dụng thay vì phải viết lại nhiều lần đoạn lệnh tính luỹ 
thừa. 
5.1.3 Hàm với đối mặc định 
Mục này và mục sau chúng ta bàn đến một vài mở rộng thiết thực của C/C++ đối với C có liên 
quan đến hàm, đó là hàm với đối mặc định và cách tạo, sử dụng các hàm có chung tên gọi. Một 
mở rộng quan trọng khác là cách truyền đối theo tham chiếu sẽ được bàn chung trong mục truyền 
tham đối thực sự cho hàm. 
Trong phần trước chúng ta đã khẳng định số lượng tham đối thực sự phải bằng số lượng tham 
đối hình thức khi gọi hàm. Tuy nhiên, trong thực tế rất nhiều lần hàm được gọi với các giá trị của 
một số tham đối hình thức được lặp đi lặp lại. Trong trường hợp như vậy lúc nào cũng phải viết 
một danh sách dài các tham đối thực sự giống nhau cho mỗi lần gọi là một công việc không mấy 
thú vị. Từ thực tế đó C++ đưa ra một cú pháp mới về hàm sao cho một danh sách tham đối thực 
sự trong lời gọi không nhất thiết phải viết đầy đủ nếu một số trong chúng đã có sẵn những giá trị 
định trước. 
Cú pháp: 
 (đ1, , đn, đmđ1 = gt1, , đmđm = gtm) 
Trong đó: 
- Các đối đ1, , đn và đối mặc định đmđ1, , đmđm đều được khai báo như bình thường, 
nghĩa là gồm có kiểu đối và tên đối; 
- Riêng các đối mặc định đmđ1, , đmđm có gán thêm các giá trị mặc định gt1, , gtm. 
Một lời gọi bất kỳ khi gọi đến hàm này đều phải có đầy đủ các tham đối thực sự ứng với 
 98 
các đ1, , đm nhưng có thể có hoặc không các tham đối thực sự ứng với các đối mặc định 
đmđ1, , đmđm. Nếu tham đối nào không có tham đối thực sự thì nó sẽ được tự động gán 
giá trị mặc định đã khai báo. 
Ví dụ, nếu khai hàm trong ví dụ 3.2 được viết lại là hienthi(int n = 10), trong đó n mặc định 
là 10. Khi đó nếu gọi hienthi(9) thì chương trình hiển thị dòng "Kỹ thuật lập trình" 9 lần, còn nếu 
gọi hienthi(10) hoặc gọn hơn hienthi() thì chương trình sẽ hiển thị 10 lần. 
Tương tự, nếu khai báo hàm trong ví dụ 3.3 được viết lại là int luythua(float x, int n = 2), khi 
đó tham số n được khai báo với giá trị mặc định là 2, nếu lời gọi hàm bỏ qua số mũ này thì chương 
trình hiểu là tính bình phương của x (n = 2), ví dụ lời gọi luythua(4, 3) được hiểu là 43, còn 
luythua(2) được hiểu là 22. 
Một ví dụ khác, giả sử viết hàm tính tổng 4 số nguyên: int tong(int m, int n, int i = 0; int j = 
0) khi đó có thể tính tổng của 5, 2, 3, 7 bằng lời gọi hàm tong(5,2,3,7) hoặc có thể chỉ tính tổng 3 
số 4, 2, 1 bằng lời gọi tong(4,2,1) hoặc cũng có thể gọi tong(6,4) chỉ để tính tổng của 2 số 6 và 4. 
Chú ý: Các đối ngầm định phải được khai báo liên tục và xuất hiện cuối cùng trong danh sách 
đối. Ví dụ: 
int tong(int x, int y=2, int z, int t=1); // sai vì các đối mặc định không liên tục 
void xoa(int x=0, int y) // sai vì đối mặc định không ở cuối 
5.1.4 Khai báo hàm trùng tên 
Hàm trùng tên hay còn gọi là hàm chồng (đè). Đây là một kỹ thuật cho phép sử dụng cùng một 
tên gọi cho các hàm “giống nhau” (cùng mục đích) nhưng xử lý trên các kiểu dữ liệu khác nhau 
hoặc trên số lượng dữ liệu khác nhau. Ví dụ hàm sau tìm số lớn nhất trong 2 số nguyên: 
int max(int a, int b) { return (a > b) ? a: b; } 
Nếu đặt c = max(3, 5) ta sẽ có c = 5. Tuy nhiên cũng tương tự như vậy nếu đặt c = max(3.0, 
5.0) chương trình sẽ bị lỗi vì các giá trị có kiểu float không phù hợp về kiểu là int của đối trong 
hàm max(). Trong trường hợp như vậy chúng ta phải viết hàm mới để tính max() của 2 số thực. 
Mục đích, cách làm việc của hàm này hoàn toàn giống hàm trước, tuy nhiên trong C và các ngôn 
ngữ lập trình khác chúng ta buộc phải sử dụng một tên mới cho hàm “mới” này. Ví dụ: 
float fmax(float a, float b) { return (a > b) ? a: b ; } 
tương tự để tuận tiện ta sẽ viết thêm các hàm: 
char cmax(char a, char b) { return (a > b) ? a: b ; } 
long lmax(long a, long b) { return (a > b) ? a: b ; } 
double dmax(double a, double b) { return (a > b) ? a: b ; } 
Tóm lại ta sẽ có 5 hàm: max(), cmax(), fmax(), lmax(), dmax(), việc sử dụng tên như vậy sẽ 
gây bất lợi khi cần gọi hàm. C++ cho phép ta có thể khai báo và định nghĩa cả 5 hàm trên với cùng 
1 tên gọi, ví dụ là max. Khi đó ta có 5 hàm: 
1: int max(int a, int b) { return (a > b) ? a: b ; } 
2: float max(float a, float b) { return (a > b) ? a: b ; } 
3: char max(char a, char b) { return (a > b) ? a: b ; } 
 99 
4: long max(long a, long b) { return (a > b) ? a: b ; } 
5: double max(double a, double b) { return (a > b) ? a: b ; } 
Và lời gọi hàm bất kỳ dạng nào như max(3,5), max(3.0,5), max('O', 'K') đều được đáp ứng. 
Chúng ta có thể đặt ra vấn đề: với cả 5 hàm cùng tên như vậy, chương trình gọi đến hàm nào. Vấn 
đề được giải quyết dễ dàng vì chương trình sẽ dựa vào kiểu của các đối khi gọi để quyết định chạy 
hàm nào. Ví dụ lời gọi max(3,5) có 2 đối đều là kiểu nguyên nên chương trình sẽ gọi hàm 1, lời 
gọi max(3.0,5) hướng đến hàm số 2 và tương tự chương trình sẽ chạy hàm số 3 khi gặp lời gọi 
max('O','K'). Như vậy một đặc điểm của các hàm trùng tên đó là trong danh sách đối của chúng 
phải có ít nhất một cặp đối nào đó khác kiểu nhau. Một đặc trưng khác để phân biệt thông qua các 
đối đó là số lượng đối trong các hàm phải khác nhau (nếu kiểu của chúng là giống nhau). 
Ví dụ việc vẽ các hình: thẳng, tam giác, vuông, chữ nhật trên màn hình là giống nhau, chúng 
chỉ phụ thuộc vào số lượng các điểm nối và toạ độ của chúng. Do vậy ta có thể khai báo và định 
nghĩa 4 hàm vẽ nói trên với cùng chung tên gọi. Chẳng hạn: 
void ve(Diem A, Diem B) ; // vẽ đường thẳng AB 
void ve(Diem A, Die ...  bản vào. Đây cũng là một trong những control thông dụng 
nhất trong lập trình visual. 
 6.2.3.1. Các thuộc tính 
Cũng giống như button và label, textbox cũng có những thuộc tính gần giống với thuộc tính của 
2 control mà ta đã được học qua. Dưới đây là bảng những thuộc tính thông dụng nhất của 
textbox: 
 Tên Thuộc tính Giá Trị Diễn giải 
MaxLength integer Chiều dài tối đa dữ liệu nhập (ký tự) 
Multiline True 
False 
Cho hay không cho textbox cao lên để cho phép nhập 
nhiều dòng. 
PasswordChar character Nếu bạn muốn textbox này là 1 password field thì bạn 
chỉ cần chỉ định character mà bạn muốn hiển thị khi bạn 
nhập password vào thuộc tính này. 
ReadOnly True 
False 
Cho hay không cho phép nhập liệu vào textbox này. 
RightToLeft Yes 
No 
Yes – Nếu bạn muốn canh lề phải dữ liệu nhập. 
ScrollBar 
Thuộc tính này chỉ có tác dụng khi bạn chọn Multiline= True NoneKhông có thanh 
cuộn.HorizontalChỉ có thanh cuộn đứng.VerticalChỉ có thanh cuộn ngang.BothCó cả 2 thanh 
cuộn đứng và ngang.WordWrap 
Thuộc tính này chỉ có tác dụng khi bạn chọn Multiline= TrueTrue 
FalseTrue – Nếu bạn muốn khi nhập liệu vào textbox thì nó sẽ tự động xuống dòng nếu như hết 
hàng. 
 138 
 6.2.3.2. Các sự kiện 
Cũng như label, Textbox thường chức năng chính là để nhập liệu nên nó cũng ít khi phải sử dụng 
các sự kiện nên ở phần này ta cũng không bàn về các sự kiện của textbox. 
 6.2.3.3 Ví dụ: 
a) Hãy tạo một project có tên TextBox và tạo giao diện nhập mới 1 sinh viên giống như hình 
dưới. Ví dụ này chỉ giới thiệu về cách thiết kế giao diện, không có các xử lý sự kiện. 
Với các thuộc tính: 
 GroupBox Name 
Text 
ForeColor 
grpThongTinCaNhan 
Thông Tin Cá Nhân 
Đỏ sậm 
Label Name 
Text 
ForeColor 
Mặc định 
Mã Số 
Xanh dương (blue) 
Label Name 
Text 
ForeColor 
Mặc định 
Họ và Tên 
Xanh dương (blue) 
Label Name 
Text 
ForeColor 
Mặc định 
Ngày Sinh 
Xanh dương (blue) 
 139 
Label Name 
Text 
ForeColor 
Mặc định 
Nơi Sinh 
Xanh dương (blue) 
Label Name 
Text 
ForeColor 
Mặc định 
Địa Chỉ 
Xanh dương (blue) 
Label Name 
Text 
ForeColor 
Mặc định 
Số ĐT 
Xanh dương (blue) 
Label Name 
Text 
ForeColor 
Mặc định 
Mã Số 
Xanh dương (blue) 
TextBox Name txtMaSV 
TextBox Name txtHovaTen 
TextBox Name txtNgaySinh 
TextBox Name txtNoiSinh 
TextBox Name txtDiaChi 
TextBox Name txtSoDT 
TextBox Name txtEmail 
Button Name 
Text 
btnLuu 
Lưu 
Button Name 
Text 
btnHuỷ 
Huỷ 
Button Name 
Text 
btnThoat 
Thoát 
Lưu ý: 
Các đối tượng label: 
font-name: tahoma 
font-size: 10px 
font-weight: bold 
Các đối tượng textbox 
 140 
font-name: tahoma 
font-size: 10px 
font-weight: normal 
 b) Hãy tạo một project có tên là TextArea và tạo giao diện form cho 1 ứng dụng soạn thảo văn 
bản đơn giản giống như hình dưới. Ví dụ này cũng chỉ để giúp bạn tạo giao diện mà thôi, không 
có các xử lý. 
với các thuộc tính sau: 
 From Name 
Text 
frmEditor 
Chương Trình Soạn Thảo Văn 
Bản 
Button Name 
Text 
btnLuuFile 
Lưu File 
Button Name 
Text 
btnMoFile 
Mở File 
Textbox Name txtEditor 
2 button sử dụng 
font: tahoma 
size: 10pt 
weight: bold 
 141 
Textbox sử dụng 
font: tahoma 
size: 12pt 
weight: normal 
6.3 MỘT SỐ VÍ DỤ 
6.3.1 Làm việc với Listbox 
Bước 1: Design như hình dưới 
Add 2 listbox, 1 listbox đã add sẵn các item và 1 listbox rỗng (add các item bằng mã khi 
loadform: code dưới) 
Bước 2: Code xử lý sự kiện cho từng nút 
 142 
Cuối cùng chạy thử xem 
 143 
6.3.2 Làm việc với RadioButton 
Bước 1: Design 
Khi mình nhập vào họ tên và chọn radion với mã là chữ thường hoặc chữ hoa sau đó nhấn vào 
kết quả thì sẽ hiển thị lên textbox, xóa thì sẽ xóa trắng hết các ô textbox 
Bước 2: code 
Hoàn thành 
 144 
6.3.3 Làm việc với Timer 
Bước 1: Design 
Add 2 buton và 1 label để hiển thị thời gian đếm ngược, ngoài ra mình kéo thêm 1 phần tử là 
timer, các bạn có thể tìm thấy trong phần toolbox 
Bước 2: Code: 
 145 
Ở đây kích đúp vào timer để xử lý thời gian sau đó cho nó hiển thị thời gian đếm ngược lên 
form, các bạn có thể cho tăng thời gian hoặc giảm thời gian bằng cách tăng hoặc giảm i đi là 
được (i++) hoặc (i–) 
6.3.4 Viết chương trình thực hiện các phép tính 
Tạo Project Lab03 
ừ màn hình khởi động Microsoft Studio chọn Menu File - New – Project 
 146 
ại ứng dụng: Windows Forms Application 
ờng dẫn lưu Prject 
Hình 6.8 Màn hình tạo mới Project 
Kết quả màn hình VS.NET cho ứng dụng Windows Form bao gồm các phần cơ bản 
(1): Toolbox: Chứa các control cho phép kéo thả vào Form 
(2): Màn hình thiết kế Form, có thể chuyển sang phần code editer 
(3): Cửa sổ Solution Explorer: Cho phép người lập trình có thể quản lý các thành phần trong 
project, hỗ trợ định vị nhanh chóng đến các file mã nguồn. 
(4): Cửa sổ property: cho phép user có thể custom lại các thành phần control trên form như: thiết 
lập các thuộc tính cho control, form, component, cho phép khai báo trình xử lý sự kiện của các 
control trên form 
 147 
Hình 6.9 Màn hình VS. NET phục vụ cho việc tạo project Windows Form 
ết quả trang Form1.cs [Code behide] 
Hình 6.10 Màn hình Code Behide 
 148 
Thiết kế Form theo mẫu tại trang Form1 .cs [Design] 
o Kéo thả các Control trong Toolbox như mẫu. 
Hình 6.11 Màn hình form Design được thiết kế 
ặt thuộc tính cho các đối tượng trên WebForm như sau: 
Viết mã lệnh xử lý : Viết các hàm xử lý sự kiện bấm vào nút + như sau: 
 149 
Hình 6.12 Màn hình Code Behide của Form 
Chạy kiểm thử chương trình 
o Kiểm lỗi trước khi chạy: Từ Menu Build →Chọn Build Solution 
Hình 6.14 Màn hình Biên dịch ứng dụng 
o Chạy chương trình Bấm Ctrl + F5 :Để chạy chương trình (không debug) và F5 để chạy debug. 
 150 
Hình 6.15 Kết quả thực thi ứng dụng 
6.4 ĐIỀU KHIỂN LED VỚI ARDUINO VÀ C# 
6.4.1 Phần cứng: 
Phần cứng tương tự như những dự án bật tắt led bình thường 
 Arduino UNO 
 1x led 
 1x điện trở 1k 
 Phần mềm Microsoft Visual C# 
6.4.2 Sơ đồ nối dây: 
Hình 6.16 Sơ đồ nối dây 
 151 
6.4.3 Phần mềm: 
Code arduino: 
1. int val; 
2. int led = 13; 
3. void setup() { 
4. pinMode(led, OUTPUT); 
5. Serial.begin(9600); 
6. } 
7. void loop() { 
8. while (Serial.available()) { 
9. val = Serial.read(); 
10. Serial.println(val); 
11. delay(200); 
12. } 
13. if (val == '1') { 
14. digitalWrite(led, LOW); 
15. } else if (val == '2') { 
16. digitalWrite(led, HIGH); 
17. } 
18. } 
Thiết kế giao diện điều khiển: 
Trên màn hình của Microsoft Visual C# nhấp chọn ToolBox rồi kéo thả các đối tượng: Button, 
serialPort, Label, ComboBox, Timer,.như giao diện. Sau đó nhấp đúp chuột vào các đối tượng 
để viết code cho từng đối tượng 
 152 
Hình 6.17 Giao diện điều khiển 
1. // Code điều khiển 
2. using System; 
3. using System.Collections.Generic; 
4. using System.ComponentModel; 
5. using System.Data; 
6. using System.Drawing; 
7. using System.Linq; 
8. using System.Text; 
9. using System.Windows.Forms; 
10. // Phần trên là phần khởi tạo mặc định bạn không cần quan tâm 
11. using System.IO.Ports; // Thêm dòng Code này để dùng lệnh với Serial.Port 
12. 
13. namespace Dieukhien 
14. { 
15. public partial class Form1 : Form 
16. { 
 153 
17. public Form1() 
18. { 
19. InitializeComponent(); 
20. } 
21. 
22. private void Form1_Load(object sender, EventArgs e) // Khi phần mềm được mở 
23. { 
24. comboBox1.DataSource = SerialPort.GetPortNames();//Quét các cổng Serial đang hoạt 
động lên ComboBox1 
25. 
26. } 
27. 
28. private void button1_Click(object sender, EventArgs e)// 
29. { 
30. if (!serialPort1.IsOpen) // Nếu đối tượng serialPort1 chưa được mở , sau khi nhấn button 
1 thỳ 
31. { 
32. 
33. serialPort1.PortName = comboBox1.Text;//cổng serialPort1 = ComboBox mà bạn đang 
chọn 
34. serialPort1.Open();// Mở cổng serialPort1 
35. 
36. 
37. } 
38. private void button4_Click(object sender, EventArgs e)// 
39. { 
40. 
41. serialPort1.Close();//Đóng cổng Serial sau khi button 4 được nhấn 
42. } 
43. 
44. } 
45. 
46. private void button2_Click(object sender, EventArgs e) 
 154 
47. { 
48. serialPort1.Write("2");//Nếu button2 được nhấn,gửi byte “1” đến cổng serialPort1 
49. } 
50. 
51. private void button3_Click(object sender, EventArgs e) 
52. { 
53. serialPort1.Write("1");//gửi byte “0” đến cổng serialPort1 
54. } 
55. 
56. private void tácGiảToolStripMenuItem1_Click(object sender, EventArgs e) 
57. { 
58. MessageBox.Show("Phần mềm được viết bởi Ðỗ Hữu Toàn (Bạn của Ðinh Hồng Thái)", 
"Tác giả");// Nếu MenuTrip tác giả được nhấn thỳ hiện lên hộp thoại 
59. } 
60. 
61. private void thoátToolStripMenuItem_Click(object sender, EventArgs e) 
62. { 
63. Application.Exit(); // Nếu ấn thoátThoát chương trình 
64. } 
65. 
66. private void timer1_Tick(object sender, EventArgs e) 
67. { 
68. if (!serialPort1.IsOpen) { 
69. button1.Text = ("Kết nối"); 
70. label3.Text = ("Chưa kết nối"); 
71. label3.ForeColor = Color.Red; 
72. //Nếu Timer được làm mới, Cổng serialPort1 chưa được mở thì thay đổi Text trong 
button1, label3đổi màu text label3 thành màu đỏ 
73. } 
74. else if (serialPort1.IsOpen) { 
75. button1.Text = ("Ngắt kết nối"); 
76. label3.Text = ("Ðã kết nối"); 
77. label3.ForeColor = Color.Green; 
 155 
78. //Nếu Timer được làm mới, Cổng serialPort1 đã mở thì thay đổi Text trong button1, 
label3đổi màu text label3 thành màu xanh 
79. 
80. } 
81. } 
82. 
83. } 
84. } 
6.5 BÀI TẬP 
1. Thêm vào Project 6.3.4 Form frmUocboi, thực hiện tìm “Ước số chung lớn nhất ” và 
“Bội số chung nhỏ nhất” của 2 số nguyên A và B: 
Yêu cầu: 
- Viết hàm tìm USCLN và BSCNN của 2 số a và b. Nếu ta chọn Option USCLN thì xuất ra kết 
quả ước số chung lớn nhất hay ngược lại là bội số chung nhỏ nhất. 
- Nút bỏ qua dùng để xóa rỗng các Textbox. 
- Nút Thoát có xuất hiện thông báo 
2. Viết chương trình nhập vào 2 số a, b và c cho biết số lớn nhất và nhỏ nhất 
trong 3 số a, b và c với giao diện như sau 
 156 
Hướng dẫn gợi ý: sử dụng cấu trúc If Else 
3. Viết chương trình nhập vào giá trị nguyên dương N, tính tổng 
S = 1 + 2 + 3 ++ N 
với giao diện như sau 
 157 
TÀI LIỆU THAM KHẢO 
[1]. D.E. Knuth, The Art of Computer Programming, Volume 1, Fundamental Algorithms, 
Addison-Wesley, Reading, MA,1973. 
[2]. D.E. Knuth, The Art of Computer Programming, Volume 2, Searching and Sorting, Addison-
Wesley, Reading, MA,1973. 
[3]. Francis Scheid, Computers and Programming, McGraw-Hill Book Company, 
Singapore,1983. 
[4]. Ian Parberry, Algorithm Analysis and Complexity, Depart. of Computer Sciences, University 
of North Texas, 2001. 
[5]. Ian Parberry, William Gasarch, Problems on Algorithms, Prentice-Hall, 2002. 
[6]. Jon Bentley, Programming Pearls, 2nd Edition, Addison-Wesley, Inc., 2000. 
[7]. N. Wirth, Data Structure + Algorithm = Programs, Pretice-Hall Inc. 1976. 
[8]. Peter Juliff, Program Design, 2nd Edition, Prentice-Hall, 1986. 
[9]. William B. Jones, Programming Concepts, Prentice-Hall, Inc., 1982. 
 158 
PHỤ LỤC 
Source Code: 
2.5.1 – Bài 1 
/* Vi du 1 - Tinh dien tich tam giac khi biet chieu cao va canh day */ 
#include 
#include 
#include 
// Chuong trinh chinh 
int main() 
{ int a,h; // a - chieu dai day, h - chieu cao 
 float s; // Dien tich tam gia 
 system("cls"); // Xoa man hinh 
 printf("Nhap vao a va h:"); 
 scanf("%d %d",&a,&h); 
 s=a*h; 
 printf("Dien tich bang ", s); 
 printf("Nhan phim bat ky de ket thuc!"); 
 getch(); // Dung doi nhan phim bat ky 
 return 0; 
} 
2.5.1 – Bài 1 
/* Chuong trinh tinh TONG, HIEU, TICH, THUONG 2 so*/ 
#include 
#include 
#include 
/* Chuong trinh chinh */ 
int main() 
{ /* 1. Khai bao bien va chuan bi*/ 
 int a,b; 
 float tong, hieu,tich, thuong; 
 159 
 system("cls"); 
 /* 2. Huong dan nhap va Nhap du lieu vao*/ 
 printf("Nhap vao A va B:"); 
 scanf("%d %d",&a,&b); 
 /* 3. Tinh toan TONG, HIEU, TICH, THUONG*/ 
 tong=a+b; 
 hieu=a-b; 
 tich=a*b; 
 thuong=a/b; 
 /* 4. Trinh bay ket qua r*/ 
 printf("Tong %d + %d = %10.2f\n", a,b,tong); 
 printf("Hieu %d - %d = %10.2f\n", a,b,hieu); 
 printf("Tich %d * %d = %10.2f\n", a,b,tich); 
 printf("Thuong %d / %d = %10.2f\n", a,b,thuong); 
 printf("Nhan phim bat ky de ket thuc!"); 
 /* 5. Doi nhan phim bat ky de ket thuc*/ 
 getch(); 
 return 0; 
} 
4.4.1 
#include 
#include 
int main() 
{ 
 int b[20], N; 
 int i, ln; 
 printf("So phan tu thuc te cua mang N= "); 
 scanf("%d",&N); 
 for(i=0; i< N; i++) 
 { 
 printf("Phan tu thu %d: ",i);scanf("%d",&b[i]); 
 } 
 ln = b[0]; 
 160 
 for(i=1; i< N; i++) 
 { 
 if (b[i]>ln) 
 { 
 ln=b[i]; 
 } 
 } 
 printf("Gia tri lon nhat la: %d", ln); 
 getch(); 
 return 0; 
} 
4.4.2 
#include 
#include 
#define N 2 
#define M 3 
int main() 
{ 
 int i, j,k; 
 int a[N][M], b[M][N], c[N][N]; 
 //nhap du lieu cho mang a 
 printf("Nhap ma tran A[%d][%d]:\n",N,M); 
 for(i=0;i<N;i++) 
 { 
 for(j=0;j<M;j++) 
 { 
 printf("a[%d][%d]:",i,j); 
 scanf("%d",&a[i][j]); 
 } 
 } 
 //nhap du lieu cho mang b 
 printf("Nhap ma tran b[%d][%d]:\n",M,N); 
 for(i=0;i<M;i++) 
 161 
 { 
 for(j=0;j<N;j++) 
 { 
 printf("b[%d][%d]:",i,j); 
 scanf("%d",&b[i][j]); 
 } 
 } 
 //Nhan hai ma tran 
 for(i=0;i<N;i++) 
 { 
 for(j=0;j<N;j++) 
 { 
 c[i][j]=0; 
 for(k=0;k<M;k++) 
 { 
 c[i][j]+=a[i][k]*b[k][j]; 
 } 
 } 
 } 
 //ghi ra man hinh 
 printf("Ma tran tich\n"); 
 for(i=0;i<N;i++) 
 { 
 for(j=0;j<N;j++) 
 { 
 printf("%5d",c[i][j]); 
 } 
 printf("\n"); 
 } 
 getch(); 
 return 0; 
} 
5.3.1 
 162 
#include 
#include 
#include 
double KC(int x1, int y1, int x2, int y2); 
double DT(double a, double b, double c); 
int main() 
{ 
int xa,ya, xb,yb, xc,yc, xm,ym; 
double ab, bc, ac, am, bm, cm; 
double abc, amb, bmc, amc; 
printf("Nhap toa do diem A(x,y):"); 
scanf("%d%d", &xa, &ya); 
printf("Nhap toa do diem B(x,y):"); 
scanf("%d%d", &xb, &yb); 
printf("Nhap toa do diem C(x,y):"); 
scanf("%d%d", &xc, &yc); 
printf("Nhap toa do diem M(x,y):"); 
scanf("%d%d", &xm, &ym); 
ab=KC(xa,ya,xb,yb); 
bc=KC(xb,yb,xc,yc); 
ac=KC(xa,ya,xc,yc); 
am=KC(xa,ya,xm,ym); 
bm=KC(xb,yb,xm,ym); 
cm=KC(xc,yc,xm,ym); 
abc=DT(ab, bc, ac); 
amb=DT(am, bm, ab); 
bmc=DT(bm, cm, bc); 
amc=DT(am, cm, ac); 
if ((amb==0)||(bmc==0)||(amc==0)) 
{ 
printf("M nam tren canh cua ABC"); 
} 
else 
 163 
{ 
if ((amb+bmc+amc)==abc) 
{ 
printf("M nam trong tam giac ABC"); 
} 
else 
{ 
printf("M nam ngoai tam giac ABC"); 
} 
} 
getch(); 
return 0; 
} 
double KC(int x1, int y1, int x2, int y2) 
{ 
double kq; 
kq=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); 
return kq; 
} 
double DT(double a, double b, double c) 
{ 
double kq, p; 
p=(double)(a+b+c)/2; 
kq=sqrt(p*(p-a)*(p-b)*(p-c)); 
return kq; 
} 
5.3.2 
#include 
#include 
#include 
#include 
int wordCount(char *s); 
int main() 
 164 
{ 
char s[100]; 
printf("Nhap vao mot xau:"); 
gets(s); 
printf("So tu: %d", wordCount(s)); 
getch(); 
return 0; 
} 
int wordCount(char *s) 
{ 
int kq,i; 
kq=0; 
i=0; 
while (s[i]!='\0') 
{ 
if (s[i]==32) 
{ 
kq=kq+1; 
} 
i++; 
} 
kq++; 
return kq; 
} 

File đính kèm:

  • pdfgiao_trinh_lap_trinh_ung_dung_phan_2.pdf