Giáo trình Ngôn ngữ lập trình C/C++ - Phạm Hồng Thái

2. Giao diện và cửa sổ soạn thảo

a. Mô tả chung

Khi gọi chạy C++ trên màn hình sẽ xuất hiện một menu xổ xuống và một cửa sổ

soạn thảo. Trên menu gồm có các nhóm chức năng: File, Edit, Search, Run, Compile,

Debug, Project, Options, Window, Help. Để kích hoạt các nhóm chức năng, có thể

ấn Alt+chữ cái biểu thị cho menu của chức năng đó (là chữ cái có gạch dưới). Ví dụ để

mở nhóm chức năng File ấn Alt+F, sau đó dịch chuyển hộp sáng đến mục cần chọn rồi

ấn Enter. Để thuận tiện cho NSD, một số các chức năng hay dùng còn được gắn với

một tổ hợp các phím cho phép người dùng có thể chọn nhanh chức năng này mà không

cần thông qua việc mở menu như đã mô tả ở trên. Một số tổ hợp phím cụ thể đó sẽ

được trình bày vào cuối phần này. Các bộ chương trình dịch hỗ trợ người lập trình một

môi trường tích hợp tức ngoài chức năng soạn thảo, nó còn cung cấp nhiều chức năng,

tiện ích khác giúp người lập trình vừa có thể soạn thảo văn bản chương trình vừa gọi

chạy chương trình vừa gỡ lỗi

Các chức năng liên quan đến soạn thảo phần lớn giống với các bộ soạn thảo khác

(như WinWord) do vậy chúng tôi chỉ trình bày tóm tắt mà không trình bày chi tiết ở

đây

pdf308 trang | Chia sẻ: hatranv1 | Lượt xem: 578 | Lượt tải: 0download
Bạn đang xem trước 20 trang mẫu tài liệu Giáo trình Ngôn ngữ lập trình C/C++ - Phạm Hồng Thái, để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên
à n = 2. 
Tương tự gt(2) = gt(1)*2 và gt(1) = gt(0)*1. Khi thực hiện gt(0) ta có đối n = 0 nên 
hàm trả lại giá trị 1, từ đó gt(1) = 1*1 = 1 và suy ngược trở lại ta có gt(2) = gt(1)*2 = 
1*2 = 2, gt(3) = gt(2)*3 = 2*3 = 6, chương trình in ra kết quả 6. 
Từ ví dụ trên ta thấy hàm đệ qui có đặc điểm: 
− Chương trình viết rất gọn, 
− Việc thực hiện gọi đi gọi lại hàm rất nhiều lần phụ thuộc vào độ lớn của đầu 
vào. Chẳng hạn trong ví dụ trên hàm được gọi n lần, mỗi lần như vậy chương 
trình sẽ mất thời gian để lưu giữ các thông tin của hàm gọi trước khi chuyển 
điều khiển đến thực hiện hàm được gọi. Mặt khác các thông tin này được lưu 
trữ nhiều lần trong ngăn xếp sẽ dẫn đến tràn ngăn xếp nếu n lớn. 
Tuy nhiên, đệ qui là cách viết rất gọn, dễ viết và đọc chương trình, mặt khác có 
nhiều bài toán hầu như tìm một thuật toán lặp cho nó là rất khó trong khi viết theo thuật 
toán đệ qui thì lại rất dễ dàng. 
2. Lớp các bài toán giải được bằng đệ qui 
Phương pháp đệ qui thường được dùng để giải các bài toán có đặc điểm: 
− Giải quyết được dễ dàng trong các trường hợp riêng gọi là trường hợp suy 
biến hay cơ sở, trong trường hợp này hàm được tính bình thường mà không 
cần gọi lại chính nó, 
− Đối với trường hợp tổng quát, bài toán có thể giải được bằng bài toán cùng 
dạng nhưng với tham đối khác có kích thước nhỏ hơn tham đối ban đầu. Và 
sau một số bước hữu hạn biến đổi cùng dạng, bài toán đưa được về trường hợp 
 124 
Chương 4. Hàm và chương trình 
suy biến. 
Như vậy trong trường hợp tính n! nếu n = 0 hàm cho ngay giá trị 1 mà không cần 
phải gọi lại chính nó, đây chính là trường hợp suy biến. Trường hợp n > 0 hàm sẽ gọi 
lại chính nó nhưng với n giảm 1 đơn vị. Việc gọi này được lặp lại cho đến khi n = 0. 
Một lớp rất rộng của bài toán dạng này là các bài toán có thể định nghĩa được 
dưới dạng đệ qui như các bài toán lặp với số bước hữu hạn biết trước, các bài toán 
UCLN, tháp Hà Nội, ... 
3. Cấu trúc chung của hàm đệ qui 
Dạng thức chung của một chương trình đệ qui thường như sau: 
if (trường hợp suy biến) 
{ 
 trình bày cách giải // giả định đã có cách giải 
} 
else // trường hợp tổng quát 
{ 
 gọi lại hàm với tham đối "bé" hơn 
} 
4. Các ví dụ 
Ví dụ 1 : 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); 
} 
 125
Chương 4. Hàm và chương trình 
Ví dụ 2 : Tính số hạng thứ n của dãy Fibonaci là dãy f(n) được định nghĩa: 
− f(0) = f(1) = 1 
− f(n) = f(n-1) + f(n-2) với ∀n ≥ 2. 
long Fib(int n) 
{ 
 long kq; 
 if (n==0 || n==1) kq = 1; else kq = Fib(n-1) + Fib(n-2); 
 return kq; 
} 
Ví dụ 3 : Chuyển tháp là bài toán cổ nổi tiếng, nội dung như sau: Cho một tháp n tầng, 
đang xếp tại vị trí 1. Yêu cầu bài toán là hãy chuyển toàn bộ tháp sang vị trí 2 (cho 
phép sử dụng vị trí trung gian 3) theo các điều kiện sau đây 
− mỗi lần chỉ được chuyển một tầng trên cùng của tháp, 
− tại bất kỳ thời điểm tại cả 3 vị trí các tầng tháp lớn hơn phải nằm dưới các 
tầng tháp nhỏ hơn. 
Bài toán chuyển tháp được minh hoạ bởi hình vẽ dưới đây. 
 trước khi chuyển sau khi chuyển 
 1 2 3 1 2 3 
Bài toán có thể được đặt ra tổng quát hơn như sau: chuyển tháp từ vị trí di đến vị 
trí den, trong đó di, den là các tham số có thể lấy giá trị là 1, 2, 3 thể hiện cho 3 vị trí. 
Đối với 2 vị trí di và den, dễ thấy vị trí trung gian (vị trí còn lại) sẽ là vị trí 6-di-den (vì 
di+den+tg = 1+2+3 = 6). Từ đó để chuyển tháp từ vị trí di đến vị trí den, ta có thể xây 
dựng một cách chuyển đệ qui như sau: 
• chuyển 1 tầng từ di sang tg, 
• chuyển n-1 tầng còn lại từ di sang den, 
• chuyển trả tầng tại vị trí tg về lại vị trí den 
 126 
Chương 4. Hàm và chương trình 
hiển nhiên nếu số tầng là 1 thì ta chỉ phải thực hiện một phép chuyển từ di sang den. 
Mỗi lần chuyển 1 tầng từ vị trí i đến j ta kí hiệu i → j. Chương trình sẽ nhập vào 
input là số tầng và in ra các bước chuyển theo kí hiệu trên. 
Từ đó ta có thể xây dựng hàm đệ qui sau đây ; 
void chuyen(int n, int di, int den) // n: số tầng, di, den: vị trí đi, đến 
{ 
 if (n==1) cout << di << " → " << den << endl; 
 else { 
 cout << di << "→" << 6-di-den << endl; // 1 tầng từ di qua trung gian 
 chuyen(n-1, di, den) ; // n-1 tầng từ di qua den 
 cout << 6-di-den << "→" den << endl; // 1 tầng từ tg về lại den 
 } 
} 
main() 
{ 
 int sotang ; 
 cout > sotang; 
 chuyen(sotang, 1, 2); 
} 
Ví dụ nếu số tầng bằng 3 thì chương trình in ra kết quả là dãy các phép chuyển 
sau đây: 
1 → 2 , 1 → 3 , 2 → 3 , 1 → 2 , 3 → 1 , 3 → 2 , 1 → 2. 
có thể tính được số lần chuyển là 2n - 1 với n là số tầng. 
IV. TỔ CHỨC CHƯƠNG TRÌNH 
1. Các loại biến và phạm vi 
a. Biến cục bộ 
Là các biến được khai báo trong thân của hàm và chỉ có tác dụng trong hàm này, 
kể cả các biến khai báo trong hàm main() cũng chỉ có tác dụng riêng trong hàm main(). 
Từ đó, tên biến trong các hàm là được phép trùng nhau. Các biến của hàm nào sẽ chỉ 
 127
Chương 4. Hàm và chương trình 
tồn tại trong thời gian hàm đó hoạt động. Khi bắt đầu hoạt động các biến này được tự 
động sinh ra và đến khi hàm kết thúc các biến này sẽ mất đi. Tóm lại, một hàm được 
xem như một đơn vị độc lập, khép kín. 
Tham đối của các hàm cũng được xem như biến cục bộ. 
Ví dụ 1 : Dưới đây ta nhắc lại một chương trình nhỏ gồm 3 hàm: luỹ thừa, xoá màn 
hình và main(). Mục đích để minh hoạ biến cục bộ. 
float luythua(float x, int n) // hàm trả giá trị xn
{ 
 int i ; 
 float kq = 1; 
 for (i=1; i<=n; i++) kq *= x; 
 return kq; 
} 
void xmh(int n) // xoá màn hình n lần 
{ 
 int i; 
 for (i=1; i<=n; i++) clrscr(); 
} 
main() 
{ 
 float x; int n; 
 cout > x >> n; 
 xmh(5); // xoá màn hình 5 lần 
 cout << luythua(x, n); // in xn
} 
Qua ví dụ trên ta thấy các biến i, đối n được khai báo trong hai hàm: luythua() và 
xmh(). kq được khai báo trong luythua và main(), ngoài ra các biến x và n trùng với đối 
của hàm luythua(). Tuy nhiên, tất cả khai báo trên đều hợp lệ và đều được xem như 
khác nhau. Có thể giải thích như sau: 
− Tất cả các biến trên đều cục bộ trong hàm nó được khai báo. 
 128 
Chương 4. Hàm và chương trình 
− x và n trong main() có thời gian hoạt động dài nhất: trong suốt quá trình chạy 
chương trình. Chúng chỉ mất đi khi chương trình chấm dứt. Đối x và n trong 
luythua() chỉ tạm thời được tạo ra khi hàm luythua() được gọi đến và độc lập 
với x, n trong main(), nói cách khác tại thời điểm đó trong bộ nhớ có hai biến 
x và hai biến n. Khi hàm luythua chay xong biến x và n của nó tự động biến 
mất. 
− Tương tự 2 đối n, 2 biến i trong luythua() và xoá màn hình cũng độc lập với 
nhau, chúng chỉ được tạo và tồn tại trong thời gian hàm của chúng được gọi và 
hoạt động. 
b. Biến ngoài 
Là các biến được khai báo bên ngoài của tất cả các hàm. Vị trí khai báo của 
chúng có thể từ đầu văn bản chương trình hoặc tại một một vị trí bất kỳ nào đó giữa 
văn bản chương trình. Thời gian tồn tại của chúng là từ lúc chương trình bắt đầu chạy 
đến khi kết thúc chương trình giống như các biến trong hàm main(). Tuy nhiên về 
phạm vi tác dụng của chúng là bắt đầu từ điểm khai báo chúng đến hết chương trình, 
tức tất cả các hàm khai báo sau này đều có thể sử dụng và thay đổi giá trị của chúng. 
Như vậy các biến ngoài được khai báo từ đầu chương trình sẽ có tác dụng lên toàn bộ 
chương trình. Tất cả các hàm đều sử dụng được các biến này nếu trong hàm đó không 
có biến khai báo trùng tên. Một hàm nếu có biến trùng tên với biến ngoài thì biến ngoài 
bị che đối với hàm này. Có nghĩa nếu i được khai báo như một biến ngoài và ngoài ra 
trong một hàm nào đó cũng có biến i thì như vậy có 2 biến i độc lập với nhau và khi 
hàm truy nhập đến i thì có nghĩa là i của hàm chứ không phải i của biến ngoài. 
Dưới đây là ví dụ minh hoạ cho các giải thích trên. 
Ví dụ 2 : Chúng ta xét lại các hàm luythua() và xmh(). Chú ý rằng trong cả hai hàm này 
đều có biến i, vì vậy chúng ta có thể khai báo i như một biến ngoài (để dùng chung cho 
luythua() và xmh()), ngoài ra x, n cũng có thể được khai báo như biến ngoài. Cụ thể: 
#include 
#include 
float x; int n; int i ; 
float luythua(float x, int n) 
{ 
 float kq = 1; 
 for (i=1; i<=n; i++) kq *= x; 
} 
 129
Chương 4. Hàm và chương trình 
void xmh() 
{ 
 for (i=1; i<=n; i++) clrscr(); 
} 
main() 
{ 
 cout > x >> n; 
 xmh(5); // xoá màn hình 5 lần 
 cout << luythua(x, n); // in xn
} 
Trong ví dụ này ta thấy các biến x, n, i đều là các biến ngoài. Khi ta muốn sử 
dụng biến ngoài ví dụ i, thì biến i sẽ không được khai báo trong hàm sử dụng nó. 
Chẳng hạn, luythua() và xmh() đều sử dụng i cho vòng lặp for của mình và nó không 
được khai báo lại trong 2 hàm này. Các đối x và n trong luythua() là độc lập với biến 
ngoài x và n. Trong luythua() khi sử dụng đến x và n (ví dụ câu lệnh kq *= x) thì đây là 
x của hàm chứ không phải biến ngoài, trong khi trong main() không có khai báo về x 
và n nên ví dụ câu lệnh cout << luythua(x, n); là sử dụng x, n của biến ngoài. 
Nói chung trong 2 ví dụ trên chương trình đều chạy tốt và như nhau. Tuy nhiên, 
việc khai báo khác nhau như vậy có ảnh hưởng hoặc gây nhầm lẫn gì cho người lập 
trình ? Liệu chúng ta có nên tự đặt ra một nguyên tắc nào đó trong khai báo biến ngoài 
và biến cục bộ để tránh những nhầm lẫn có thể xảy ra. Chúng ta hãy xét tiếp cũng ví dụ 
trên nhưng thay đổi một số khai báo và tính 23 (có thể bỏ bớt biến n) như sau: 
#include 
#include 
float x; int i ; // không dùng n 
float luythua(float x, int n) 
{ 
 float kq = 1; 
 for (i=1; i<=n; i++) kq *= x; 
} 
void xmh() 
{ 
 130 
Chương 4. Hàm và chương trình 
 for (i=1; i<=n; i++) clrscr(); 
} 
main() 
{ 
 x = 2; 
 i = 3; 
 xmh(5); // xoá màn hình 5 lần 
 cout << luythua(x, i); // in xi, kết quả x = 23 = 8 ? 
} 
Nhìn vào hàm main() ta thấy giá trị 23 được tính bằng cách đặt x = 2, i = 3 và gọi 
hàm luythua(x,i). Kết quả ta mong muốn sẽ là giá trị 8 hiện ra màn hình, tuy nhiên 
không đúng như vậy. Trước khi in kết quả này ra màn hình hàm xmh() đã được gọi đến 
để xoá màn hình. Hàm này sử dụng một biến ngoài i để làm biến đếm cho mình trong 
vòng lặp for và sau khi ra khỏi for (cũng là kết thúc xmh()) i nhận giá trị 6. Biến i 
ngoài này lại được sử dụng trong lời gọi luythua(x,i) của hàm main(), tức tại thời điểm 
này x = 2 và i = 6, kết quả in ra màn hình sẽ là 26 = 64 thay vì 8 như mong muốn. 
Tóm lại "điểm yếu" dẫn đến sai sót của chương trình trên là ở chỗ lập trình viên 
đã "tranh thủ" sử dụng biến i cho 2 hàm xmh() và main() (bằng cách khai báo nó như 
biến ngoài) nhưng lại với mục đích khác nhau. Do vậy sau khi chạy xong hàm xmh() i 
bị thay đổi khác với giá trị i được khởi tạo lúc ban đầu. Để khắc phục lỗi trong chương 
trình trên ta cần khai báo lại biến i: hoặc trong main() khai báo thêm i (nó sẽ che biến i 
ngoài), hoặc trong cả hai xmh() và main() đều có biến i (cục bộ trong từng hàm). 
Từ đó, ta nên đề ra một vài nguyên tắc lập trình sao cho nó có thể tránh được 
những lỗi không đáng có như vậy: 
• nếu một biến chỉ sử dụng vì mục đích riêng của một hàm thì nên khai báo 
biến đó như biến cục bộ trong hàm. Ví dụ các biến đếm của vòng lặp, thông 
thường chúng chỉ được sử dụng thậm chí chỉ riêng trong vòng lặp chứ cũng 
chưa phải cho toàn bộ cả hàm, vì vậy không nên khai báo chúng như biến 
ngoài. Những biến cục bộ này sau khi hàm kết thúc chúng cũng sẽ kết thúc, 
không gây ảnh hưởng đến bất kỳ hàm nào khác. Một đặc điểm có lợi nữa cho 
khai báo cục bộ là chúng tạo cho hàm tính cách hoàn chỉnh, độc lập với mọi 
hàm khác, chương trình khác. Ví dụ hàm xmh() có thể mang qua chạy ở 
chương trình khác mà không phải sửa chữa gì nếu i đã được khai báo bên 
trong hàm. Trong khi ở ví dụ này hàm xmh() vẫn hoạt động được nhưng trong 
chương trình khác nếu không có i như một biến ngoài (để xmh() sử dụng) thì 
hàm sẽ gây lỗi. 
 131
Chương 4. Hàm và chương trình 
• với các biến mang tính chất sử dụng chung rõ nét (đặc biệt với những biến 
kích thước lớn) mà nhiều hàm cùng sử dụng chúng với mục đích giống nhau 
thì nên khai báo chúng như biến ngoài. Điều này tiết kiệm được thời gian cho 
người lập trình vì không phải khai báo chúng nhiều lần trong nhiều hàm, tiết 
kiệm bộ nhớ vì không phải tạo chúng tạm thời mỗi khi chạy các hàm, tiết 
kiệm được thời gian chạy chương trình vì không phải tổ chức bộ nhớ để lưu 
trữ và giải phóng chúng. Ví dụ trong chương trình quản lý sinh viên (chương 
6), biến sinh viên được dùng chung và thống nhất trong hầu hết các hàm (xem, 
xoá, sửa, bổ sung, thống kê ) nên có thể khai báo chúng như biến ngoài, 
điều này cũng tăng tính thống nhất của chương trình (mọi biến sinh viên là 
như nhau cho mọi hàm con của chương trình). 
Tóm lại, nguyên tắc tổng quát nhất là cố gắng tạo hàm một cách độc lập, khép 
kín, không chịu ảnh hưởng của các hàm khác và không gây ảnh hưởng đến hoạt động 
của các hàm khác đến mức có thể. 
2. Biến với mục đích đặc biệt 
a. Biến hằng và từ khoá const 
Để sử dụng hằng có thể khai báo thêm từ khoá const trước khai báo biến. Phạm vi 
và miền tác dụng cũng như biến, có nghĩa biến hằng cũng có thể ở dạng cục bộ hoặc 
toàn thể. Biến hằng luôn luôn được khởi tạo trước. 
Có thể khai báo từ khoá const trước các tham đối hình thức để không cho phép 
thay đổi giá trị của các biến ngoài (đặc biệt đối với với mảng và xâu kí tự, vì bản thân 
các biến này được xem như con trỏ do đó hàm có thể thay đổi được giá trị của các biến 
ngoài truyền cho hàm này). 
Ví dụ sau thể hiện hằng cũng có thể được khai báo ở các phạm vi khác nhau. 
const int MAX = 30; // toàn thể 
void vidu(const int *p) // cục bộ 
{ 
const MAX = 10; // cục bộ 
} 
void main() 
{ 
const MAX = 5; // cục bộ 
 132 
Chương 4. Hàm và chương trình 
} 
Trong Turbo C, BorlandC và các chương trình dịch khác có nhiều hằng số khai 
báo sẵn trong tệp values.h như MAXINT, M_PI hoặc các hằng đồ hoạ trong graphics.h 
như WHITE, RED,  
b. Biến tĩnh và từ khoá static 
Được khai báo bằng từ khoá static. Là biến cục bộ nhưng vẫn giữ giá trị sau khi 
ra khỏi hàm. Phạm vi tác dụng như biến cục bộ, nghĩa là nó chỉ được sử dụng trong 
hàm khai báo nó. Tuy nhiên thời gian tác dụng được xem như biến toàn thể, tức sau khi 
hàm thực hiện xong biến vẫn còn tồn tại và vẫn lưu lại giá trị sau khi ra khỏi hàm. Giá 
trị này này được tiếp tục sử dụng khi hàm được gọi lại, tức biến static chỉ được khởi 
đầu một lần trong lần chạy hàm đầu tiên. Nếu không khởi tạo, C++ tự động gán giá trị 
0 (ngầm định = 0). Ví dụ: 
int i = 1; 
void bp() 
{ 
static int lanthu = 0; 
lanthu++; 
i = 2 * i; 
cout << "Hàm chạy lần thứ " << lanthu << ", i = " << i ; 
} 
main() 
{ 
ham(); // Hàm chạy lần thứ 1, i = 1 
ham(); // Hàm chạy lần thứ 2, i = 2 
ham(); // Hàm chạy lần thứ 3, i = 4 
} 
c. Biến thanh ghi và từ khoá register 
Để tăng tốc độ tính toán C++ cho phép một số biến được đặt trực tiếp vào thanh 
ghi thay vì ở bộ nhớ. Khai báo bằng từ khoá register đứng trước khai báo biến. Tuy 
 133
Chương 4. Hàm và chương trình 
nhiên khai báo này chỉ có tác dụng đối với các biến có kích thước nhỏ như biến char, 
int. 
Ví dụ: register char c; register int dem; 
d. Biến ngoài và từ khoá extern 
Như đã biết một chương trình có thể được đặt trên nhiều file văn bản khác nhau. 
Một biến không thể được khai báo nhiều lần với cùng phạm vi hoạt động. Do vậy nếu 
một hàm sử dụng biến được khai báo trong file văn bản khác thì biến này phải được 
khai báo với từ khoá extern. Từ khoá này cho phép chương trình dịch tìm và liên kết 
biến này từ bên ngoài file đang chứa biến. Chúng ta hãy xét ví dụ gây lỗi sau đây và 
tìm phương án khắc phục chúng. 
void in(); 
void main() 
{ 
int i = 1; 
in(); 
} 
void in() 
{ 
cout << i ; 
} 
• Lỗi (cú pháp) vì i là biến cục bộ trong main(), trong in() không nhận biết i, 
nếu trong hoặc trước in() khai báo thêm i thì lỗi ngữ nghĩa (tức chương trình 
in giá trị i khác không theo ý muốn của lập trình viên). 
• Giả thiết khai báo lại như sau: 
void in(); 
void main() { ... } // Bỏ khai báo i trong main() 
int i; // Đưa khai báo i ra trước in() và sau main() 
void in() { ... } 
cách khai báo này cũng gây lỗi vì main() không nhận biết i. Cuối cùng để main() 
có thể nhận biết i thì i phải được khai báo dưới dạng biến extern. Thông thường trong 
trường hợp này cách khắc phục hay nhất là khai báo trước main() để bỏ các extern 
(không cần thiết). 
 134 
Chương 4. Hàm và chương trình 
Giả thiết 2 chương trình trên nằm trong 2 tệp khác nhau. Để liên kết (link) biến i 
giữa 2 chương trình cần định nghĩa tổng thể i trong một và khai báo extern trong 
chương trình kia. 
/* program1.cpp*/ 
void in(); 
int i; 
void main() 
{ 
i = 1; 
in(); 
} 
/* program2.cpp */ 
void in() 
{ 
extern i; 
cout << i ; 
} 
Hàm in() nằm trong tệp văn bản program2.cpp, được dùng để in giá trị của biến i 
khai báo trong program1.cpp, tạm gọi là tệp gốc (hai tệp này khi dịch sẽ được liên kết 
với nhau). Từ đó trong tệp gốc, i phải được khai báo là biến ngoài, và bất kỳ hàm ở tệp 
khác muốn sử dụng biến i này đều phải có câu lệnh khai báo extern int i (nếu không có 
từ khoá extern thì biến i lại được xem là biến cục bộ, khác với biến i trong tệp gốc). 
Để liên kết các tệp nguồn có thể tạo một dự án (project) thông qua menu 
PROJECT (Alt-P). Các phím nóng cho phép mở dự án, thêm bớt tệp vào danh sách tệp 
của dự án  được hướng dẫn ở dòng cuối của cửa sổ dự án. 
3. Các chỉ thị tiền xử lý 
Như đã biết trước khi chạy chương trình (bắt đầu từ văn bản chương trình tức 
chương trình nguồn) C++ sẽ dịch chương trình ra tệp mã máy còn gọi là chương trình 
đích. Thao tác dịch chương trình nói chung gồm có 2 phần: xử lý sơ bộ chương trình và 
dịch. Phần xử lý sơ bộ được gọi là tiền xử lý, trong đó có các công việc liên quan đến 
các chỉ thị được đặt ở đầu tệp chương trình nguồn như #include, #define  
a. Chỉ thị bao hàm tệp #include 
 135
Chương 4. Hàm và chương trình 
Cho phép ghép nội dung các tệp đã có khác vào chương trình trước khi dịch. Các 
tệp cần ghép thêm vào chương trình thường là các tệp chứa khai báo nguyên mẫu của 
các hằng, biến, hàm  có sẵn trong C hoặc các hàm do lập trình viên tự viết. Có hai 
dạng viết chỉ thị này. 
1: #include 
2: #include “đường dẫn\tệp” 
Dạng khai báo 1 cho phép C++ ngầm định tìm tệp tại thư mục định sẵn (khai báo 
thông qua menu Options\Directories) thường là thư mục TC\INCLUDE và tệp là các 
tệp nguyên mẫu của thư viện C++. 
Dạng khai báo 2 cho phép tìm tệp theo đường dẫn, nếu không có đường dẫn sẽ 
tìm trong thư mục hiện tại. Tệp thường là các tệp (thư viện) được tạo bởi lập trình viên 
và được đặt trong cùng thư mục chứa chương trình. Cú pháp này cho phép lập trình 
viên chia một chương trình thành nhiều môđun đặt trên một số tệp khác nhau để dễ 
quản lý. Nó đặc biệt hữu ích khi lập trình viên muốn tạo các thư viện riêng cho mình. 
b. Chỉ thị macro #define 
#define tên_macro xaukitu 
Trước khi dịch bộ tiền xử lý sẽ tìm trong chương trình và thay thế bất kỳ vị trí 
xuất hiện nào của tên_macro bởi xâu kí tự. Ta thường sử dụng macro để định nghĩa các 
hằng hoặc thay cụm từ này bằng cụm từ khác dễ nhớ hơn, ví dụ: 
#define then // thay then bằng dấu cách 
#define begin { // thay begin bằng dấu { 
#define end } // thay end bằng dấu } 
#define MAX 100 // thay MAX bằng 100 
#define TRUE 1 // thay TRUE bằng 1 
từ đó trong chương trình ta có thể viết những đoạn lệnh như: 
if (i < MAX) then 
begin 
Ok = TRUE; 
cout << i ; 
end 
tr

File đính kèm:

  • pdfgiao_trinh_ngon_ngu_lap_trinh_cc_pham_hong_thai.pdf