Mac dinh mot ham phai chay trong chuong tirnh c++
I. Phân chia chương trình thành từng hàm1. Kĩ thuật lập trình hướng cấu trúcCùng xem xét một ví dụ sau: Cho ba số nguyên dương a,b,c,a, b, c, đều không nhỏ hơn 2,2, hãy kiếm tra xem những số nào là số nguyên tố và đưa ra thông báo số đó là số nguyên tố?. Show
Ta biết rằng một số nguyên tố sẽ không chia hết cho số nào ngoài 11 và chính nó. Áp dụng những gì đã học từ các bài trước, ta có thể xây dựng một chương trình như sau:
Biên dịch và chạy chương trình trên với a=2,b=5,c=9a=2, b=5, c = 9 sẽ cho ra kết quả:
Vấn đề chúng ta nhận thấy ở đây là, quá trình kiểm tra số nguyên tố đối với từng số là quá trình tương tự nhau, chỉ thay đổi giá trị số thôi, nhưng chúng ta phải viết lại tới ba lần khiến cho chương trình rất dài. Điều này sẽ còn tệ hơn nữa nếu như cần kiểm tra 4,5,. ..4, 5,... thậm chí là 10001000 số! Trên thực tế, lập trình chính là xây dựng một quá trình giải bài toán gồm nhiều bước khác nhau, mỗi bước sẽ giải quyết một công việc cụ thể. Rất nhiều trường hợp ta sẽ gặp phải các công việc tương tự nhau, để tránh phải viết đi viết lại một đoạn code gây lãng phí thời gian, ta sẽ chia chương trình thành các hàm con, mỗi hàm phụ trách một công việc nhất định và tất cả sẽ được gọi ra trong một hàm chính. Cách lập trình như vậy gọi là lập trình hướng cấu trúc hay lập trình module hóa. Ưu điểm của phương pháp này là:
Cách lập trình này rất phù hợp trong lập trình thi đấu, vì mỗi giải thuật thường chỉ áp dụng cho những bài toán nhất định. Tất nhiên, nó cũng có những nhược điểm, nhưng chúng ta sẽ không bàn đến trong bài học này. 2. Định nghĩa về hàm. Hàm tự định nghĩa và hàm dựng sẵnC++ là
một ngôn ngữ lập trình có khả năng hướng cấu trúc, bao gồm một hàm Có hai loại hàm trong C++ là hàm tự định nghĩa và hàm dựng sẵn được cung cấp bởi các thư viện của C++. Sử dụng linh hoạt các hàm sẽ hỗ trợ rất tốt cho lập trình viên trong quá trình xây dựng chương trình. II. Các hàm toán học dựng sẵn trong C++Trong thư viện chuẩn của C++ cung cấp khá nhiều hàm dựng sẵn giúp ích cho người lập trình, và một trong số đó là các hàm toán học. Để sử dụng các hàm toán học trong C++, đầu tiên ta cần khai báo thư viện và không gian tên chứa chúng:
Bảng dưới đây là một số hàm thường sử dụng trong quá trình làm việc với C++: III. Các bước định nghĩa và sử dụng một hàm1. Khai báo hàmGiống như các biến và hằng, một hàm phải được khai báo và định nghĩa trước khi sử dụng. Một khai báo hàm có thể đặt ở bất kỳ đâu trong chương trình. Cú pháp khai báo một hàm như sau:
Trong đó ta có:
Ví dụ, dưới đây là một vài khai báo hàm hợp lệ:
2. Định nghĩa hàmPhần định nghĩa hàm là phần quan trọng nhất của một hàm, nó quyết định hàm đó sẽ làm công việc gì và trả ra kết quả là gì. Cú pháp định nghĩa hàm như sau:
Trong đó, phần {Thân_hàm} chứa các câu lệnh của hàm. Đối với hàm có {Kiểu_trả_về} là một kiểu dữ
liệu nào đó thì bắt buộc phải có ít nhất một dòng lệnh Ví dụ: Hàm dưới đây trả về giá trị lớn nhất giữa hai số nguyên aa và bb:
3. Lời gọi hàmMột hàm sau khi được định nghĩa, nếu muốn hoạt động thì phải được gọi ra trong hàm Việc hàm được gọi ra như thế nào cũng tùy thuộc vào {Kiểu_trả_về} của hàm. Nếu như {Kiểu_trả_về} là một kiểu dữ liệu - nghĩa là hàm có giá trị trả về - thì lời gọi hàm đó được phép sử dụng kết hợp trong các câu lệnh gán, biểu thức tính toán hoặc logic. Ngược lại nếu {Kiểu_trả_về} là Ví dụ 1: Hàm
Kết quả chạy chương trình với x1=1,y1=2,x2=5,y2=4,x3=10,y3=10x1 = 1, y1 = 2, x2 = 5, y2 = 4, x3 = 10, y3 = 10 là:
Ta thấy ở ví dụ trên, cần tìm giá trị lớn nhất giữa ba cặp số (x,y)(x, y) khác nhau. Nếu không sử dụng hàm, ta sẽ phải viết lại quy trình tìm giá trị lớn nhất đủ 33 lần, nhưng khi dùng hàm thì việc kiểm tra chỉ cần viết một lần trong hàm và gọi hàm đó ra sử dụng ba lần với tham số truyền vào lần lượt là các cặp số cần kiểm tra thôi. Đây chính là lợi thế của việc viết chương trình thành các hàm. Ví dụ 2: Dùng hàm
Kết quả chạy chương trình:
IV. Tham số của hàmTham số thực chất là các biến đại diện cho dữ liệu truyền vào hàm khi có một lời gọi hàm nào đó. Khi dữ liệu truyền vào hàm, nó sẽ được lưu vào tham số và hàm sẽ tính toán bằng dữ liệu trên tham số đó. Tham số được phân làm hai loại: Tham số thực sự và tham số hình thức. 1. Tham số thực sựChính là các biến, hằng ở bên ngoài truyền vào trong một hàm. Khi truyền các giá trị này vào hàm, các giá trị đó sẽ được sử dụng dưới tên của tham số hình thức. Lấy ví dụ:
Trong hàm 2. Tham số hình thứcLà danh sách tham số đứng phía sau khai báo của một hàm. Những tham số này sẽ đại diện cho dữ liệu truyền vào hàm, nhờ vào tham số mà chúng ta có thể tái sử dụng hàm với rất nhiều các bộ dữ liệu khác nhau. Có hai cách truyền tham số thực sự từ bên ngoài vào hàm: 2.1. Truyền tham trịVới cách truyền tham số này, hàm sẽ tạo một bản sao của dữ liệu được truyền vào, sau đó thực hiện các tính toán trong hàm với dữ liệu đó mà không làm thay đổi dữ liệu bên ngoài truyền vào. Ví dụ:
Chạy chương trình này sẽ thu được kết quả:
Ta thấy hai giá trị aa lúc đầu và lúc sau vẫn giữ nguyên. Nguyên do là vì, giá trị của biến
aa ở hàm Khi nào sử dụng truyền tham trị: Nên sử dụng cách truyền tham trị trong những trường hợp mà dữ liệu truyền vào chỉ dùng để tính toán trung gian cho những kết quả khác. 2.2. Truyền tham chiếuVới tham chiếu, biến truyền vào sẽ được truyền thẳng địa chỉ của nó vào trong hàm nhưng với một cái tên khác, và dữ liệu bị thay đổi trong hàm sẽ được cập nhật sang dữ liệu gốc đã truyền vào. Muốn truyền dữ liệu bằng tham chiếu, chỉ cần thêm toán tử
Chạy chương trình này sẽ thu được kết quả:
Giá trị aa lúc sau so với ban đầu đã thay đổi. Lí do là vì khi sử dụng tham chiếu để truyền giá trị aa vào thì chính địa chỉ của biến aa được truyền vào hàm, nhưng dưới cái tên là x,x, từ đó mọi thay đổi của tham số xx sẽ được cập nhật thẳng lên aa. Khi nào sử dụng truyền tham chiếu: Khi cần chuyển dữ liệu đã xử lý ra ngoài hàm để sử dụng trong các hàm khác. Trong trường hợp muốn sử dụng tham chiếu nhưng không muốn dữ liệu bị cập nhật thay đổi lên biến gốc, ta sử dụng cú pháp khai báo như sau:
Ví dụ:
V. Biến toàn cục và Biến cục bộTùy vào vị trí khai báo biến mà chúng ta có thể chia các biến trong C++ ra làm hai loại: Biến toàn cục (global variables) và Biến cục bộ (local variables). Sử dụng thành thạo hai loại biến này có ý nghĩa rất quan trọng trong lập trình nói chung và lập trình thi đấu nói riêng. 1. Biến toàn cục (global variables)Định nghĩa: Là các biến được khai báo ở ngoài hàm, có giá trị kể từ vị trí nó được khai báo cho tới hết chương trình. Mọi hàm kể từ vị trí khai báo đều có thể sử dụng biến toàn cục. Khi khai báo biến toàn cục, các biến sẽ nhận giá trị mặc định là 00 đối với kiểu số, và giá trị rỗng đối với kiểu chuỗi hoặc kí tự. Ví dụ:
Kết quả chạy chương trình:
Ta thấy hai biến xx và yy sẽ bị thay đổi ở cả hai hàm 2. Biến cục bộ (local variables)Định nghĩa: Là các biến được khai báo ở trong một hàm, chỉ có tác dụng cho tới hết khối lệnh mà nó thuộc vào và sẽ biến mất khi khối lệnh kết thúc. Khi khai báo các biến cục bộ, chúng sẽ nhận giá trị mặc định là những giá trị tùy ý sinh ra bởi chương trình. Do đó, chúng ta cần lưu ý luôn luôn khởi tạo giá trị ban đầu cho các biến cục bộ trước khi thực hiện tính toán liên quan tới biến đó (trừ khi ta sẽ nhập giá trị cho biến đó sau khi khai báo). Ví dụ:
Kết quả:
Ta thấy hai biến aa và bb ở hàm VI. Nạp chồng hàm và nạp chồng toán tử1. Nạp chồng hàmNgôn ngữ C++ cho phép người dùng định nghĩa ra các hàm giống tên và chức năng với nhau, nhưng khác nhau về kiểu trả về hoặc khác nhau về tham số. Khi gọi hàm, chương trình sẽ dựa vào đặc điểm của tham số trong lời gọi để quyết định hàm nào sẽ được gọi. Các hàm trùng tên, tính năng tương tự nhưng khác về tham số như vậy được gọi là các hàm nạp chồng. Hàm nạp chồng giúp lập trình viên tiết kiệm thời gian hơn khi không phải mất công nghĩ ra các tên hàm khác nhau cho nhiều biến thể của cùng một công việc. Ví dụ: Dưới đây định nghĩa hàm
Biên dịch và chạy chương trình trên sẽ cho ra kết quả:
Lưu ý: Các hàm nạp chồng buộc phải khác nhau hoàn toàn về danh sách tham số, chứ không thể chỉ khác nhau về kiểu trả về. Việc sử dụng hàm nạp chồng rất hữu ích trong lập trình, bởi vì có rất nhiều kiểu dữ liệu sẽ phát sinh trong quá trình làm việc. Thay vì sử dụng ép kiểu khiến cho chương trình trở nên dài dòng và rối mắt, ta nên tạo ra các hàm nạp chồng cho mọi kiểu dữ liệu cần dùng. Rất nhiều hàm có sẵn của C++ được xây dựng bằng phương pháp nạp chồng hàm này. 2. Nạp chồng toán tửTrên thực tế, các toán tử trong C++ chính là các hàm được viết sẵn. Khi người dùng sử dụng một toán tử nào đó, trình biên dịch sẽ gọi ra phiên bản tương ứng của toán tử đó dựa vào kiểu dữ liệu của toán hạng. Lấy ví dụ:
Trong trình biên dịch đã chứa sẵn các phiên bản khác nhau của toán tử Đối với câu lệnh thứ hai: Lập trình viên có thể nạp chồng hầu hết các toán tử trong C++. Cú pháp để nạp chồng toán tử hoàn toàn giống như nạp chồng hàm:
Trong đó, {Kiểu_trả_về} là một kiểu có sẵn hoặc một kiểu do người dùng tự định nghĩa. {Toán_tử} là một toán tử sẵn có của C++. {Danh_sách_tham_số} là các tham số với kiểu do người dùng tự định nghĩa (không được sử dụng kiểu có sẵn cho các tham số). Dưới đây là danh sách các toán tử có thể nạp chồng trong C++: Các toán tử không thể nạp chồng bao gồm: VII. Khuôn mẫu hàm (Function Template) trong C++Khuôn mẫu hàm là một phương thức dùng để tạo ra các hàm tổng quát. Đặt trường hợp chúng ta có một công việc nhưng phải xử lý trên rất nhiều kiểu dữ liệu khác nhau. Nếu như định nghĩa quá nhiều hàm nạp chồng cũng sẽ gây dài dòng và khó kiểm tra. Khuôn mẫu hàm sẽ giúp cho lập trình viên giải quyết việc đó, bằng cách tạo ra 1 hàm tổng quát và trình biên dịch sẽ tự chọn kiểu dữ liệu phù hợp cho nó trong quá trình biên dịch mã nguồn. Cú pháp:
Ở đây, {Kiểu_dữ_liệu_tổng_quát} là một định danh bất kỳ do người dùng đặt ra để thay thế cho tên kiểu cụ thể. Từ khóa Ví dụ: Dưới đây là một function template trả về giá trị lớn nhất trong hai giá trị ở các kiểu: số nguyên, số thực và chuỗi kí tự.
Biên dịch và chạy chương trình trên sẽ cho ra kết quả:
Ngoài khuôn mẫu hàm, trong C++ còn có khuôn mẫu lớp, tuy nhiên lớp (class) trong C++ thuộc về kĩ thuật lập trình hướng đối tượng, nên tôi sẽ không đề cập ở đây. VIII. Tài liệu tham khảo
|