MonoDevelop (https://www.monodevelop.com/) là một open-source GNOME IDE (intergrated development environment) hỗ trợ lập trình đa ngôn ngữ (với mục tiêu ban đầu là .Net) trên các hệ điều hành Linux, Mac OS X và Windows.
Phiên bản hiện tại 7.6 (7.6.9.22) ra mắt vào đầu 2019.
Với giao diện tương tự Visual Studio, chúng ta có thể nhanh chóng làm quen và phát triển các dự án .Net trên những platform khác nhau.
Những chức năng chính
Multi-platform: Supports Linux, Windows and macOS.
Advanced Text Editing: Code completion support for C#, code templates, code folding.
Configurable workbench: Fully customizable window layouts, user defined key bindings, external tools.
Multiple language support: C#, F#, Visual Basic .NET, Vala.
Integrated Debugger: For debugging Mono and native applications.
Trong bài này chúng ta cùng tìm hiểu việc cài đặt dotNet Core 3.1 trên Hệ điều hành CentOS 7.
dotNet là gì
.NET là một nền tảng phát triển mã nguồn mở, đa nền tảng, miễn phí để xây dựng nhiều loại ứng dụng khác nhau.
Với .NET, chúng ta có thể sử dụng nhiều ngôn ngữ, trình soạn thảo và thư viện để xây dựng cho web, thiết bị di động, máy tính để bàn, chơi game và IoT.
Cho dù chúng ta đang làm việc với ngôn ngữ C#, F# hoặc Visual Basic, mã nguồn sẽ chạy tự nhiên trên mọi hệ điều hành tương thích. Những triển khai .NET khác nhau xử lý các tác vụ nặng cho chúng ta:
.NET Core là một triển khai .NET đa nền tảng cho các trang web, máy chủ và ứng dụng bảng điều khiển trên Linux, Windows và macOS.
.NET Framework hỗ trợ các trang web, dịch vụ, ứng dụng máy tính để bàn và nhiều hơn nữa trên Windows.
Xamarin / Mono là một triển khai .NET để chạy các ứng dụng trên tất cả các hệ điều hành di động chính.
dotNet Core
.NET Core có các đặc điểm sau:
Đa nền tảng: Chạy trên các hệ điều hành Windows, macOS và Linux.
Nhất quán trên các kiến trúc: Chạy mã nguồn với cùng một hành vi trên nhiều kiến trúc, bao gồm x64, x86 và ARM.
Các công cụ dòng lệnh: Bao gồm các công cụ dòng lệnh dễ sử dụng có thể được sử dụng để phát triển cục bộ và trong các tình huống tích hợp liên tục.
Triển khai linh hoạt: Có thể được bao gồm trong ứng dụng riêng hoặc được cài đặt song song (cài đặt toàn người dùng hoặc toàn hệ thống).
Tương thích: .NET Core tương thích với .NET Framework, Xamarin và Mono, thông qua .NET Standard.
Nguồn mở: Nền tảng .NET Core là nguồn mở, sử dụng giấy phép MIT và Apache 2. .NET Core là một dự án .NET Foundation.
Được hỗ trợ bởi Microsoft: .NET Core được Microsoft hỗ trợ, theo Hỗ trợ .NET Core.
Các bước cài đặt dotNet Core 3.1 trên CentOS 7
Bước 1.
Chúng ta mở ứng dụng Terminal.
Trước khi cài đặt .NET, chúng ta sẽ cần phải đăng ký khóa Microsoft, đăng ký kho sản phẩm và cài đặt các phụ thuộc cần thiết.
Điều này chỉ cần được thực hiện một lần trên mỗi máy.
Xác định chỉ số i của phần tử x[i] đứng liền trước đoạn cuối đó.
Nếu tìm thấy chỉ số i như trên: (i) tìm phần tử x[k] nhỏ nhất thoả mãn điều kiện x[k] > x[i]; (ii) Đảo giá trị x[k] và x[i]; (iii) Lật ngược thứ tự đoạn cuối giảm dần (từ x[i+1] đến x[k]) trở thành tăng dần.
Nếu không tìm thấy tức là toàn dãy đã sắp giảm dần, đây là cấu hình cuối cùng
Bước 1.
Chúng ta định nghĩa một mảng gồm n phần tử.
Bước 2.
Chúng ta gán giá trị là chỉ số vị trí tương ứng cho từng phần tử trong mảng.
Bước 3.
Chúng ta thực hiện thuật toán sinh trong vòng lặp while() {}.
Nội dung chính của thuật toán bao gồm các bước từ 3.1 đến 3.4.
Bước 3.1.
Tại từng bước lặp, chúng ta nhận được một hoán vị.
Chúng ta thêm hoán vị này vào danh sách sequences.
Bước 3.2.
Chúng ta duyệt các phần tử từ cuối dãy trở lại.
Bước 3.3.
Chúng ta thực hiện xem xét nếu chưa gặp phải hoán vị cuối.
Việc kiểm tra được thực hiện từ Bước 3.3.1 đến 3.3.3.
Bước 3.3.1.
Chúng ta duyệt các phần tử từ cuối dãy trở lại.
Bước 3.3.2.
Chúng ta lùi dần k.
Bước 3.3.3.
Chúng ta thực hiện đổi chỗ x[k] và x[i].
Bước 3.3.4.
Chúng ta điều chỉnh những phần tử sau x[i].
Bước 3.4.
Thuật toán sinh dừng lại khi toàn bộ dãy giảm dần.
Thử nghiệm
Chúng ta thử nghiệm phương thức GeneratePermutation() trong class Program.cs.
Kết luận
Trong nội dung bài này, chúng ta đã cùng tìm hiểu một số bài toán con đối với thuật toán sinh để liệt kê một danh sách theo yêu cầu cho trước.
Hi vọng chúng ta có thể hiểu thêm về tư duy thuật toán cũng như một số các kỹ thuật lập trình Csharp để áp dụng cho các bài khác.
Trong nhóm bài này, chúng ta cùng nhau tìm hiểu việc thiết kế một kiến trúc để lập trình phần mềm theo mô hình 3 lớp.
Những nội dung chính sẽ được trình bày trong nhóm bài:
Thiết lập một cơ sở dữ liệu cơ bản trong PostgreSQL để áp dụng trong toàn bộ nhóm bài. Chúng ta có thể tham khảo để tự thực hiện đối với những hệ quản trị cơ sở dữ liệu khác như: MySQL / MariaDB; SQLServer; Oracle; …
Thiết kế kiến trúc lập trình phần mềm theo mô hình 3 lớp. Chúng ta cũng sẽ áp dụng một chút kiến thức về lập trình hướng đối tượng ở đây.
Kỹ thuật kết nối và truy vấn cơ sở dữ liệu theo phương pháp Prepared Statement. Đây là phương pháp được ưu tiên khuyến khích hơn phương pháp thông thường.
Những kỹ thuật lập trình cụ thể sẽ được trình bày lần lượt với các ngôn ngữ: Java / C# / Python / PHP.
Nội dung chính của bài này là trình bày phần thứ hai và tập trung vào Tầng 2 trong nội dung về kỹ thuật lập trình với ngôn ngữ Csharp:
Phần 1. Xây dựng kiến trúc tổng quan của mô hình 3 lớp.
Phần 2. Kỹ thuật lập trình cụ thể cho từng tầng trong kiến trúc mô hình 3 lớp.
Class BaseService
Bước 1.
Chúng ta thiết kế lớp cơ sở BaseService như sau:
Bước 2.
Chúng ta đặc tả phương thức createConnection() đối với tác vụ kết nối đến PostgreSQL:
Bước 3.
Chúng ta đặc tả các phương thức chính trong class BaseService:
Class CategoryService
Chúng ta thiết kế lớp dẫn xuất CategoryService như sau:
Class ProductService
Chúng ta thiết kế lớp dẫn xuất ProductService như sau:
Kết luận
Trong bài này, chúng ta cùng nhau tìm hiểu việc thực hiện kỹ thuật lập trình cho phần thứ hai và tập trung vào Tầng 2.
Chúng ta có thể áp dụng những kiến thức trong nhóm bài để thực hiện một số bài tập:
Thêm / xóa / sửa / truy vấn dữ liệu trong bảng category và product theo những yêu cầu thực tế khác nhau.
Thay đổi cơ sở dữ liệu PostgreSQL bởi các cơ sở dữ liệu khác: MySQL / MariaDB; Oracle; …
Nhóm bài này sẽ trở thành một trong những kiến thức nền để thực hiện các dạng phần mềm: Desktop / Web Application.
Trong nhóm bài này, chúng ta cùng nhau tìm hiểu việc thiết kế một kiến trúc để lập trình phần mềm theo mô hình 3 lớp.
Những nội dung chính sẽ được trình bày trong nhóm bài:
Thiết lập một cơ sở dữ liệu cơ bản trong PostgreSQL để áp dụng trong toàn bộ nhóm bài. Chúng ta có thể tham khảo để tự thực hiện đối với những hệ quản trị cơ sở dữ liệu khác như: MySQL / MariaDB; SQLServer; Oracle; …
Thiết kế kiến trúc lập trình phần mềm theo mô hình 3 lớp. Chúng ta cũng sẽ áp dụng một chút kiến thức về lập trình hướng đối tượng ở đây.
Kỹ thuật kết nối và truy vấn cơ sở dữ liệu theo phương pháp Prepared Statement. Đây là phương pháp được ưu tiên khuyến khích hơn phương pháp thông thường.
Những kỹ thuật lập trình cụ thể sẽ được trình bày lần lượt với các ngôn ngữ: Java / C# / Python / PHP.
Nội dung chính của bài này là trình bày phần thứ hai và tập trung vào Tầng 3 trong nội dung về kỹ thuật lập trình với ngôn ngữ Csharp:
Phần 1. Xây dựng kiến trúc tổng quan của mô hình 3 lớp.
Phần 2. Kỹ thuật lập trình cụ thể cho từng tầng trong kiến trúc mô hình 3 lớp.
Class BaseDAO – Kiến trúc tổng quan
Bước 1.
Chúng ta thiết kế lớp cơ sở BaseDAO thành abstract class như sau:
Bước 2.
Chúng ta định nghĩa các thuộc tính trong class BaseDAO:
Bước 3.
Chúng ta định nghĩa phương thức khởi tạo không có tham số của class BaseDAO:
Bước 4.
Chúng ta định nghĩa các phương thức chính trong class BaseDAO:
Class BaseDAO – Phương thức getConnection()
Chúng ta đặc tả phương thức getConnection() đối với tác vụ kết nối đến PostgreSQL:
Class BaseDAO – Phương thức selectDataFromOneTable()
Bước 1.
Chúng ta đặc tả phương thức selectDataFromOneTable() đối với tác vụ truy xuất dữ liệu từ một bảng trong PostgreSQL.
Chúng ta thực hiện kỹ thuật bắt lỗi kết nối và truy vấn cơ sở dữ liệu:
Bước 2.
Mã nguồn SQL tổng quan để thực hiện truy vấn dữ liệu:
SELECT column_i, …, column_j FROM table [WHERE column_k = value_k AND … AND column_l = value_l]
Chúng ta đặc tả phần thứ nhất của chuỗi SQL như sau:
Bước 3.
Chúng ta đặc tả phần thứ hai của chuỗi SQL như sau:
Kỹ thuật lập trình cần chú ý ở đây:
Giá trị của từng trường điều kiện được thể hiện bằng dấu “?”.
Chúng ta sẽ thay thế từng dấu “?” bằng giá trị tương ứng trong dataSet ở các bước sau.
Đây là bước đầu tiên của kỹ thuật Prepared Statement. Kỹ thuật này giúp truy xuất dữ liệu thuận tiện hơn, độc lập cơ sở dữ liệu và phần nào chống được kỹ thuật tấn công SQL Injection.
Bước 4.
Chúng ta gọi phương thức getConnection() để thực hiện kỹ thuật kết nối cơ sở dữ liệu:
Bước 5.
Chúng ta định nghĩa một thực thể của class NpgsqlCommand:
Đây là bước thứ hai của kỹ thuật Prepared Statement giúp chuẩn bị thay thế từng dấu “?” trong chuỗi SQL bởi giá trị tương ứng.
Bước 6.
Chúng ta gọi phương thức appendData() để thực hiện bước thứ ba của kỹ thuật Prepared Statement là thay thế từng dấu “?” trong chuỗi SQL bởi giá trị tương ứng:
Kỹ thuật lập trình cần chú ý ở đây:
Chúng ta định nghĩa phương thức appendData() là abstract trong class BaseDAO.
Chúng ta đặc tả cụ thể các kỹ thuật lập trình của phương thức appendData() trong các lớp dẫn xuất là CategoryDAO và ProductDAO.
Bước 7.
Chúng ta thực hiện truy vấn dữ liệu và trả về kết quả là một thực thể của class NpgsqlDataReader.
Chúng ta tiếp tục gọi phương thức mappingData() để thực hiện việc chuyển đổi dữ liệu trong thực thể này về dạng mong muốn và thêm vào results.
Kỹ thuật lập trình cần chú ý ở đây:
Chúng ta định nghĩa phương thức mappingData() là abstract trong class BaseDAO.
Chúng ta đặc tả cụ thể các kỹ thuật lập trình của phương thức mappingData() trong các lớp dẫn xuất là CategoryDAO và ProductDAO.
Bước 8.
Chúng ta thực hiện đóng kết nối đến cơ sở dữ liệu:
Class BaseDAO – Phương thức insertData()
Bước 1.
Chúng ta đặc tả phương thức insertData() đối với tác vụ thêm dữ liệu vào một bảng trong PostgreSQL.
Chúng ta thực hiện kỹ thuật bắt lỗi kết nối và truy vấn cơ sở dữ liệu:
Bước 2.
Mã nguồn SQL tổng quan để thực hiện thêm dữ liệu:
INSERT INTO table (column_i, …, column_j) VALUE (value_i, …, value_j)
Chúng ta đặc tả phần thứ nhất của chuỗi SQL như sau:
Bước 3.
Chúng ta đặc tả phần thứ hai của chuỗi SQL như sau:
Bước 4.
Chúng ta gọi phương thức getConnection() để thực hiện kỹ thuật kết nối cơ sở dữ liệu:
Bước 5.
Chúng ta định nghĩa một thực thể của class NpgsqlCommand:
Bước 6.
Chúng ta gọi phương thức appendData() để thực hiện bước thứ ba của kỹ thuật Prepared Statement là thay thế từng dấu “?” trong chuỗi SQL bởi giá trị tương ứng:
Bước 7.
Chúng ta thực hiện thêm dữ liệu:
Bước 8.
Chúng ta thực hiện đóng kết nối đến cơ sở dữ liệu:
Class BaseDAO – Phương thức updateData()
Bước 1.
Chúng ta đặc tả phương thức updateData() đối với tác vụ cập nhật dữ liệu trong một bảng trong PostgreSQL.
Chúng ta thực hiện kỹ thuật bắt lỗi kết nối và truy vấn cơ sở dữ liệu:
Bước 2.
Mã nguồn SQL tổng quan để thực hiện cập nhật dữ liệu:
UPDATE table SET (column_i = value_i, …, column_j = value_j) [WHERE column_k = value_k AND … AND column_l = value_l]
Chúng ta đặc tả phần thứ nhất của chuỗi SQL như sau:
Bước 3.
Chúng ta đặc tả phần thứ hai của chuỗi SQL như sau:
Bước 4.
Chúng ta gọi phương thức getConnection() để thực hiện kỹ thuật kết nối cơ sở dữ liệu:
Bước 5.
Chúng ta định nghĩa một thực thể của class NpgsqlCommand:
Bước 6.
Chúng ta gọi phương thức appendData() để thực hiện bước thứ ba của kỹ thuật Prepared Statement là thay thế từng dấu “?” trong chuỗi SQL bởi giá trị tương ứng:
Bước 7.
Chúng ta thực hiện cập nhật dữ liệu:
Bước 8.
Chúng ta thực hiện đóng kết nối đến cơ sở dữ liệu:
Class BaseDAO – Phương thức deleteData()
Bước 1.
Chúng ta đặc tả phương thức deleteData() đối với tác vụ xóa dữ liệu trong một bảng trong PostgreSQL.
Chúng ta thực hiện kỹ thuật bắt lỗi kết nối và truy vấn cơ sở dữ liệu:
Bước 2.
Mã nguồn SQL tổng quan để thực hiện xóa dữ liệu:
DELETE FROM table WHERE column_k = value_k AND … AND column_l = value_l
Chúng ta đặc tả chuỗi SQL như sau:
Bước 3.
Chúng ta gọi phương thức getConnection() để thực hiện kỹ thuật kết nối cơ sở dữ liệu:
Bước 4.
Chúng ta định nghĩa một thực thể của class NpgsqlCommand:
Bước 5.
Chúng ta gọi phương thức appendData() để thực hiện bước thứ ba của kỹ thuật Prepared Statement là thay thế từng dấu “?” trong chuỗi SQL bởi giá trị tương ứng:
Bước 6.
Chúng ta thực hiện xóa dữ liệu:
Bước 7.
Chúng ta thực hiện đóng kết nối đến cơ sở dữ liệu:
Class CategoryDAO
Bước 1.
Chúng ta thiết kế lớp dẫn xuất CategoryDAO như sau:
Bước 2.
Chúng ta đặc tả kỹ thuật lập trình cho phương thức appendData() như sau:
Kỹ thuật lập trình cần chú ý:
Mỗi trường trong bảng category có định dạng khác nhau. Tương ứng là từng phần tử trong danh sách data cũng có định dạng khác nhau.
Theo quy định về kiểu dữ liệu List trong Csharp thì mọi phần tử đều phải có cùng một định dạng.
Như vậy chúng ta định nghĩa kiểu dữ liệu cho từng phần tử trong data là object: List<object> data. Đây là một class nguyên thủy và là cha của mọi class được định nghĩa.
Bước 3.
Chúng ta đặc tả kỹ thuật lập trình cho phương thức mappingData() như sau:
Class ProductDAO
Bước 1.
Chúng ta thiết kế lớp dẫn xuất ProductDAO như sau:
Bước 2.
Chúng ta đặc tả kỹ thuật lập trình cho phương thức appendData() như sau:
Bước 3.
Chúng ta đặc tả kỹ thuật lập trình cho phương thức mappingData() như sau:
Kết luận
Trong bài này, chúng ta cùng nhau tìm hiểu việc thực hiện kỹ thuật lập trình cho phần thứ hai và tập trung vào Tầng 3.
Trong bài tiếp theo, chúng ta cùng tìm hiểu việc thực hiện kỹ thuật lập trình cho Tầng 2.
Trong nhóm bài này, chúng ta cùng nhau tìm hiểu việc thiết kế một kiến trúc để lập trình phần mềm theo mô hình 3 lớp.
Những nội dung chính sẽ được trình bày trong nhóm bài:
Thiết lập một cơ sở dữ liệu cơ bản trong PostgreSQL để áp dụng trong toàn bộ nhóm bài. Chúng ta có thể tham khảo để tự thực hiện đối với những hệ quản trị cơ sở dữ liệu khác như: MySQL / MariaDB; SQLServer; Oracle; …
Thiết kế kiến trúc lập trình phần mềm theo mô hình 3 lớp. Chúng ta cũng sẽ áp dụng một chút kiến thức về lập trình hướng đối tượng ở đây.
Kỹ thuật kết nối và truy vấn cơ sở dữ liệu theo phương pháp Prepared Statement. Đây là phương pháp được ưu tiên khuyến khích hơn phương pháp thông thường.
Những kỹ thuật lập trình cụ thể sẽ được trình bày lần lượt với các ngôn ngữ: Java / C# / Python / PHP.
Nội dung chính của bài này là trình bày phần thứ nhất trong nội dung về kỹ thuật lập trình với ngôn ngữ Csharp:
Phần 1. Xây dựng kiến trúc tổng quan của mô hình 3 lớp.
Phần 2. Kỹ thuật lập trình cụ thể cho từng tầng trong kiến trúc mô hình 3 lớp.
Xây dựng kiến trúc tổng quan của mô hình 3 lớp
Bước 1.
Chúng ta tạo mới Console Project trong MonoDevelop và đặt tên là CsharpThreeTiersProject.
Chúng ta sẽ thực hiện các kỹ thuật lập trình về đặc tả giao diện Console ở Tầng 1.
Bước 2.
Chúng ta tạo class BaseService trong folder Service.
Đây là lớp cơ sở của Tầng 2 về xử lý các tác vụ trung gian.
Bước 3.
Chúng ta tạo class CategoryService và ProductService trong folder Service.
Đây là các lớp dẫn xuất của BaseService để thực thi cụ thể các tác vụ ở Tầng 2.
Bước 4.
Chúng ta tạo class BaseDAO trong folder Dao.
Đây là lớp cơ sở của Tầng 3 về xử lý các tác vụ kết nối và truy vấn cơ sở dữ liệu.
Bước 5.
Chúng ta tạo class CategoryDAO và ProductDAO trong folder Dao.
Đây là các lớp dẫn xuất của BaseDAO để thực thi cụ thể các tác vụ ở Tầng 3.
Thiết lập driver điều khiển để kết nối PostgreSQL
Bước 1.
Chúng ta download nuget npgsql 4.0.10 tại địa chỉ như trong hình.
Bước 2.
Chúng ta lựa chọn Edit → Preferences … trong project.
Bước 3.
Màn hình Preferences hiện ra.
Chúng ta lựa chọn NuGet → Sources ở cột bên trái.
Chúng ta lựa chọn nút Add để thêm nuget.
Bước 4.
Màn hình Add Package Source hiện ra.
Chúng ta nhập Name như trong hình và chỉ để file nuget download bên trên.
Chúng ta lựa chọn nút Add Source để thực hiện.
Bước 5.
Màn hình Preferences sau khi thêm nuget hiện ra.
Chúng ta lựa chọn nút OK để thực hiện.
Bước 6.
Chúng ta nhấn chuột phải vào tên project.
Chúng ta lựa chọn Add → Add NuGet Packages …
Bước 7.
Màn hình Add Packages hiện ra.
Chúng ta lựa chọn nuget source phù hợp trong combo box.
Chúng ta lựa chọn nutget Npgsql và chú ý đúng version 4.0.10 đã download bên trên.
Chúng ta lựa chọn nút Add Package để thực hiện.
Bước 8.
Màn hình chính của project sau khi được thêm nuget npgsql.
Kết luận
Trong bài này, chúng ta đã cùng nhau tìm hiểu việc xây dựng kiến trúc tổng quan của mô hình 3 lớp cho một Csharp Project.
Trong bài tiếp theo, chúng ta sẽ cùng thực hiện các tác vụ cụ thể.
Trong nội dung bài này, chúng ta cùng nhau tìm hiểu một số bài toán cơ bản về ước số và bội số:
Tìm ước số chung lớn nhất của hai số tự nhiên.
Tìm bội số chung nhỏ nhất của hai số tự nhiên.
Phân tích một số tự nhiên thành các thừa số nguyên tố.
Tính số lượng các ước số của một số tự nhiên.
Tính tổng các ước số của một số tự nhiên.
Ước số chung lớn nhất của hai số
Ý tưởng giải thuật
Ước số chung lớn nhất (USCLN) của 2 số được tính theo thuật toán Euclid:
UCLN (a, b) = UCLN (b, (a mod b))
Bước 1.
Chúng ta tạo một Console Project trong MonoDevelop và đặt tên là CsharpAlgorithmSecondProject.
Bước 2.
Chúng ta tạo folder Algorithm và class UocBoi.cs.
Bước 3.
Chúng ta thực hiện giải thuật bằng ngôn ngữ Csharp như sau:
Bội số chung nhỏ nhất của hai số
Ý tưởng giải thuật
Bội số chung nhỏ nhất (BSCNN) của hai số được tính theo công thức:
Bước 1.
Chúng ta thực hiện giải thuật bằng ngôn ngữ Csharp như sau:
Bước 2.
Chúng ta thực hiện thử nghiệm phương thức TinhUCLN() và TinhBCNN() trong class Program.cs như sau:
Bước 3.
Chúng ta thực thi toàn bộ project để kiểm tra kết quả thử nghiệm:
Phân tích thừa số nguyên tố
Ý tưởng giải thuật
Chúng ta thực hiện chia số N cho các số nguyên tố trong đoạn [2; N].
Với mỗi số nguyên tố đó, đếm số lần mà số N chia hết.
Sau mỗi lần chia cho số i, số N của chúng ta sẽ giảm đi i lần.
Chúng ta dừng quá trình chia khi số chia lớn hơn N.
Bước 1.
Chúng ta thực hiện giải thuật bằng ngôn ngữ Csharp như sau:
Những kỹ thuật lập trình cần chú ý:
Chúng ta sử dụng kiểu dữ liệu Dictionary của Csharp để lưu trữ tập hợp không giới hạn các phần tử theo từng cặp <từ_khóa, giá trị>. Mỗi phần tử là một cặp: từ_khóa là thừa số nguyên tố; giá_trị là số mũ tương ứng với thừa số nguyên tố này.
Do thừa số nguyên tố và số mũ đều là số nguyên, chúng ta định nghĩa kiểu dữ liệu tập hợp là Dictionary<int, int>.
Bước 2.
Chúng ta thực hiện thử nghiệm phương thức PhanTichTSNT() trong class Program.cs như sau:
Những kỹ thuật lập trình cần chú ý:
Chúng ta sử dụng lớp thư viện StringBuilder để xử lý một số tác vụ liên quan đến chuỗi.
Phương thức Append() của StringBuilder thực hiện nối một chuỗi mới vào chuỗi hiện có.
Cách thức duyệt từng phần tử trong Dictionary là sử dụng kiểu dữ liệu KeyValuePair<>. Từng phần tử được truy xuất sẽ có thể lấy ra được từ_khóa là Key và giá_trị là Value.
Bước 3.
Chúng ta thực thi toàn bộ project để kiểm tra kết quả thử nghiệm:
Số các ước số của một số
Ý tưởng giải thuật
Giả sử N được phân tích thành thừa số nguyên tố như sau:
Số các ước số của N là
Bước 1.
Chúng ta thực hiện giải thuật bằng ngôn ngữ Csharp như sau:
Tổng các ước số của một số
Ý tưởng giải thuật
Tổng các ước của N là
Bước 1.
Chúng ta thực hiện giải thuật bằng ngôn ngữ Csharp như sau:
Bước 2.
Chúng ta thực hiện thử nghiệm phương thức TinhSoUocSo() và TinhTongUocSo() trong class Program.cs như sau:
Bước 3.
Chúng ta thực thi toàn bộ project để kiểm tra kết quả thử nghiệm:
Tổng kết
Trong bài này, chúng ta đã cùng nhau tìm hiểu một số giải thuật cơ bản xung quanh ước số và bội số của một số tự nhiên và thực hiện bằng ngôn ngữ Csharp.
Hy vọng rằng chúng ta có thể áp dụng phù hợp những kỹ thuật và chức năng này cho những bài tiếp theo.
Trong nội dung bài viết này, chúng ta cùng nhau tìm hiểu cách thức mà Java hỗ trợ việc thực hiện những thuật ngữ về Lập trình hướng đối tượng: (i) tính chất trừu tượng – abstraction; (ii) tính chất đa hình – polymorphism; (iii) lớp trừu tượng – abstract class; (iv) giao diện – interface.
Chúng ta thiết kế một chương trình nhỏ bao gồm các lớp và giao diện như sau:
Lớp trừu tượng: PhuongTienGiaoThong.
Các lớp đối tượng ở tầng dưới thứ hai: PhuongTienDuongBo; PhuongTienDuongThuy; PhuongTienDuongKhong.
Các lớp đối tượng ở tầng dưới cùng: Oto; XeMay; XeDap; TauThuy; Thuyen; MayBay; KhinhKhiCau; ThuyPhiCo.
Giao diện ở cấp cao nhất: HoatDong.
Giao diện ở tầng dưới: CoTheChay; CoTheBay; CoTheBoi.
Thiết kế Lớp trừu tượng
Bước 1.
Chúng ta thực hiện tạo Console Project trong MonoDevelop và đặt tên là CsharpOOPThirdProject.
Mặc định thì class Program.cs được tạo ra với phương thức Main().
Bước 2.
Chúng ta thực hiện tạo folder Object.
Chúng ta thực hiện tạo class PhuongTienGiaoThong.
Bước 3.
Chúng ta thực hiện tạo class PhuongTienDuongBo là một dẫn xuất của class PhuongTienGiaoThong.
Bước 4.
Chúng ta thực hiện tạo class PhuongTienDuongThuy là một dẫn xuất của class PhuongTienGiaoThong.
Bước 5.
Chúng ta thực hiện tạo class PhuongTienDuongKhong là một dẫn xuất của class PhuongTienGiaoThong.
Thiết kế Lớp đối tượng
Bước 1.
Chúng ta thực hiện tạo class Oto là một dẫn xuất của class PhuongTienDuongBo.
Bước 2.
Chúng ta thực hiện tạo class XeMay là một dẫn xuất của class PhuongTienDuongBo.
Bước 3.
Chúng ta thực hiện tạo class XeDap là một dẫn xuất của class PhuongTienDuongBo.
Bước 4.
Chúng ta thực hiện tạo class Thuyen là một dẫn xuất của class PhuongTienDuongThuy.
Bước 5.
Chúng ta thực hiện tạo class TauThuy là một dẫn xuất của class PhuongTienDuongThuy.
Bước 6.
Chúng ta thực hiện tạo class MayBay là một dẫn xuất của class PhuongTienDuongKhong.
Bước 7.
Chúng ta thực hiện tạo class KhinhKhiCau là một dẫn xuất của class PhuongTienDuongKhong.
Bước 8.
Chúng ta thực hiện tạo class ThuyPhiCo là một dẫn xuất của class PhuongTienGiaoThong.
Thiết kế Giao diện
Bước 1.
Chúng ta thực hiện tạo folder action.
Chúng ta thực hiện tạo interface ICoTheChay.
Những điểm cần chú ý:
Chúng ta sử dụng từ khóa interface đứng trước định nghĩa tên của giao diện.
Riêng đối với Csharp, một quy tắc phổ biến là thêm chữ cái I đứng trước tên dự kiến được đặt cho giao diện. Ở đây chúng ta có ICoTheChay.
Bước 2.
Chúng ta thực hiện tạo interface ICoTheBoi.
Bước 3.
Chúng ta thực hiện tạo interface ICoTheBay.
Bước 4.
Chúng ta thực hiện tạo interface IHoatDong là giao diện cơ sở của các giao diện: ICoTheChay; ICoTheBay; ICoTheBoi.
Thiết kế Tính đa hình thứ nhất
Bước 1.
Chúng ta đặc tả những đặc trưng của abstract class PhuongTienGiaoThong:
Thuộc tính: soLuongBanhXe; soLuongChoNgoi.
Những phương thức get / set.
Phương thức trừu tượng: GioiThieu().
Chú ý rằng những đặc trưng này sẽ được kế thừa lại hoàn toàn từ những lớp dẫn xuất của PhuongTienGiaoThong trên cây gia phả.
Bước 2.
Chúng ta đặc tả những đặc trưng của class PhuongTienDuongBo:
Thuộc tính. Đầu tiên là kế thừa những thuộc tính từ lớp cơ sở PhuongTienGiaoThong. Tiếp đến là định nghĩa thêm 01 thuộc tính riêng biệt: loaiDongCo.
Phương thức. Đầu tiên là kế thừa trọn vẹn những phương thức get / set đối với những thuộc tính được đặc tả ở lớp cơ sở PhuongTienGiaoThong. Tiếp đến là định nghĩa các phương thức get / set đối với thuộc tính loaiDongCo.
Kế thừa và đặc tả lại phương thức GioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.
Chú ý rằng những đặc trưng này sẽ được kế thừa lại hoàn toàn từ những lớp dẫn xuất của PhuongTienDuongBo trên cây gia phả.
Bước 3.
Chúng ta đặc tả những đặc trưng của classPhuongTienDuongKhong:
Thuộc tính. Đầu tiên là kế thừa những thuộc tính từ lớp cơ sở PhuongTienGiaoThong. Tiếp đến là định nghĩa thêm 02 thuộc tính riêng biệt: soLuongCanh; soLuongQuat.
Phương thức. Đầu tiên là kế thừa trọn vẹn những phương thức get / set đối với những thuộc tính được đặc tả ở lớp cơ sở PhuongTienGiaoThong. Tiếp đến là định nghĩa các phương thức get / set đối với thuộc tính soLuongCanh; soLuongQuat.
Kế thừa và đặc tả lại phương thức GioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.
Chú ý rằng những đặc trưng này sẽ được kế thừa lại hoàn toàn từ những lớp dẫn xuất của PhuongTienDuongKhong trên cây gia phả.
Bước 4.
Chúng ta đặc tả những đặc trưng của class PhuongTienDuongThuy:
Thuộc tính. Đầu tiên là kế thừa những thuộc tính từ lớp cơ sở PhuongTienGiaoThong. Tiếp đến là định nghĩa thêm 01 thuộc tính riêng biệt: loaiBanhLai.
Phương thức. Đầu tiên là kế thừa trọn vẹn những phương thức get / set đối với những thuộc tính được đặc tả ở lớp cơ sở PhuongTienGiaoThong. Tiếp đến là định nghĩa các phương thức get / set đối với thuộc tính loaiBanhLai.
Kế thừa và đặc tả lại phương thức GioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.
Chú ý rằng những đặc trưng này sẽ được kế thừa lại hoàn toàn từ những lớp dẫn xuất của PhuongTienDuongThuy trên cây gia phả.
Bước 5.
Chúng ta đặc tả những đặc trưng của class Oto:
Thuộc tính. Kế thừa trọn vẹn những thuộc tính từ lớp cơ sở PhuongTienDuongBo.
Phương thức. Kế thừa và đặc tả lại phương thức GioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.
Bước 6.
Chúng ta đặc tả những đặc trưng của class XeMay:
Thuộc tính. Kế thừa trọn vẹn những thuộc tính từ lớp cơ sở PhuongTienDuongBo.
Phương thức. Kế thừa và đặc tả lại phương thức GioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.
Bước 7.
Chúng ta đặc tả những đặc trưng của class XeDap:
Thuộc tính. Kế thừa trọn vẹn những thuộc tính từ lớp cơ sở PhuongTienDuongBo.
Phương thức. Kế thừa và đặc tả lại phương thức GioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.
Bước 8.
Chúng ta đặc tả những đặc trưng của class MayBay:
Thuộc tính. Kế thừa trọn vẹn những thuộc tính từ lớp cơ sở PhuongTienDuongKhong.
Phương thức. Kế thừa và đặc tả lại phương thức GioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.
Bước 9.
Chúng ta đặc tả những đặc trưng của class KhinhKhiCau:
Thuộc tính. Kế thừa trọn vẹn những thuộc tính từ lớp cơ sở PhuongTienDuongKhong.
Phương thức. Kế thừa và đặc tả lại phương thức GioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.
Bước 10.
Chúng ta đặc tả những đặc trưng của class TauThuy:
Thuộc tính. Kế thừa trọn vẹn những thuộc tính từ lớp cơ sở PhuongTienDuongThuy.
Phương thức. Kế thừa và đặc tả lại phương thức GioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.
Bước 11.
Chúng ta đặc tả những đặc trưng của class Thuyen:
Thuộc tính. Kế thừa trọn vẹn những thuộc tính từ lớp cơ sở PhuongTienDuongThuy.
Phương thức. Kế thừa và đặc tả lại phương thức GioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.
Bước 12.
Chúng ta đặc tả những đặc trưng của class ThuyPhiCo:
Thuộc tính. Đầu tiên là kế thừa những thuộc tính từ lớp cơ sở PhuongTienGiaoThong. Tiếp đến là định nghĩa thêm 02 thuộc tính riêng biệt: loaiBanhLai; soLuongCanh.
Phương thức. Đầu tiên là kế thừa trọn vẹn những phương thức get / set đối với những thuộc tính được đặc tả ở lớp cơ sở PhuongTienGiaoThong. Tiếp đến là định nghĩa các phương thức get / set đối với thuộc tính loaiBanhLai; soLuongCanh.
Kế thừa và đặc tả lại phương thức GioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.
Bước 13.
Chúng ta thực hiện thử nghiệm tính đa hình như bên dưới.
Chúng ta có thể nhận thấy những điểm rất rõ ở đây là:
Thực thể của đối tượng nào thì sẽ tự biết mình là ai.
Và như vậy sẽ tự thực hiện một cách chính xác phương thức GioiThieu() cũng như các phương thức get / set của các thuộc tính được đặc tả trong lớp trừu tượng PhuongTienGiaoThong.
Bước 14.
Kết quả thực hiện thử nghiệm đa hình thứ nhất như sau:
Thiết kế Tính đa hình thứ hai
Bước 1.
Chúng ta định nghĩa phương thức trừu tượng ThongBao() trong interface cơ sở IHoatDong.
Bước 2.
Chúng ta định nghĩa interface ICoTheChay kế thừa từ interface IHoatDong:
Kế thừa việc định nghĩa các phương thức trừu tượng từ interface IHoatDong.
Định nghĩa phương thức trừu tượng riêng biệt: Chay().
Bước 3.
Chúng ta định nghĩa interface ICoTheBoi kế thừa từ interface IHoatDong:
Kế thừa việc định nghĩa các phương thức trừu tượng từ interface IHoatDong.
Định nghĩa phương thức trừu tượng riêng biệt: Boi().
Bước 4.
Chúng ta định nghĩa interface ICoTheBay kế thừa từ interface IHoatDong:
Kế thừa việc định nghĩa các phương thức trừu tượng từ interface IHoatDong.
Định nghĩa phương thức trừu tượng riêng biệt: Bay().
Bước 5.
Chúng ta điều chỉnh class PhuongTienDuongBo để thuộc phạm vi ảnh hưởng của interface ICoTheChay:
Kế thừa và đặc tả lại toàn bộ các phương thức trừu tượng được định nghĩa trong interface IHoatDong cũng như ICoTheChay.
Bước 6.
Chúng ta điều chỉnh class PhuongTienDuongThuy để thuộc phạm vi ảnh hưởng của interface ICoTheBoi:
Kế thừa và đặc tả lại toàn bộ các phương thức trừu tượng được định nghĩa trong interface IHoatDong cũng như ICoTheBoi.
Bước 7.
Chúng ta điều chỉnh class PhuongTienDuongKhong để thuộc phạm vi ảnh hưởng của interface ICoTheBay:
Kế thừa và đặc tả lại toàn bộ các phương thức trừu tượng được định nghĩa trong interface IHoatDong cũng như ICoTheBay.
Bước 8.
Chúng ta điều chỉnh class ThuyPhiCo để thuộc phạm vi ảnh hưởng của interface ICoTheChay và ICoTheBoi.
Có thể thực thi cùng lúc nhiều interface. Có nghĩa rằng 1 lớp đối tượng có thể cùng lúc chịu ảnh hưởng của nhiều bộ quy tắc khác nhau.
Kế thừa và đặc tả lại toàn bộ các phương thức trừu tượng được định nghĩa trong interface IHoatDong cũng như ICoTheChay, ICoTheBoi.
Bước 9.
Chúng ta điều chỉnh lại ví dụ về tính đa hình như bên dưới.
Những điểm cần chú ý:
Những đối tượng thuộc phạm vi ảnh hưởng của những interface khác nhau sẽ thực thi những phương thức đặc trưng riêng của từng interface.
Chúng ta cần kiểm tra một chút để biết thực thể của đối tượng nào bằng cách sử dụng từ khóa is.
Tổng kết
Trong bài này, chúng ta đã cùng nhau tìm hiểu sự hỗ trợ của Csharp trong việc thực hiện tính chất đa hình trong Lập trình hướng đối tượng.
Hi vọng với bài này thì chúng ta đã có cái nhìn tổng quát hơn về cả 04 tính chất đặc trưng nhất của Lập trình hướng đối tượng.
Tiếp theo nội dung của bài trước, trong bài này chúng ta cùng nhau tìm hiểu một số kỹ thuật lập trình cơ bản trong C# đồng thời tìm hiểu một số chức năng cần thiết trong MonoDevelop.
Chúng ta thực hiện tiếp Yêu cầu 2 và Yêu cầu 3 của bài toán cơ bản thông qua những kỹ thuật về lập trình:
Câu lệnh điều khiển và rẽ nhánh.
Các toán tử cơ bản.
Định nghĩa và thực thi các phương thức.
Chúng ta cũng tìm hiểu phương pháp debug trong MonoDevelop để kiểm tra từng câu lệnh cũng như bắt lỗi.
Những kỹ thuật được trình bày sẽ mang tính phổ quát và độc lập ngôn ngữ lập trình. Điều đó có nghĩa rằng chúng ta có thể áp dụng ý tưởng từ các kỹ thuật này khi tìm hiểu các ngôn ngữ khác như PHP / Java / Python.
Xây dựng phương thức trong C#
Một phương thức trong C# là một khối các câu lệnh có tên và có thể được thực thi bằng cách gọi từ một nơi khác trong chương trình.
Chú ý rằng một phương thức phải được định nghĩa bên trong một class. Điều này sẽ được thảo luận kỹ hơn trong các bài tiếp theo về lập trình hướng đối tượng.
Cấu trúc cú pháp của một phương thức như sau:
phạm_vi_truy_cập [static] kiểu_dữ_liệu_trả_về tên_phương_thức (danh_sách_tham_số) { // Thực hiện công việc }
Chúng ta có hai dạng phương thức chính:
Dạng phương thức không trả về kết quả.
Dạng phương thức có trả về kết quả.
Xây dựng phương thức không trả về kết quả
Bước 1.
Chúng ta thực hiện việc tạo một Console Project mới trong MonoDevelop.
Màn hình giao diện MonoDevelop hiển thị nội dung mặc của class MainClass.cs hiện ra.
Bước 2.
Chúng ta lựa chọn tạo class mới bằng cách nhấn chuột phải vào tên của project trong phân vùng màn hình bên trái.
Chúng ta lựa chọn chức năng Add → New File …
Bước 3.
Màn hình New File hiện ra.
Chúng ta lựa chọn mục General trong phân vùng màn hình bên trái.
Chúng ta lựa chọn chức năng Empty Class trong phân vùng màn hình ở giữa.
Chúng ta nhập thông tin như sau:
Name: BaiCoBan
Chú ý rằng, theo quy định trong C# thì chữ cái đầu của file phải được viết hoa.
Chúng ta lựa chọn nút New để thực hiện.
Bước 4.
Hệ thống thực hiện việc tạo mới class BaiCoBan.cs.
Chúng ta điều chỉnh thông tin thứ nhất như sau:
namespace BaiTap
Về cơ bản thì namespace trong C# có ý nghĩa tương tự như package trong Java. Nội dung về namespace và class sẽ được thảo luận sâu hơn trong các bài tiếp theo về lập trình hướng đối tượng.
Chúng ta tiếp tục tạo phương thức:
public void TinhTong() {}
Những điểm cần chú ý ở đây:
Theo quy định trong C# thì chữ cái đầu của phương thức phải được viết hoa.
Về nguyên tắc chung khi viết mã nguồn C#, cặp dấu {} nên để bên dưới phần định nghĩa phương thức. Không giống như Java là dấu { để ngay bên phải phần định nghĩa phương thức.
Từ khóa thứ nhất cho biết phạm vi được phép truy xuất đến phương thức này. Ở đây chúng ta sử dụng từ khóa public. Từ khóa này cho biết phạm vi được truy xuất đến phương thức này là trên toàn bộ project. Điều này sẽ được thảo luận kỹ hơn trong các bài tiếp theo về lập trình hướng đối tượng.
Từ khóa thứ hai cho biết kiểu dữ liệu của kết quả được trả về sau khi thực thi phương thức. Ở đây chúng ta sử dụng từ khóa void. Từ khóa này cho biết phương thức này không trả về kết quả mà chỉ thực hiện các tác vụ bên trong.
Bước 5.
Nội dung đầu tiên bên trong phương thức TinhTong() như sau:
Bước 6.
Nội dung thứ hai bên trong phương thức TinhTong() như sau:
Bước 7.
Nội dung thứ ba bên trong phương thức TinhTong() như sau:
Ở đây chúng ta có một số điểm cần chú ý:
Thứ nhất, câu lệnh điều kiện và rẽ nhánh.
Câu lệnh điều kiện thứ nhất là if có cấu trúc cú pháp như sau:
if (điều_kiện_1) { // Thực thi công việc nếu điều_kiện_1 là đúng } else if (điều_kiện_2) { // Thực thi công việc nếu điều_kiện_2 là đúng } else { // Thực thi công việc nếu cả điều_kiện_1 và điều_kiện_2 đều sai }
Chú ý rằng tùy trường hợp chúng ta mới cần đến rẽ nhánh else if hoặc else.
Câu lệnh điều khiển thứ hai là switch có cấu trúc cú pháp như sau:
switch(biểu_thức) { case giá_trị_1: // thực thi công việc nếu giá trị của biểu_thức trùng với giá_trị_1 break; case giá_trị_2: // thực thi công việc nếu giá trị của biểu_thức trùng với giá_trị_2 break; default: // thực thi công việc nếu giá trị của biểu_thức khác với các giá trị bên trên }
Chúng ta có một số chú ý ở đây:
Từ khóa break thực hiện thoát khỏi một đoạn chương trình bên trong cặp {} hoặc một vòng lặp.
Từ khóa default được sử dụng tùy trường hợp cần thiết.
Thứ hai, một số toán tử cơ bản.
Chúng ta có thể tham khảo một số toán tử cơ bản trong C# như sau:
Toán tử +. Thực hiện phép cộng: x + y.
Toán tử –. Thực hiện phép trừ: x – y.
Toán tử *. Thực hiện phép nhân: x * y.
Toán tử /. Thực hiện phép chia: x / y.
Toán tử %. Thực hiện phép chia lấy số dư: x % y.
Toán tử ++. Thực hiện phép cộng thêm 1 vào số: x ++.
Toán tử --. Thực hiện phép trừ đi 1 vào số: x --.
Bước 8.
Nội dung thứ tư bên trong phương thức TinhTong() như sau:
Bước 9.
Chúng ta thực thi phương thức TinhTong() trong class MainClass.cs như sau:
Xây dựng phương thức có trả về kết quả
Bước 1.
Đối với phương thức TinhTong() có trả về kết quả, chúng ta có một số chú ý như sau:
Chúng ta thay thế từ khóa void bằng kiểu dữ liệu của kết quả được trả về. Ở đây do chúng ta thực hiện tính tổng các số tự nhiên nên kiểu dữ liệu của kết quả được trả về là int.
Chúng ta có thể cung cấp tham số cho phương thức này. Ở đây chúng ta cung cấp 02 tham số là số lượng phần tử n và mảng int[] tapHop để thực hiện việc tính tổng các số tự nhiên.
Do là có trả về kết quả nên ở câu lệnh cuối chúng ta sử dụng từ khóa return. Ở đây chúng ta thực hiện return tong.
Bước 2.
Trong phương thức main() của class MainClass.cs, chúng ta thực hiện một số nội dung trước khi thực thi phương thức TinhTong().
Chúng ta chú ý rằng nên định nghĩa một biến để lưu giá trị được trả về của phương thức TinhTong().
Bước 3.
Chúng ta thực thi toàn bộ project để thử nghiệm những đoạn mã nguồn C# được xây dựng bên trên:
Thực hiện Debug để kiểm tra các dòng lệnh và bắt lỗi trong MonoDevelop
Bước 1.
Chúng ta để con trỏ chuột tại dòng lệnh muốn bắt đầu debug.
Chúng ta lựa chọn chức năng Run → New Breakpoint … trên thanh Toolbars.
Chúng ta cũng nhận thấy trên menu Run có những chức năng cơ bản để debug:
Chức năng Step Into với phím F11. Thực hiện lần lượt chuyển đến phương thức gặp phải tại dòng lệnh đang được debug.
Chức năng Step Over với phím F10. Thực thi dòng lệnh hiện tại và chuyển tiếp đến dòng lệnh tiếp theo bên dưới.
Bước 2.
Màn hình Create a Breakpoint hiện ra.
Chúng ta giữ nguyên các thông tin mặc định.
Chúng ta lựa chọn nút Create để thực hiện.
Bước 3.
Chúng ta nhận thấy xuất hiện một chấm nhỏ màu đỏ bên trái và dòng lệnh đặt con trỏ chuột đã được tô đậm màu hồng.
Bước 4.
Chúng ta lựa chọn nút mũi tên ở góc trái trên thanh Toolbars để thực hiện debug.
Project sẽ được thực thi cho đến dòng lệnh được đặt dấu chấm đỏ debug.
Bước 5.
Màn hình giao diện chính cho tác vụ debug.
Bước 6.
Chúng ta thực hiện chức năng Step Over với phím F10 tại một số dòng lệnh liên tiếp.
Chúng ta thử dừng lại tại dòng lệnh:
Console.WriteLine(tapHop[i] + “ ”);
Chúng ta chú ý tab Locals trong phần màn hình bên dưới.
Giá trị của các biến được định nghĩa trước dòng lệnh hiện tại đã được hiển thị chi tiết.
Tổng kết
Trong bài này, chúng ta đã cùng nhau tìm hiểu một số kỹ thuật lập trình cơ bản trong C# đồng thời tìm hiểu một số chức năng cần thiết trong MonoDevelop.
Hy vọng rằng chúng ta có thể áp dụng phù hợp những kỹ thuật và chức năng này cho những bài tiếp theo.
Trong chuỗi các bài học về kỹ thuật lập trình Csharp cơ bản qua các ví dụ, chúng ta sẽ cùng nhau tìm hiểu những kỹ thuật lập trình cơ bản nhất mà có thể áp dụng ngay để xây dựng các chương trình ứng dụng thực tế.
Những kỹ thuật được trình bày sẽ mang tính phổ quát và độc lập ngôn ngữ lập trình. Điều đó có nghĩa rằng chúng ta có thể áp dụng các kỹ thuật này đối với các ngôn ngữ khác như PHP / Java / Python.
Đề bài
Yêu cầu 1: Thiết lập một tập hợp gồm một số lượng nhất định các số tự nhiên ngẫu nhiên.
Yêu cầu 2: Tính tổng các số chẵn trong tập hợp này.
Yêu cầu 3: Hiển thị các số này và tổng ra màn hình Console.
Phân tích và lập trình Yêu cầu 1
Phân tích
Để thực hiện Yêu cầu 1, chúng ta xem xét một số tác vụ nhỏ sau:
Tác vụ 1. Xác định một số lượng cố định.
Tác vụ 2. Thiết lập một tập hợp với số lượng phần tử được xác định bên trên.
Tác vụ 3. Xác định giá trị số tự nhiên cho từng phần tử.
Như vậy chúng ta sẽ cùng tìm hiểu những kỹ thuật lập trình sau để thực hiện lần lượt các tác vụ trên:
Kỹ thuật 1. Các kiểu dữ liệu số nguyên cơ bản trong Csharp.
Kỹ thuật 2. Khai báo biến và gán giá trị.
Kỹ thuật 3. Kiểu dữ liệu về tập hợp: mảng.
Kỹ thuật 4. Sử dụng thư viện toán học cơ bản trong dotNET Core SDK.
Kỹ thuật 5. Kỹ thuật thực hiện vòng lặp để duyệt các phần tử trong tập hợp.
Lập trình với ngôn ngữ Csharp
Thực hiện Tác vụ 1 – Xác định một số lượng cố định
Chúng ta có thể thực hiện Tác vụ 1 với chuỗi lệnh sau:
int n = 10;
Những điểm cơ bản cần chú ý với chuỗi lệnh trên:
Thứ nhất, cú pháp cho việc định nghĩa một biến và gán giá trị.
Theo quy định trong Csharp, tất cả các biến phải được định nghĩa trước khi có thể được sử dụng.
Cú pháp cơ bản cho việc định nghĩa một biến như sau:
Theo Yêu cầu 1, số lượng phần tử của một tập hợp phải là một số tự nhiên.
Csharp cung cấp cho chúng ta một số kiểu dữ liệu số tự nhiên tương ứng với phạm vi khác nhau:
Kiểu dữ liệu byte. Đây là kiểu dữ liệu không dấu 8-bit có phạm vi số từ 0 đến 255.
Kiểu dữ liệu sbyte. Đây là kiểu dữ liệu có dấu 8-bit có phạm vi số từ -128 đến 127.
Kiểu dữ liệu ushort. Đây là kiểu dữ liệu không dấu 16-bit có phạm vi số từ 0 đến 65,535.
Kiểu dữ liệu short. Đây là kiểu dữ liệu có dấu 16-bit có phạm vi số từ –32,768 đến 32,767.
Kiểu dữ liệu int. Đây là kiểu dữ liệu có dấu 32-bit có phạm vi số từ –2,147,483,648 đến 2,147,483,647.
Kiểu dữ liệu uint. Đây là kiểu dữ liệu không dấu 32-bit có phạm vi số từ 0 đến 4,294,967,295.
Kiểu dữ liệu long. Đây là kiểu dữ liệu có dấu 64-bit có phạm vi số rất lớn so với kiểu int.
Kiểu dữ liệu ulong. Đây là kiểu dữ liệu không dấu 64-bit có phạm vi số rất lớn so với kiểu uint.
Trong các chương trình ứng dụng thông thường, chúng ta chỉ cần sử dụng kiểu dữ liệu int là đủ.
Thứ ba, gán giá trị cho biến.
Chúng ta có thể gán giá trị cho biến ngay khi định nghĩa giống như chuỗi lệnh trên.
Chúng ta cũng có thể định nghĩa biến trước rồi gán giá trị sau:
int n; n = 10;
Theo nguyên tắc chung, chúng ta nên đặt tên biến có một ý nghĩa cụ thể phù hợp mục tiêu sử dụng.
Tên của biến có thể bao gồm nhiều ký tự viết liền nhau và nên bắt đầu bằng một ký tự in thường.
Ví dụ với Yêu cầu 1 trong bài này, chúng ta có thể đặt tên biến là n hoặc soPhanTu.
Thứ tư, xác định số lượng.
Theo Yêu cầu 1, chúng ta có thể xác định trước một số lượng phần tử.
Ví dụ ở đây là n = 10.
Chúng ta cũng có thể xác định một cách ngẫu nhiên một số lượng trong phạm vi nào đó.
Chúng ta thực hiện ý tưởng trên với các chuỗi lệnh sau:
Random rand = new Random(); int n = rand.Next(1000);
Chuỗi lệnh thứ nhất là định nghĩa một thực thể của lớp đối tượng Random. Chúng ta sẽ tìm hiểu kỹ hơn những kiến thức về lớp đối tượng trong các bài sau.
Chuỗi lệnh thứ hai là thực thi phương thức Next() để phát sinh ngẫu nhiên một số tự nhiên trong phạm vi từ 0 đến 999. Chúng ta sẽ tìm hiểu kỹ hơn những kiến thức về phương thức trong các bài sau.
Thực hiện Tác vụ 2 – Thiết lập một tập hợp với số lượng phần tử được xác định
Chúng ta có thể thực hiện Tác vụ 2 với chuỗi lệnh sau:
int[] tapHop = new int[n];
Những điểm cơ bản cần chú ý với chuỗi lệnh trên:
Thứ nhất, cú pháp cho việc định nghĩa mảng một chiều và gán giá trị.
Csharp cung cấp cho chúng ta một kiểu dữ liệu cơ bản để lưu trữ một tập hợp các phần tử: mảng.
Tùy thuộc vào yêu cầu của chương trình ứng dụng, chúng ta có thể định nghĩa mảng một chiều hoặc mảng nhiều chiều.
Theo Yêu cầu 1, chúng ta định nghĩa mảng một chiều.
Cú pháp cơ bản cho việc định nghĩa một mảng một chiều như sau:
kiểu_dữ_liệu[] tên_mảng = new kiểu_dữ_liệu[số_lượng];
Chú ý rằng toán tử đặc biệt new giúp khởi tạo trong bộ nhớ một khoảng để lưu trữ mảng một chiều.
Chúng ta sẽ tìm hiểu kỹ hơn những kiến thức về các toán tử trong các bài sau.
Thứ hai, gán giá trị.
Chúng ta có thể gán giá trị cho mảng ngay khi định nghĩa giống như chuỗi lệnh trên.
Chúng ta cũng có thể định nghĩa mảng trước rồi gán giá trị sau:
int[] tapHop; tapHop = new int[số_lượng];
Thực hiện Tác vụ 3 – Xác định giá trị số tự nhiên cho từng phần tử
Những điểm cần chú ý khi thực hiện Tác vụ 3:
Thứ nhất, truy xuất từng phần tử trong mảng.
Theo quy định trong Csharp, các phần tử trong mảng được bắt đầu từ vị trí 0 đến số_lượng – 1.
Như vậy, để truy xuất phần tử thứ i trong mảng, chúng ta sử dụng cú pháp:
tên_mảng[i-1]
Thứ hai, gán giá trị cho từng phần tử trong mảng bằng phương pháp thủ công.
Chúng ta truy xuất từng phần tử trong mảng rồi gán giá trị.
Ví dụ với mảng tapHop[] gồm có 10 phần tử là các số tự nhiên. Chúng ta thực hiện gán giá trị như sau:
Thứ ba, gán giá trị cho từng phần tử trong mảng bằng phương pháp tự động với kỹ thuật lặp for.
Cú pháp cơ bản cho việc truy xuất các phần tử trong một mảng một chiều với kỹ thuật lặp for như sau:
for (khởi_tạo_biến_truy_xuất; điều_kiện_lặp; bước_lặp) { // thực hiện công việc }
Vòng lặp for hoạt động như sau:
Khi vòng lặp đầu tiên bắt đầu, phần khởi tạo của vòng lặp được thực thi. Nói chung, đây là một biểu thức đặt giá trị của biến điều khiển vòng lặp, hoạt động như một bộ đếm điều khiển vòng lặp. Điều quan trọng là phải hiểu rằng biểu thức khởi tạo chỉ được thực hiện một lần.
Tiếp theo, điều kiện được đánh giá. Đây phải là một biểu thức Boolean. Nó thường kiểm tra biến điều khiển vòng lặp dựa trên giá trị đích. Nếu biểu thức này là đúng, thì phần thân của vòng lặp được thực thi. Nếu nó sai, vòng lặp chấm dứt.
Tiếp theo, phần lặp của vòng lặp được thực thi. Đây thường là một biểu thức làm tăng hoặc giảm biến điều khiển vòng lặp. Vòng lặp sau đó lặp lại, đầu tiên đánh giá biểu thức điều kiện, sau đó thực hiện phần thân của vòng lặp và sau đó thực hiện biểu thức lặp với mỗi lần truyền. Quá trình này lặp lại cho đến khi biểu thức kiểm soát là sai.
Ví dụ với mảng tapHop[] gồm có 10 phần tử là các số tự nhiên. Chúng ta thực hiện gán giá trị như sau:
for (int i = 0; i < n; i++) { tapHop[i] = rand.nextInt(100); }
Thứ tư, gán giá trị cho từng phần tử trong mảng bằng phương pháp tự động với kỹ thuật lặp while.
Vòng lặp while là câu lệnh vòng lặp cơ bản.
Nó lặp lại một câu lệnh hoặc khối trong khi biểu thức kiểm soát của nó là đúng. Điều kiện có thể là bất kỳ biểu thức Boolean nào.
Phần thân của vòng lặp sẽ được thực thi miễn là biểu thức điều kiện là đúng.
Khi điều kiện trở thành sai, điều khiển chuyển sang dòng mã tiếp theo ngay sau vòng lặp.
Ví dụ với mảng tapHop[] gồm có 10 phần tử là các số tự nhiên. Chúng ta thực hiện gán giá trị như sau:
int i = 0; while (i < n) { tapHop[i] = rand.nextInt(100); i = i + 1; }
Tổng kết
Trong bài này, chúng ta đã cùng nhau tìm hiểu một số những kỹ thuật lập trình cơ bản đầu tiên trong ngôn ngữ Csharp.
Trong những bài tiếp theo, chúng ta sẽ tiếp tục tìm hiểu những kỹ thuật lập trình cơ bản khác để hoàn thành bài toán đặt ra ban đầu.