Giáo trình Lập trình C# 1 - Trình độ: Cao đẳng - Trường Cao đẳng cơ giới Ninh Bình

doc 124 trang Gia Huy 16/05/2022 1950
Bạn đang xem 20 trang mẫu của tài liệu "Giáo trình Lập trình C# 1 - Trình độ: Cao đẳng - Trường Cao đẳng cơ giới Ninh Bình", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên

Tài liệu đính kèm:

  • docgiao_trinh_lap_trinh_c_1_trinh_do_cao_dang_truong_cao_dang_c.doc

Nội dung text: Giáo trình Lập trình C# 1 - Trình độ: Cao đẳng - Trường Cao đẳng cơ giới Ninh Bình

  1. BỘ NÔNG NGHIỆP VÀ PHÁT TRIỂN NÔNG THÔN TRƯỜNG CAO ĐẲNG CƠ GIỚI NINH BÌNH GIÁO TRÌNH MÔ ĐUN: LẬP TRÌNH C# 1 NGHỀ: LẬP TRÌNH MÁY TÍNH TRÌNH ĐỘ: CAO ĐẲNG Ban hành kèm theo Quyết định số: /QĐ-TCĐCGNB ngày .tháng .năm 2017 của Trường Cao đẳng Cơ giới Ninh Bình Tam Điệp, năm 2017 1
  2. TUYÊN BỐ BẢN QUYỀN Tài liệu này thuộc loại sách giáo trình nên các nguồn thông tin có thể được phép dùng nguyên bản hoặc trích dùng cho các mục đích về đào tạo và tham khảo. Mọi mục đích khác mang tính lệch lạc hoặc sử dụng với mục đích kinh doanh thiếu lành mạnh sẽ bị nghiêm cấm. 2
  3. LỜI GIỚI THIỆU Trong hệ thống kiến thức chuyên ngành trang bị cho sinh viên nghề Lập trình máy tính, mô đun góp phần cung cấp những nội dung liên quan đến ngôn ngữ lập trình C#. Các nội dung chính được trình bày trong tài liệu này gồm các bài: Bài 1: Microsoft .NET Bài 2: Ngôn ngữ C# Bài 3: Cơ bản về C# Bài 4: Xây dựng lớp – Đối tượng Bài 5: Kế thừa – Đa hình Bài 6: Nạp chồng toán tử Bài 7: Mảng, chỉ mục và tập hợp Bài 8: Xử lý chuỗi Mặc dầu có rất nhiều cố gắng, nhưng không tránh khỏi những khiếm khuyết, rất mong nhận được sự đóng góp ý kiến của độc giả để giáo trình được hoàn thiện hơn. Ninh Bình, ngày tháng năm 2017 THAM GIA BIÊN SOẠN 1. Chủ biên – CN Phạm Thị Thoa 2. Th.S Nguyễn Xuân Khôi 3. Th.S Nguyễn Anh Văn 3
  4. MỤC LỤC TRANG Bài 1. Microsoft .NET 6 1. Microsoft .NET 7 2. Biên dịch và MSIL 8 Bài 2. Ngôn ngữ C# 11 1. Tại sao phải sử dụng ngôn ngữ C# 12 2. Ngôn ngữ C# với ngôn ngữ khác 14 3. Các bước chuẩn bị cho chương trình 14 4. Chương trình C# đơn giản 15 Bài 3. Cơ bản về C# Error! Bookmark not defined. 1.Kiểu dữ liệu 20 2. Biến và hằng 22 3. Biểu thức 25 4. Khoảng trắng 26 5. Câu lệnh 26 6. Toán tử 39 7. Namespace 42 8. Các chỉ dẫn biên dịch 43 Bài 4. Xây dựng lớp – Đối tượng Error! Bookmark not defined. 1. Tạo lớp và đối tượng 46 2. Sử dụng các thành viên static 52 3. Hủy đối tượng 55 4. Truyền tham số và nạp chồng phương thức 57 5. Đóng gói dữ liệu với thuộc tính 63 Bài 5. Kế thừa – Đa hình Error! Bookmark not defined. 1. Tạo lớp kế thừa 69 2. Khai thác tính đa hình 72 3. Tạo lớp trừu tượng 76 4. Tạo lớp lồng nhau 79 Bài 6. Nạp chồng toán tử Error! Bookmark not defined. 1. Nạp chồng toán tử toán học 83 2. Nạp chồng toán tử quan hệ so sánh 87 Bài 7. Mảng, chỉ mục và tập hợp Error! Bookmark not defined. 4
  5. 1. Xây dựng và xử lý mảng 93 2. Xây dựng và xử lý bộ chỉ mục 97 3. Tạo giao diện tập hợp 101 Bài 8. Xử lý chuỗi Error! Bookmark not defined. 1. Tạo một chuỗi 111 2. Tạo chuỗi dùng phương thức ToString 114 3. Thao tác trên chuỗi 115 4. Tìm một chuỗi con 119 5. Chia chuỗi 121 5
  6. GIÁO TRÌNH MÔ ĐUN Tên mô đun: Lập trình C# 1 Mã số mô đun: MĐ20 Vị trí, tính chất, ý nghĩa và vai trò của mô đun: - Vị trí: Đây là mô đun chứa đựng kiến thức nền tảng về ngôn ngữ lập trình C#, là mô đun hỗ trợ cho hai mô đun lập trình Windows 2 và lập trình Windows 3. - Tính chất. Mô đun này yêu cầu đã học qua các kiến thức về lập trình hướng đối tượng, cấu trúc dữ liệu. - Ý nghĩa và vai trò của đun: Mục tiêu của mô đun: - Kiến thức: + Trình bày được các kiến thức về nền tảng Microsoft .NET; + Trình bày được các kiến thức và kỹ năng về lập trình hướng đối tượng trên C#; + Trình bày được cú pháp các lệnh cơ bản trong C#; + Trình bày được các bước xây dựng lớp đối tượng; + Mô tả được các bước nạp chồng hàm, chồng toán tử; + Trình bày các kiến thức cơ bản về mảng, chuỗi. - Kỹ năng: + Sử dụng thành thạo các toán tử; + Sử dụng được các chỉ dẫn biên dịch; + Sử dụng thành thạo các cấu trúc điều khiển; + Xây dựng được lớp, xây dựng lớp có chồng toán tử; + Sử dụng được các lớp cơ sở của NET. + Khai báo và thao tác được với mảng và chuỗi; - Năng lực tự chủ và trách nhiệm: Rèn luyện tính cẩn thận, chính xác, đảm bảo an toàn cho người và trang thiết bị. Nội dung của môn học/mô đun: Bài 1. Microsoft .NET Mã bài: MĐ20_B01 Giới thiệu : Trong bài này chúng ta sẽ nghiên cứu khái quát về Microsoft.NET, biên dịch và ngôn ngữ C#. 6
  7. Mục tiêu : - Trình bày được nền tảng Microsoft .NET, trình biên dịch và MSIL, lý do và lịch sử về sự ra đời của ngôn ngữ C#; - Mô tả được khái quát về ngôn ngữ C#; - Đảm bảo an toàn cho người và thiết bị. 1. Microsoft .NET Microsoft .NET gồm 2 phần chính : Framework và Integrated Development Environment (IDE). Framework cung cấp những gì cần thiết và căn bản, chữ Framework có nghĩa là khung hay khung cảnh trong đó ta dùng những hạ tầng cơ sở theo một qui ước nhất định để công việc được trôi chảy. IDE thì cung cấp một môi trường giúp chúng ta triển khai dễ dàng, và nhanh chóng các ứng dụng dựa trên nền tảng .NET. Nếu không có IDE chúng ta cũng có thể dùng một trình soạn thảo ví như Notepad hay bất cứ trình soạn thảo văn bản nào và sử dụng command line để biên dịch và thực thi, tuy nhiên việc này mất nhiều thời gian. Tốt nhất là chúng ta dùng IDE phát triển các ứng dụng, và cũng là cách dễ sử dụng nhất. Tính năng của Micosoft.NET ➢ Một mô hình lập trình cho phép nhà phát triển xây dựng các ứng dụng dịch vụ web và ứng dụng client với Extensible Markup Language (XML). ➢ Tập hợp dịch vụ XML Web, như Microsoft .NET My Services cho phép nhà phát triển đơn giản và tích hợp người dùng kinh nghiệm. ➢ Cung cấp các server phục vụ bao gồm: Windows 2000, SQL Server, và BizTalk Server, tất cả điều tích hợp, hoạt động, và quản lý các dịch vụ XML Web và các ứng dụng. ➢ Các phần mềm client như Windows XP và Windows CE giúp người phát triển phân phối sâu và thuyết phục người dùng kinh nghiệm thông qua các dòng thiết bị. ➢ Nhiều công cụ hỗ trợ như Visual Studio .NET, để phát triển các dịch vụ Web XML, ứng dụng trên nền Windows hay nền web một cách dể dàng và hiệu quả. Kiến trúc .NET Framework .NET Framework là một platform mới làm đơn giản việc phát triển ứng dụng trong môi trường phân tán của Internet. .NET Framework được thiết kế 7
  8. đầy đủ để đáp ứng theo quan điểm sau:  Để cung cấp một môi trường lập trình hướng đối tượng vững chắc, trong đó mã nguồn đối tượng được lưu trữ và thực thi một cách cục bộ. Thực thi cục bộ nhưng được phân tán trên Internet, hoặc thực thi từ xa.  Để cung cấp một môi trường thực thi mã nguồn mà tối thiểu được việc đóng gói phần mềm và sự tranh chấp về phiên bản.  Để cung cấp một môi trường thực thi mã nguồn mà đảm bảo việc thực thi an toàn mã nguồn, bao gồm cả việc mã nguồn được tạo bởi hãng thứ ba hay bất cứ hãng nào mà tuân thủ theo kiến trúc .NET.  Để cung cấp một môi trường thực thi mã nguồn mà loại bỏ được những lỗi thực hiện các script hay môi trường thông dịch.  Để làm cho những người phát triển có kinh nghiệm vững chắc có thể nắm vững nhiều kiểu ứng dụng khác nhau. Như là từ những ứng dụng trên nền Windows đến những ứng dụng dựa trên web.  Để xây dựng tất cả các thông tin dựa triên tiêu chuẩn công nghiệp để đảm bảo rằng mã nguồn trên .NET có thể tích hợp với bất cứ mã nguồn khác. .NET Framework có hai thành phần chính: Common Language Runtime (CLR) và thư viện lớp Common Language Runtime (CLR): thực hiện quản lý bộ nhớ, quản lý thực thi tiểu trình, thực thi mã nguồn, xác nhận mã nguồn an toàn, biên bịch và các dịch vụ hệ thống khác. Những đặc tính trên là nền tảng cơ bản cho những mã nguồn được quản lý chạy trên CLR. Thư viện lớp .NET Framework là một tập hợp những kiểu dữ liệu được dùng lại và được kết hợp chặt chẽ với Common Language Runtime. Thư viện lớp là hướng đối tượng cung cấp những kiểu dữ liệu mà mã nguồn được quản lý của chúng ta có thể dẫn xuất 2. Biên dịch và MSIL Trong .NET Framework, chương trình không được biên dịch vào các tập tin thực thi mà thay vào đó chúng được biên dịch vào những tập tin trung gian gọi là Microsoft Intermediate Language (MSIL). Những tập tin MSIL được tạo ra từ C# cũng tương tự như các tập tin MSIL được tạo ra từ những ngôn ngữ khác của .NET, platform ở đây không cần biết ngôn ngữ của mã nguồn. Điều quan trọng chính yếu của CLR là chung (common), cùng một runtime hỗ trợ phát triển trong C# cũng như trong VB.NET. 8
  9. Mã nguồn C# được biên dịch vào MSIL khi chúng ta build project. Mã MSIL này được lưu vào trong một tập tin trên đĩa. Khi chúng ta chạy chương trình, thì MSIL được biên dịch một lần nữa, sử dụng trình biên dịch Just-In- Time (JIT). Kết quả là mã máy được thực thi bởi bộ xử lý của máy. Trình biên dịch JIT tiêu chuẩn thì thực hiện theo yêu cầu. Khi một phương thức được gọi, trình biên dịch JIT phân tích MSIL và tạo ra sản phẩm mã máy có hiệu quả cao, mã này có thể chạy rất nhanh. Trình biên dịch JIT đủ thông minh để nhận ra khi một mã đã được biên dịch, do vậy khi ứng dụng chạy thì việc biên dịch chỉ xảy ra khi cần thiết, tức là chỉ biên dịch mã MSIL chưa biên dịch ra mã máy. Khi đó một ứng dụng .NET thực hiện, chúng có xu hướng là chạy nhanh và nhanh hơn nữa, cũng như là những mã nguồn được biên dịch rồi thì được dùng lại. Do tất cả các ngôn ngữ .NET Framework cùng tạo ra sản phẩm MSIL giống nhau, nên kết quả là một đối tượng được tạo ra từ ngôn ngữ này có thể được truy cập hay được dẫn xuất từ một đối tượng của ngôn ngữ khác trong .NET 3. Ngôn ngữ C# Ngôn ngữ C# khá đơn giản, chỉ khoảng 80 từ khóa và hơn mười mấy kiểu dữ liệu được xây dựng sẵn. Tuy nhiên, ngôn ngữ C# có ý nghĩa cao khi nó thực thi những khái niệm lập trình hiện đại. C# bao gồm tất cả những hỗ trợ cho cấu trúc, thành phần component, lập trình hướng đối tượng. C# được xây dựng trên nền tảng của hai ngôn ngữ mạnh nhất là C++ và Java. Ngôn ngữ C# được phát triển bởi đội ngũ kỹ sư của Microsoft, trong đó người dẫn đầu là Anders Hejlsberg và Scott Wiltamuth. Ngôn ngữ C# chứa những từ khóa cho việc khai báo những kiểu lớp đối tượng mới và những phương thức hay thuộc tính của lớp, và cho việc thực thi đóng gói, kế thừa, và đa hình, ba thuộc tính cơ bản của bất cứ ngôn ngữ lập trình hướng đối tượng. Trong ngôn ngữ C# mọi thứ liên quan đến khai báo lớp điều được tìm thấy trong phần khai báo của nó. Định nghĩa một lớp trong ngôn ngữ C# không đòi hỏi phải chia ra tập tin header và tập tin nguồn giống như trong ngôn ngữ C++. Hơn thế nữa, ngôn ngữ C# hỗ trợ kiểu XML, cho phép chèn các tag XML để phát sinh tự động các document cho lớp. 9
  10. C# cũng hỗ trợ giao diện interface, nó được xem như một cam kết với một lớp cho những dịch vụ mà giao diện quy định. Trong ngôn ngữ C#, một lớp chỉ có thể kế thừa từ duy nhất một lớp cha, tức là không cho đa kế thừa như trong ngôn ngữ C++, tuy nhiên một lớp có thể thực thi nhiều giao diện. Khi một lớp thực thi một giao diện thì nó sẽ hứa là nó sẽ cung cấp chức năng thực thi giao diện. Trong ngôn ngữ C#, những cấu trúc cũng được hỗ trợ, nhưng khái niệm về ngữ nghĩa của nó thay đổi khác với C++. Trong C#, một cấu trúc được giới hạn, là kiểu dữ liệu nhỏ gọn, và khi tạo thể hiện thì nó yêu cầu ít hơn về hệ điều hành và bộ nhớ so với một lớp. Một cấu trúc thì không thể kế thừa từ một lớp hay được kế thừa nhưng một cấu trúc có thể thực thi một giao diện. Ngôn ngữ C# cung cấp những đặc tính hướng thành phần (component- oriented), như là những thuộc tính, những sự kiện. Lập trình hướng thành phần được hỗ trợ bởi CLR cho phép lưu trữ metadata với mã nguồn cho một lớp. Metadata mô tả cho một lớp, bao gồm những phương thức và những thuộc tính của nó, cũng như những sự bảo mật cần thiết và những thuộc tính khác. 10
  11. BÀI 2. NGÔN NGỮ C# Mã bài: MĐ20_B02 Giới thiệu: Trong bài này chúng ta sẽ nghiên cứu khái quát về ngôn ngữ C#: tại sao phải dùng C#, các bước để chuẩn bị cho chương trình và giới thiệu cho các bạn biết sơ qua 1 chương trinh C# đơn giản. Mục tiêu: - Mô tả được các đặc điểm nổi bật của ngôn ngữ C#; - Trình bày được các bước để viết một chương trình trong C#; - Viết được chương trình C# đơn giản; - Đảm bảo an toàn cho người và thiết bị. 1. Tại sao phải sử dụng ngôn ngữ C# Một số mục đích khi xây dựng ngôn ngữ C#: ➢C# là ngôn ngữ đơn giản ➢C# là ngôn ngữ hiện đại ➢C# là ngôn ngữ hướng đối tượng ➢C# là ngôn ngữ mạnh mẽ và mềm dẻo ➢C# là ngôn ngữ có ít từ khóa ➢C# là ngôn ngữ hướng module ➢C# sẽ trở nên phổ biến a. C# là ngôn ngữ đơn giản - C# loại bỏ một vài sự phức tạp và rối rắm của những ngôn ngữ như Java và c++, bao gồm việc loại bỏ những macro, những template, đa kế thừa, và lớp cơ sở ảo (virtual base class). - Ngôn ngữ C# đơn giản vì nó dựa trên nền tảng C và C++. Nếu chúng ta thân thiện với C và C++ hoậc thậm chí là Java, chúng ta sẽ thấy C# khá giống về diện mạo, cú pháp, biểu thức, toán tử và những chức năng khác được lấy trực tiếp từ ngôn ngữ C và C++, nhưng nó đã được cải tiến để làm cho ngôn ngữ đơn giản hơn b. C# là ngôn ngữ hiện đại Những đặc tính của C#: xử lý ngoại lệ, thu gom bộ nhớ tự động, những kiểu dữ liệu mở rộng, và bảo mật mã nguồn. Đây những đặc tính được mong đợi trong một ngôn ngữ hiện đại. c. C# là ngôn ngữ hướng đối tượng Những đặc điểm chính của ngôn ngữ hướng đối tượng (Object- 12
  12. oriented language) là sự đóng gói (encapsulation), sự kế thừa (inheritance), và đa hình (polymorphism). C# hỗ trợ tất cả những đặc tính trên. d. C# là ngôn ngữ mạnh mẽ và cũng mềm dẻo Với ngôn ngữ C# chúng ta chỉ bị giới hạn ở chính bởi bản thân hay là trí tưởng tượng của chúng ta. Ngôn ngữ này không đặt những ràng buộc lên những việc có thể làm. C# được sử dụng cho nhiều các dự án khác nhau như là tạo ra ứng dụng xử lý văn bản, ứng dụng đồ họa, bản tính, hay thậm chí những trình biên dịch cho các ngôn ngữ khác. e. C# là ngôn ngữ ít từ khóa C# là ngôn ngữ sử dụng giới hạn những từ khóa. Bảng sau liệt kê các từ khóa của ngôn ngữ C#. abstr defaul foreac Objec sizeof unsaf actAs tdelega hgoto tOpera stacka eushor Base te do if torOut llocstatic tusing Bool doubl implic Overri string virtu Brea e else it in deParam struct alvolat kByte enum int sPrivat switch ilevoid Case event interfa eProtec this while Catc explic ceintern tedPublic throw hChar itextern al is Reado true chec false lock nlyRef try kedClas finally long Retur typeof sCons fixed names nSbyte uint tconti float pacenew Seale ulong nuedeci for null dShort unche mal cked f. C# là ngôn ngữ hướng module Mã nguồn C# có thể được viết trong những phần được gọi là những lớp, những lớp này chứa các phương thức thành viên của nó. Những lớp và những phương thức có thể được sử dụng lại trong ứng dụng hay các chương trình khác. 13
  13. g. C# là một ngôn ngữ phổ biến C# là ngôn ngữ đứng thứ 5 trong biểu đồ khảo sát 15 ngôn ngữ sử dụng phổ biến nhất năm 2014. 2. Ngôn ngữ C# với ngôn ngữ khác Microsoft nói rằng C# mang đến sức mạnh của ngôn ngữ C++ với sự dễ dàng của ngôn ngữ Visual Basic. Có thể nó không dễ như Visual Basic, nhưng với phiên bản Visual Basic.NET (Version 7) thì ngang nhau. Bởi vì chúng được viết lại từ một nền tảng. Chúng ta có thể viết nhiều chương trình với ít mã nguồn hơn nếu dùng C#. Một điều quan trọng khác với C++ là mã nguồn C# không đòi hỏi phải có tập tin header. Tất cả mã nguồn được viết trong khai báo một lớp. Như đã nói ở bên trên. .NET runtime trong C# thực hiện việc thu gom bộ nhớ tự động. Do điều này nên việc sử dụng con trỏ trong C# ít quan trọng hơn trong C++. Những con trỏ cũng có thể được sử dụng trong C#, khi đó những đoạn mã nguồn này sẽ được đánh dấu là không an toàn (unsafe code). C# cũng từ bỏ ý tưởng đa kế thừa như trong C++. Và sự khác nhau khác là C# đưa thêm thuộc tính vào trong một lớp giống như trong Visual Basic. Và những thành viên của lớp được gọi duy nhất bằng toán tử “.” khác với C++ có nhiều cách gọi trong các tình huống khác nhau. Điểm giống nhau C# và Java là cả hai cùng biên dịch ra mã trung gian: C# biên dịch ra MSIL còn Java biên dịch ra bytecode. Sau đó chúng được thực hiện bằng cách thông dịch hoặc biên dịch just-in-time trong từng máy ảo tương ứng. Sự khác nhau giữ Java và C#: trong ngôn ngữ C# nhiều hỗ trợ được đưa ra để biên dịch mã ngôn ngữ trung gian sang mã máy. C# chứa nhiều kiểu dữ liệu cơ bản hơn Java và cũng cho phép nhiều sự mở rộng với kiểu dữ liệu giá trị. 3. Các bước chuẩn bị cho chương trình ❖ Xác định mục tiêu của chương trình. ❖ Xác định những phương pháp giải quyết vấn đề. ❖ Tạo một chương trình để giải quyết vấn đề. ❖ Thực thi chương trình để xem kết quả. 14
  14. 4. Chương trình C# đơn giản * Lớp, đối tượng và kiểu dữ liệu - Điều cốt lõi của lập trình hướng đối tượng là tạo ra các kiểu mới. Kiểu là một thứ được xem như trừu tượng. - Kiểu được định nghĩa như một dạng vừa có thuộc tính chung (properties) và các hành vi ứng xử (behavior) của nó. - Kiểu trong kiểu trong C# được định nghĩa là một lớp (class), và các thể hiện riêng của từng lớp được gọi là đối tượng (object). - Khai báo lớp trong C# không có dấu ; sau ngoặc } cuối cùng của lớp. Và khácvới lớp trong C/C++ là chia thành 2 phần header và phần định nghĩa. Trong C# , định nghĩa một lớp được gói gọn trong dấu { } sau tên lớp và trong cùng một tập tin. * Phương thức - Phương thức chính là các hàm được định nghĩa trong lớp. - Các phương thức này chỉ ra rằng các hành động mà lớp có thể làm được cùng với cách thức làm hành động đó. - Khi chương trình thực thi, CLR gọi hàm Main() đầu tiên, hàm Main() là đầu vào của chương trình, và mỗi chương trình phải có một hàm Main(). Cấu trúc hàm main: static void Main( ) { } * Chú thích Một chương trình được viết tốt thì cần phải có chú thích các đoạn mã được viết. Các đoạn chú thích này sẽ không được biên dịch và cũng không tham gia vào chương trình. Mục đích chính là làm cho đoạn mã nguồn rõ ràng và dễ hiểu. Một chuỗi chú thích trên một dòng thì bắt đầu bằng ký tự “//” Ví dụ: // Xuat ra man hinh. Ngoài ra C# còn cho phép kiểu chú thích cho một hay nhiều dòng, và ta phải khai báo “/*” ở phần đầu chú thích và kết thúc chú thích là ký tự “*/”. * Ứng dụng Console 15
  15. Ứng dụng này giao tiếp với người dùng thông quan bàn phím và không có giao diện người dùng (UI) * Lớp Console - Đưa dữ liệu ra màn hình chúng ta dùng phương thức Write hoặc WriteLine của lớp Console + Cú pháp: Console.Write(dòng diều khiển[, danh sách đối]); Console.WriteLine(dòng diều khiển[, danh sách đối]); Trong đó: dòng diều khiển: là một hằng xâu ký tự đặt trong hai dấu “ ”, nó bao gồm các loại đối tượng sau: Các ký tự thông thường, các ký tự đặc biệt và các đặc tả có dạng: {i,-j:dt } có thể đặt bất kỳ ở vị trí nào trong xâu với: i là thứ tự của một đối mà ta cần đưa giá trị của chúng ra tại vị trí đặt đặc tả(các đối có thứ tự bắt đầu từ không), j là độ rộng dành cho đối cần đưa ra(nếu j mà lớn hơn độ dài của dữ liệu cần đưa ra thì giá trị đó được căn phải, nếu muốn căn trái thì ta thêm dấu trừ phía trước, còn nếu j mà nhỏ hơn độ dài thực tế của dữ liệu cần đưa ra thì không có gì thay đổi), d là định dạng dữ liệu đưa ra, ví dụ định dạng là C định dạng theo kiểu tiền tệ, N định dạng kiểu số, G định dạng chuẩn , t là số chữ số thập phân(chỉ áp dụng cho số thực) danh sách các đối: các đối có thể là hằng, biến, biểu thức và đặt cách nhau một dấu phẩy + Sự khác nhau giữa Write( ) và WriteLine( ) là: Write( ) sau khi viết dữ liệu ra màn hình thì con trỏ đặt ở cuối dòng còn WriteLine( ) sau khi viết dữ liệu ra màn hình thì con trỏ đặt ở đầu dòng tiếp theo. Để nhập dữ liệu vào từ bàn phím chúng ta dùng phương thức ReadLine có trong lớp Console như sau: Kiểudữliệu Tênbiến; Tênbiến=Kiểudữliệu.Parse(Console.ReadLine()); Thông thường trong qua trình nhập dữ liệu chúng ta thương kết hợp phương thức Write với ReadLine trong lớp Console. Phương thức này trả về dữ liệu kiểu string. Ví dụ: 16
  16. double a; Console.Write("Nhap a="); a = double.Parse(Console.ReadLine()); * Namespace –Không gian tên Namespace cung cấp cho ta cách tổ chức quan hệ giữa các lớp và các kiểu khác nhau. Đây là kĩ thuật cho phép .NET tránh việc các tên lớp, tên biến, tên hàm đụng độ vì trùng tên với nhau giữa các lớp. Để khai báo không gian tên chúng ta sử dụng từ khóa namespace. Đối tượng Console bị hạn chế bởi namespace bằng việc sử dụng mã lệnh: System.Console.WriteLine(); * Toán tử “.”: được sử dụng để truy cập đến phương thức hay dữ liệu trong một lớp Ví dụ: System.Console.WriteLine(“Chao Mung”); * Từ khóa using Để làm cho chương trình gọn hơn, và không cần phải viết từng namespace cho từng đối tượng, C# cung cấp từ khóa là using, sau từ khóa này là một namespace hay subnamespace với mô tả đầy đủ trong cấu trúc phân cấp của nó. Ta có thể dùng dòng lệnh : using System; ở đầu chương trình và khi đó trong chương trình nếu chúng ta có dùng đối tượng Console thì không cần phải viết đầy đủ : System.Console. mà chỉ cần viết Console. thôi. Ví dụ: using System; class ChaoMung { static void Main() { //Xuat ra man hinh chuoi thong bao Console.WriteLine(“Chao Mung”); } } 17
  17. * Trong C# phân biệt chữ hoa chữ thường Trình tự thực hiện - Khởi động chương trình Visual Studio 2010 Start\ All Programs\ Microsoft Visual Studio 2010\ Microsoft Visual Studio 2010 Chọn New Project Chọn Console Application\ Gõ tên project vào mục Name\OK 18
  18. - Gõ lệnh vào hàm Main Biên dịch: Nhấn F6 Chạy chương trình: Nhấn F5 19
  19. BÀI 3. CƠ BẢN VỀ C# Mã bài: MĐ20_B03 Giới thiệu: Trong bài này chúng ta sẽ nghiên cứu về: các kiểu dữ liệu, cách khai báo và sử dụng biến, hằng; cú pháp các lệnh cơ bản trong C#. Mục tiêu: - Hiểu rõ về không gian tên (namespace); - Trình bày được các kiểu dữ liệu cơ bản trong C#; - Trình bày được các cú pháp: khai báo biến, khai báo hằng, các câu lệnh cơ bản trong C#; - Sử dụng thành thạo các kiểu dữ liệu dựng sẵn của C#; - Có kỹ năng tốt về việc sử dụng biến, hằng và các biểu thức; - Sử dụng thành thạo các toán tử; - Dử dụng được các chỉ dẫn biên dịch; - Sử dụng thành thạo các câu lệnh để giải quyết được các bài toán theo yêu cầu; - Rèn luyện tính cẩn thận, đảm bảo an toàn cho người và thiết bị. 1. Kiểu dữ liệu Ngôn ngữ C# đưa ra các kiểu dữ liệu xây dựng sẵn rất hữu dụng, phù hợp với một ngôn ngữ lập trình hiện đại, mỗi kiểu dữ liệu được ánh xạ đến một kiểu dữ liệu được hỗ trợ bởi hệ thống xác nhận ngôn ngữ chung (Common Language Specification: CLS) trong MS.NET. Bảng các kiểu dữ liệu xây dựng sẵn K Số Kiể Mô tả iểu C#B byte1 u .NETByt Số nguyên dương không dấu từ yte c 2 e Ch 0-255 Ký tự Unicode har B 1 ar Bo Giá trị logic true/ false ool s 1 oleanSb Số nguyên có dấu ( từ -128 đến byte s 2 yte Int 127) Số nguyên có dấu giá trị từ - hort 16 32768 đến 32767. u 2 Uịn Số nguyên không dấu 0 – 65.535 short t16 I 4 Int Số C d – v nt 32 nguyên ó ấu 2.147.483.647 à 2.147.483.620 47
  20. Ui 4 Uin Số nguyên không dấu 0 – nt t32 4.294.967.295 fl 4 Sin Kiểu dấu chấm động, giá trị xấp oat gle xỉ từ 3,4E- 38 đến 3,4E+38, với 7 chữ d 8 Do số có nghĩa Kiểu dấu chấm động có độ ouble uble chính xác gấp đôi, giá trị xấp xỉ từ 1,7E-308 đến 1,7E+308, với 15,16 chữ số có nghĩa. D 8 De Có độ chính xác đến 28 con số ecimal cimal và giá trị thập phân, được dùng trong tính toán tài chính, kiểu này đòi hỏi phải có hậu tố “m” hay “M” theo sau L 8 Int giá trị.Kiểu số nguyên có dấu có giá trị ong 64 trong khoảng : -9.223.370.036.854.775.808 đến 9.223.372.036.854.775.807 ul 8 Uin Số nguyên không ong t64 dấu từ 0 đến 0xffffffffffffffff S Kiểu chuỗi tring (được nói kỹ ở chương 8) Kiểu dữ liệu Unicode (char) có một số ký đặc biệt như sau: Ký tự Ý nghĩa \’ Dấu nháy đơn \” Dấu nháy kép \\ Dấu chéo \0 Ký tự null \a Alert \b Backspace \f Sang trang form feed 21
  21. \n Dòng mới \r Đầu dòng \t Tab ngang \v Tab dọc Chuyển đổi các kiểu dữ liệu Những đối tượng của một kiểu dữ liệu này có thể được chuyển sang những đối tượng của một kiểu dữ liệu khác thông qua cơ chế chuyển đổi tường minh hay ngầm định. Ví dụ về chuyển đổi ngầm định (chỉ chuyển đổi kiểu nhỏ sang kiểu rộng hơn) short x = 10; int y = x; // chuyển đổi ngầm định Cú pháp chuyển đổi dữ liệu: Biến=(kiểu) giá trị[biến]; Ví dụ: short x; int y = 500; x = (short) y; 2. Biến và hằng 2.1. Biến Một biến là một vùng lưu trữ với một kiểu dữ liệu. + Khai báo biến: Kiểu_dữ_liệu tên_biến; Ví dụ: int a; + Gán dữ liệu cho biến: Tên_biến = giá_trị; Ví dụ: a=10; Ta cũng có thể gán giá trị cho biến khi khai báo Ví dụ: int a=9; Định danh 22
  22. Định danh là tên mà người lập trình chỉ định cho các kiểu dữ liệu, các phương thức, biến, hằng, hay đối tượng Một định danh phải bắt đầu với một ký tự chữ cái hay dấu gạch dưới, các ký tự còn lại phải là ký tự chữ cái, chữ số, dấu gạch dưới. Trình tự thực hiện - Khởi động chương trình Visual Studio 2010 Chọn Console Application\ Gõ tên project vào mục Name\OK Gõ lệnh vào hàm Main Biên dịch: Nhấn F6 Chạy chương trình: Nhấn F5 2.2. Hằng Hằng cũng là một biến nhưng giá trị của hằng không thay đổi. Cú pháp khai báo hằng = ; Ví dụ: const int DoSoi = 100; 23
  23. Trình tự thực hiện - Khởi động chương trình Visual Studio 2010 Chọn Console Application\ Gõ tên project vào mục Name\OK Gõ lệnh vào hàm Main Biên dịch: Nhấn F6 Chạy chương trình: Nhấn F5 2.3. Kiểu liệt kê - Kiểu liệt kê đơn giản là tập hợp các tên hằng có giá trị không thay đổi (thường được gọi là danh sách liệt kê). - Cú pháp khai báo kiểu liệt kê enum [:kiểu cơ sở] {danh sách các thành phần liệt kê}; Ví dụ: enum NhietDoNuoc 24
  24. { DoDong = 0, DoNguoi = 20, DoAm = 40, DoNong = 60, DoSoi = 100, } - Truy xuất vào từng phần tử: . Trình tự thực hiện • Khởi động chương trình Visual Studio 2010 • Chọn Console Application\ Gõ tên project vào mục Name\OK • Gõ lệnh vào hàm Main •Biên dịch: Nhấn F6 •Chạy chương trình: Nhấn F5 3. Biểu thức Những câu lệnh mà thực hiện việc đánh giá một giá trị gọi là biểu thức. Một phép gán một giá trị cho một biến cũng là một biểu thức: 25
  25. var1 = 24; Trong câu lệnh trên phép đánh giá hay định lượng chính là phép gán có giá trị là 24 cho biến var1. Lưu ý là toán tử gán (‘=’) không phải là toán tử so sánh. Do var1 = 24 là một biểu thức được định giá trị là 24 nên biểu thức này có thể được xem như phần bên phải của một biểu thức gán khác: var2 = var1 = 24; Lệnh này sẽ được thực hiện từ bên phải sang khi đó biến var1 sẽ nhận được giá trị là 24 và tiếp sau đó thì var2 cũng được nhận giá trị là 24. 4. Khoảng trắng Trong ngôn ngữ C#, những khoảng trắng, khoảng tab và các dòng được xem như là khoảng trắng (whitespace). C# sẽ bỏ qua tất cả các khoảng trắng đó, do vậy chúng ta có thể viết như sau: var1=24; hay var1 = 24; và trình biên dịch C# sẽ xem hai câu lệnh trên là hoàn toàn giống nhau. Tuy nhiên, cũng cần lưu ý khi sử dụng khoảng trắng như sau: int x = 24; tương tự như: int x=24; nhưng không giống như: intx=24; //khai báo sai Tuy nhiên lưu ý là khoảng trắng trong một chuỗi sẽ không được bỏ qua. Nếu chúng ta viết: System.WriteLine(“Xin chao!”); mỗi khoảng trắng ở giữa hai chữ “Xin” và “chao” đều được đối xử bình thường như các ký tự khác trong chuỗi. 5. Câu lệnh Mục tiêu: Trình bày được cú pháp các lệnh phân nhánh, các lệnh lặp trong C# Sử dụng được các câu lệnh để giải quyết các bài tập theo yêu cầu. Trong C# một chỉ dẫn lập trình đầy đủ được gọi là câu lệnh. Mỗi câu lệnh phải kết thúc với một dấu chấm phẩy, ví dụ như: int x; // một câu lệnh 26
  26. x = 32; // câu lệnh khác int y =x; // đây cũng là một câu lệnh Phân loại câu lệnh + Lệnh đơn + Lệnh kép: tập các lệnh trong cặp dấu { } + Lệnh phân nhánh không có điều kiện (unconditional branching statement) và phân nhánh có điều kiện (conditional branching statement). + Các lệnh lặp for, while, do 5.1.Phân nhánh không có điều kiện Phân nhánh không có điều kiện có thể tạo ra bằng hai cách: gọi một hàm và dùng từ khoá phân nhánh không điều kiện.  Gọi hàm Khi trình biên dịch xử lý đến tên của một hàm, thì sẽ ngưng thực hiện hàm hiện thời mà bắt đầu phân nhánh dể tạo một gọi hàm mới. Sau khi hàm vừa tạo thực hiện xong và trả về một giá trị thì trình biên dịch sẽ tiếp tục thực hiện dòng lệnh tiếp sau của hàm ban đầu.  Từ khoá phân nhánh không điều kiện Để thực hiện phân nhánh ta gọi một trong các từ khóa sau: goto, break, continue, return, statementthrow. 5.2. Phân nhánh có điều kiện Phân nhánh có điều kiện được tạo bởi các lệnh điều kiện. Các từ khóa của các lệnh này như : if, else, switch 5.2.1. Lệnh if - Cú pháp if (biểu thức điều kiện) Hoạt động: trình biên dịch kiểm tra biểu thức điều kiện, câu lệnh chỉ được thực hiện khi biểu thức điều kiện đúng Ví dụ: int a = 10; int b = 5; if (a > b) Console.WriteLine("{0} lon hon {1}",a,b); Trình tự thực hiện 27
  27. •Khởi động chương trình Visual Studio 2010 •Chọn Console Application\ Gõ tên project vào mục Name\OK • Gõ lệnh vào hàm Main •Biên dịch: Nhấn F6 •Chạy chương trình: Nhấn F5 5.2.2. Lệnh if else - Cú pháp: if (biểu thức điều kiện) [else ] 28
  28. Hoạt động: Trình biên dịch kiểm tra biểu thức điều kiện, Nếu biểu thức điều kiện đúng thì thực hiện Câu lệnh 1 ngược lại thực hiện Câu lệnh 2. - Ví dụ int a = 10; int b = 5; if (a > b) Console.WriteLine("{0} lon hon {1}",a,b); else Console.WriteLine("{0} lon hon {1}", b, a); Trình tự thực hiện •Khởi động chương trình Visual Studio 2010 •Chọn Console Application\ Gõ tên project vào mục Name\OK • Gõ lệnh vào hàm Main •Biên dịch: Nhấn F6 •Chạy chương trình: Nhấn F5 29
  29. 5.2.3. Câu lệnh if lồng nhau Các lệnh điều kiện if có thể lồng nhau để phục vụ cho việc xử lý các câu điều kiện phức tạp. Ví dụ: Căn cứ vào điểm trung bình để xếp loại học lực: Nếu dtb =9 thì xếp loại Xuất sắc double dtb = 8.5; if (dtb < 5) Console.WriteLine("Xep loai: Yeu"); else if (dtb<7) Console.WriteLine("Xep loai: Trung binh"); else if (dtb<8) Console.WriteLine("Xep loai: Kha"); else if(dtb<9) Console.WriteLine("Xep loai: Gioi"); else Console.WriteLine("Xep loai: Xuat sac"); Trình tự thực hiện • Khởi động chương trình Visual Studio 2010 • Chọn Console Application\ Gõ tên project vào mục Name\OK • Gõ lệnh vào hàm Main 30
  30. • Biên dịch: Nhấn F6 • Chạy chương trình: Nhấn F5 5.2.4.Câu lệnh switch Khi có quá nhiều điều kiện để chọn thực hiện thì dùng câu lệnh if sẽ rất rối rắm và dài dòng, C# cung cấp câu lệnh nhảy switch - Cú pháp: switch (biểu thức) { case : [ ] case : [ ] case : [ ] [default: ] } 31
  31. Hoạt động: trình biên dịch sẽ tính giá trị của biển thức, Nếu giá trị của biểu thức bằng giá trị tương ứng của case nào thì câu lệnh thuộc case đó sẽ được thực thi. Sau khi thực thi xong lệnh nếu gặp lệnh break thì sẽ thoát khỏi lệnh switch ngược lại thì các lệnh còn lại sẽ được thực thi. Nếu giá trị biểu thức không bằng giá trị của case nào thì khi đó câu lệnh n+1 sẽ được thực thi. - Ví dụ: Xếp thứ trong 1 tuần Thu=2 thì kết quả là “Thu hai” Thu =3 kết quả là “Thu ba” Nếu thu là một giá trị khác thứ trong tuần thì kết quả là “thu khong ton tai” int thu =6; switch (thu) { case 2: { Console.WriteLine("Thu hai"); break; } case 3: { Console.WriteLine("Thu ba"); break; } case 4: { Console.WriteLine("Thu tu"); break; } case 5: { Console.WriteLine("Thu nam"); break; } case 6: { Console.WriteLine("Thu sau"); break; } case 7: { Console.WriteLine("Thu bay"); break; } case 8: {Console.WriteLine("Thu tam"); break;} default: { Console.WriteLine("Thu khong ton tai"); break; } } - Lệnh break là lệnh nhảy thoát khỏi câu lệnh trong cùng chứa nó. Trình tự thực hiện •Khởi động chương trình Visual Studio 2010 •Chọn Console Application\ Gõ tên project vào mục Name\OK • Gõ lệnh vào hàm Main 32
  32. •Biên dịch: Nhấn F6 •Chạy chương trình: Nhấn F5 5.3. Vòng lặp while Ý nghĩa của vòng lặp while là: “Trong khi điều kiện đúng thì thực hiện các công việc này”. Cú pháp sử dụng vòng lặp while như sau: while (Biểu thức) Biểu thức của vòng lặp while là điều kiện để các lệnh được thực hiện, biểu thức này bắt buộc phải trả về một giá trị kiểu bool là true/false. Nếu có nhiều câu lệnh cần được thực hiện trong vòng lặp while thì phải đặt các lệnh này trong khối lệnh. 33
  33. Ví dụ: Hiển thị các số từ 0 đến 9 int i = 0; while ( i < 10 ) { Console.WriteLine(" i: {0} ",i); i++; } Trình tự thực hiện •Khởi động chương trình Visual Studio 2010 •Chọn Console Application\ Gõ tên project vào mục Name\OK • Gõ lệnh vào hàm Main •Biên dịch: Nhấn F6 •Chạy chương trình: Nhấn F5 34
  34. 5.4. Câu lênh do while - Cú pháp do while (điều kiên) Hoạt động: máy sẽ thực hiện câu lệnh sau đó kiểm tra điều kiện. Nếu điều kiện đúng thì tiếp tục thực hiện câu lệnh, lặp đến khi điều kiện sai. Ví dụ: hiển thị 10 số tự nhiên đầu tiên int x = 0; do { Console.WriteLine("{0}" , x); x++; } while(x < 10) Trình tự thực hiện •Khởi động chương trình Visual Studio 2010 •Chọn Console Application\ Gõ tên project vào mục Name\OK • Gõ lệnh vào hàm Main 35
  35. •Biên dịch: Nhấn F6 •Chạy chương trình: Nhấn F5 5.5. Vòng lặp for - Vòng lặp biết trước số lần lặp - Vòng lặp for bao gồm ba phần chính: •Khởi tạo biến đếm vòng lặp •Kiểm tra điều kiện biến đếm, nếu đúng thì sẽ thực hiện các lệnh bên trong vòng for •Thay đổi bước lặp. Cú pháp sử dụng vòng lặp for như sau: for ([ phần khởi tạo] ; [biểu thức điều kiện]; [bước lặp]) Ví dụ: hiển thị 10 số tự nhiên đầu tiên Trình tự thực hiện •Khởi động chương trình Visual Studio 2010 •Chọn Console Application\ Gõ tên project vào mục Name\OK • Gõ lệnh vào hàm Main 36
  36. •Biên dịch: Nhấn F6 •Chạy chương trình: Nhấn F5 5.6. Câu lệnh lặp foreach - Vòng lặp foreach cho phép tạo vòng lặp thông qua một tập hợp hay một mảng. - Câu lệnh foreach có cú pháp chung như sau: foreach ( in ) Ví dụ: Hiển thị các phần tử trong 1 mảng int[] intArray = {1,2,3,4,5,6,7,8,9,10}; foreach( int item in intArray) { Console.Write(“{0} ”, item); } 37
  37. Trình tự thực hiện •Khởi động chương trình Visual Studio 2010 •Chọn Console Application\ Gõ tên project vào mục Name\OK • Gõ lệnh vào hàm Main •Biên dịch: Nhấn F6 •Chạy chương trình: Nhấn F5 5.7. Lệnh goto lệnh break, lệnh continue * Lệnh goto - Lệnh nhảy goto là một lệnh nhảy đơn giản, cho phép chương trình nhảy vô điều kiện tới một vị trí trong chương trình thông qua tên nhãn. - Cách sử dụng lệnh nhảy goto:  Tạo một nhãn  goto đến nhãn Nhãn là một định danh theo sau bởi dấu hai chấm (:). Thường thường một lệnh goto gắn với một điều kiện nào đó. * Lệnh break 38
  38. Break khi được sử dụng sẽ đưa chương trình thoát khỏi vòng lặp và tiếp tục thực hiện các lệnh tiếp ngay sau vòng lặp. * Lệnh continue Continue ngừng thực hiện các công việc còn lại của vòng lặp hiện thời và quay về đầu vòng lặp để thực hiện bước lặp tiếp theo 6. Toán tử Toán tử được kí hiệu bằng một biểu tượng dùng để thực hiện một hành động. Các kiểu dữ liệu cơ bản của C# như kiểu nguyên hỗ trợ rất nhiều các toán tử như toán tử gán, toán tử toán học, logic 6.1. Toán tử gán “=” Toán tử gán hay phép gán làm cho toán hạng bên trái thay đổi giá trị bằng với giá trị của toán hạng bên phải 6.2. Toán tử toán học * Các phép toán số học cơ bản (+,-,*,/) - Phép cộng: “+” - Phép trừ: “-” - Phép nhân: “*” - Phép chia: “/” Khi chia hai số nguyên thì C# sẽ bỏ phần dư lấy phần nguyên Ví dụ Console.Write("{0} ", 15/2); Kết quả sẽ là 7 Do vậy để lấy kết quả chính xác khi chia 2 số nguyên chúng ta sử dụng ép kiểu Ví dụ: Console.Write("{0} ", (float) 15/2); Kết quả sẽ là 7.5 * Phép toán chia lấy dư Để tìm phần dư của phép chia nguyên, chúng ta sử dụng toán tử chia lấy dư (%). Ví dụ: 5%2 kết quả là 1 8%3 kết quả là 2 * Toán tử tăng và giảm - Tính toán và gán trở lại Cấu trúc chung x toan_tu=y; 39
  39. tương đương với lệnh: x=x toan_tu y; Toán tử Ý nghĩa += Cộng thêm giá trị toán hạng bên phải vào giá trị toán hạng bên trái x+=y tương đương: x=x+y; -= Toán hạng bên trái được trừ bớt đi một lượng bằng giá trị của toán hạng bên phải x-=y tương đương: x=x-y; *= Toán hạng bên trái được nhân với một lượng bằng giá trị của toán hạng bên phải. x*=y tương đương: x=x*y; /= Toán hạng bên trái được chia với một lượng bằng giá trị của toán hạng bên phải. x/=y tương đương: x=x/y; %= Toán hạng bên trái được chia lấy dư với một lượng bằng giá trị của toán hạng bên phải. x%=y tương đương: x=x%y; - Toán tử tăng giảm tiền tố và tăng giảm hậu tố var1=++var2: tăng giá trị của var2 rồi mới gán giá trị cho var1 var1= var2: Giảm giá trị của var2 rồi gán giá trị cho var1 var1=var2++: Gán giá trị cho var1 rồi tăng giá trị của var2 var1=var2 : Gán giá trị cho var2 rồi giảm giá trị của var2 * Toán tử quan hệ Những toán tử quan hệ được dùng để so sánh giữa hai giá trị, và sau đó trả về kết quả là một giá trị logic kiểu bool (true hay false). Bảng các toán tử quan hệ 40
  40. Tên toán tử Kí hiệu So sánh bằng == Không bằng != Lớn hơn > Lớn hơn hay bằng >= Nhỏ hơn > Trái 6 Quan hệ = is Trái 6.3. Sử dụng toán tử ba ngôi Cú pháp: ? : Hoạt động: Máy tính kiểm tra biểu thức điều kiện, Nếu biểu thức điều kiện đúng thì thực hiện biểu thức thứ 1 ngược lại nếu biểu thức điều kiện sai thì thực hiện biểu thức thứ 2. Ví dụ: Tìm giá trị lớn nhất của 2 giá trị. int value2,value1; int maxValue; 41
  41. value1 = 10; value2 = 20; maxValue = value1 > value2 ? value1 : value2; Console.WriteLine("Gia tri thu nhat {0}, gia tri thu hai {1},gia tri lon nhat {2}", value1, value2, maxValue); Trình tự thực hiện • Khởi động chương trình Visual Studio 2010 • Chọn Console Application\ Gõ tên project vào mục Name\OK • Gõ lệnh vào hàm Main •Biên dịch: Nhấn F6 •Chạy chương trình: Nhấn F5 7. Namespace - Namespace được xem như là tập hợp các lớp đối tượng, và cung cấp duy nhất các định danh cho các kiểu dữ liệu và được đặt trong một cấu trúc phân cấp. - Khai báo sử dụng namespace trong chương trình: using - Để tạo một namespace dùng cú pháp sau: namespace { 42
  42. } Ví dụ: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace vi_du1 { class Program { static void Main(string[] args) { int value2,value1; int maxValue; value1 = 10; value2 = 20; maxValue = value1 > value2 ? value1 : value2; Console.WriteLine("Gia tri thu nhat {0}, gia tri thu hai {1},gia tri lon nhat {2}", value1, value2, maxValue); //Lệnh dừng màn hình để xem Console.ReadKey(); } } } 8. Các chỉ dẫn biên dịch Định nghĩa định danh Câu lệnh tiền xử lý sau: #define DEBUG Để kiểm tra một định danh đã được định nghĩa thì ta dùng cú pháp #if . Do đó ta có thể viết như sau: #define DEBUG // Các đoạn mã nguồn bình thường, không bị tác động bởi trình tiền xử lý 43
  43. #if DEBUG // Các đoạn mã nguồn trong khối if debug được biên dịch #else // Các đoạn mã nguồn không định nghĩa debug và không được biên dịch #endif // Các đoạn mã nguồn bình thường, không bị tác động bởi trình tiền xử lý Không định nghĩa định danh Sử dụng chỉ thị tiền xử lý #undef để xác định trạng thái của một định danh là không được định nghĩa. Một định danh đã được khai báo bên trên với chỉ thị #define sẽ có hiệu quả đến khi một gọi câu lệnh #undef định danh đó hay đến cuối chương trình: #define DEBUG #if DEBUG // Đoạn code này được biên dịch #endif #undef DEBUG #if DEBUG // Đoạn code này không được biên dịch #endif #if đầu tiên đúng do DEBUG được định nghĩa, còn #if thứ hai sai không được biên dịch vì DEBUG đã được định nghĩa lại là #undef. 9. Bài tập 1. Viết chương trình nhập vào 3 số nguyên. In ra màn hình số nguyên nhỏ nhất trong 3 số đó. 44
  44. 2. Viết chương trình nhập vào họ tên, điểm thi cuối kỳ của một học sinh. In ra họ tên học sinh bằng chữ IN HOA, và kết quả xếp loại của học sinh theo tiêu chuẩn sau: - Giỏi: Nếu Điểm kết quả >= 8 - Khá: Nếu 8 > Điểm >= 6.5 - Trung bình: Nếu 6.5 > Điểm >= 5 - Yếu: Nếu Điểm < 5 3. Viết chương trình giải phương trình bậc 1: bx + c = 0 4. Viết chương trình giải phương trình bậc 2: ax2 + bx + c = 0 5. Viết chương trình nhập vào một số nguyên cho đến khi nhận được số nguyên dương thì dừng. 6. Viết chương trình nhập vào một số nguyên n. Cho biết số nguyên n có phải là số nguyên tố không ? 7. Viết chương trình nhập vào một số nguyên dương n chỉ năm dương lịch. Cho biết n có phải là năm nhuận không ? 8. Viết chương trình nhập vào số nguyên dương n. In ra màn hình kết quả của các tổng sau: a) S1 = 1 + 2 + 3 + + n b) S2 = 1 +1/2+1/3+ +1/n 9. Viết chương trình nhập vào số nguyên dương n. In ra màn hình: a) Các số nguyên dương từ 1 đến n b) Tổng và trung bình cộng của n số nguyên dương này. 45
  45. BÀI 4. XÂY DỰNG LỚP – ĐỐI TƯỢNG Mã bài: MĐ20_B04 Giới thiệu: Trong bài này chúng ta sẽ nghiên cứu các bước xây dựng lớp, nạp chồng toán tử trong lớp. Mục tiêu: -Trình bày được các bước xây dựng lớp, tạo đối tượng; -Trình bày được các bước khai báo và sử dụng thành viên static; -Trình bày được các bước nạp trồng toán tử; -Xây dựng được lớp cơ bản theo yêu cầu; -Xây dựng được lớp với các thành viên static, nạp chồng toán tử; -Tạo được đối tượng; -Rèn luyện tính cẩn thận, tỷ mỉ, đảm bảo an toàn cho người và thiết bị. 1. Tạo lớp và đối tượng Cú pháp khai báo lớp class [: ] { // Khai báo biến thành viên ; //Khai báo phương thức } Trong đó: class là từ khoá là 1 định danh [ ] lớp cơ sở dùng để kế thừa Phạm vi truy cập quyết định khả năng các phương thức của lớp bao gồm việc các phương thức của lớp khác có thể nhìn thấy và sử dụng các biến thành viên hay những phương thức bên trong lớp. Bao gồm 46
  46. Thuộc tính Giới hạn truy cập Public Không hạn chế. Những thành viên được đánh dấu public có thể được dùng bởi bất kì các phương thức của lớp bao gồm những lớp khác. Private Thành viên trong một lớp A được đánh dấu là private thì chỉ được truy cập bởi các phương thức của lớp A. Protected Thành viên trong lớp A được đánh dấu là protected thì chỉ được các phương thức bên trong lớp A và những phương thức dẫn xuất từ lớp A truy cập. Internal Thành viên trong lớp A được đánh dấu là internal thì được truy cập bởi những phương thức của bất cứ lớp nào trong cùng khối hợp ngữ với A. protected Thành viên trong lớp A được đánh dấu internal là protected internal được truy cập bởi các phương thức của lớp A, các phương thức của lớp dẫn xuất của A, và bất cứ lớp nào trong cùng khối hợp ngữ của A. Danh_sách_tham_số: ccác tham số của phương thức có hoặc không có Cú pháp khai báo tham số: Hàm tạo không đối Cú pháp { // khởi tạo giá trị cho các thuộc tính bàng 1 giá trị cụ thể } Hàm này tự phát sinh khi tạo lớp có thể không cần định nghĩa Hàm tạo có đối 47
  47. Cú pháp { // khởi tạo giá trị cho các biến thành viên bằng các tham số } Chú ý:Khi đã có hàm tạocó đối thì phải xây dựng hàm tạo không đôi vì khi đã xây dựng hàm tạo máy sẽ không tự phát sinh hàm tạo không đôi. Từ khoá this: dùng để tham chiếu đến thể hiện hiện hành của một đối tượng. Tham chiếu this này được xem là con trỏ ẩn đến tất các phương thức không có thuộc tính tĩnh trong một lớp. Mỗi phương thức có thể tham chiếu đến những phương thức khác và các biến thành viên thông qua tham chiếu this này Tham chiếu this này được sử dụng thường xuyên theo ba cách: + Sử dụng khi các biến thành viên bị che lấp bởi tham số đưa vào Ví dụ: khi định nghĩa lớp phân số this.t=0; this.mau=1; + Sử dụng tham chiếu this để truyền đối tượng hiện hành vào một tham số của một phương thức của đối tượng khác + Các thứ ba sử dụng tham chiếu this là mảng chỉ mục (indexer). Ví dụ: Xây dựng lớp phân số gồm 2 phương thức nhập và hiển thị phân số public class clsphanso { int t, m; // hàm tạo không đối // hàm tạo không đối public clsphanso() { t = 0; m = 1; } public clsphanso(int a,int b) { t = a; m = b; 48
  48. } public void nhap() { Console.Write("Nhap tu so:"); t = int.Parse(Console.ReadLine()); Console.Write("Nhap mau so:"); m = int.Parse(Console.ReadLine()); } public void hienthi() { Console.Write("{0}/{1}", t, m); } } Khai báo đối tượng: = new Ví dụ: Khai báo đối tượng thuộc lớp phân số clsphanso ps1 = new clsphanso(); Sử dụng các phương thức . Ví dụ: gọi phương thức nhập, hiển thị của phân sô ps1.nhap(); ps1.hienthi(); Trình tự thực hiện - Chuột phải vào tên project\Add\Class 49
  49. Gõ tên lớp vào mục Name\Chọn Add 50
  50. Viết code định nghĩa lớp Về hàm main Khai báo đối thượng thuộc lớp clsphanso và gọi các phương thức nhập và hiển thị. 51
  51. Biên dịch: Nhấn F6 Chạy: Nhấn F5\ Nhập tử số\Nhập mẫu số 2. Sử dụng các thành viên static - Biến tĩnh + Khai báo static + Truy xuất . Thuộc tính tĩnh được truy xuất trực tiếp qua tên lớp, không thông qua 1 thê hiện nào của lớp. - Phương thức tĩnh + Khai báo static { // các lệnh của phương thức } + Truy xuất . Phương thức tĩnh được xem như là phần hoạt động của lớp hơn là của thể hiện một lớp. Chúng cũng không cần có một tham chiếu this hay bất cứ thể hiện nào tham chiếu tới. Phương thức tĩnh không thể truy cập trực tiếp đến các thành viên không có tính chất tĩnh Trình tự thực hiện - Chuột phải vào tên project\Add\Class 52
  52. Gõ tên lớp vào mục Name\Chọn Add 53
  53. Viết code cho lớp clsVar Viết code sử dụng lớp clsVar trong hàm Main Biên dịch: Nhấn F6 Chạy chương trình: Nhấn F5\ Nhập số nguyên 54
  54. 3. Hủy đối tượng Hàm huỷ (Destructor) Dùng để giải phóng vùng nhớ đã cấp phát cho đối tượng khi mà đối tuợng không còn được tham chiếu đến. Hàm hủy bỏ là một hàm không có giá trị trả về có tên trùng tên với class và có thêm kí tự “~”ở trước. Cú pháp khai báo: ~Tên_lớp() { // Thực hiện một số công việc } Hoặc Tên_lớp.Finalize() { // Thực hiện một số công việc base.Finalize(); } Trình tự thực hiện - Chuột phải vào tên project\Add\Class 55
  55. Gõ tên lớp clsHinhvuong vào mục Name\Chọn Add Viết code lớp clsHinhvuong 56
  56. Viết code sử dụng lớp clsHinhvuong trong hàm Main Biên dịch: Nhấn F6 Chạy chương trình: Nhấn F5 4. Truyền tham số và nạp chồng phương thức 4.1. Truyền tham số Để trả giá trị về cho tham số sau khi kết thúc hàm ta khai báo tham số theo cú pháp sau: Với tham số được truyền là biến đã được khởi tạo ref Ví dụ: public void GetTime(ref int h, ref int m,ref int s) { h = Hour; m = Minute; s = Second; } Gọi hàm trên như sau: int theHour = 0; int theMinute = 0; int theSecond = 0; t.GetTime(ref theHour,ref theMinute,ref theSecond); - Với truyền tham chiếu với biến chưa khởi tạo out Ví dụ: public void GetTime(out int h, out int m,out int s) { h = Hour; 57
  57. m = Minute; s = Second; } t.GetTime(out theHour,out theMinute,out theSecond); Trình tự thực hiện - Chuột phải vào tên project\Add\Class Gõ tên lớp clsTime vào mục Name\Chọn Add 58
  58. Viết code lớp clsTime Viết code hàm Main sử dụng đối tượng thuộc lớp clsTime Biên dịch chương trình: Nhấp F6 Chạy chương trình: Nhấn F5 59
  59. Sai hỏng thường gặp, nguyên nhân và biện pháp phòng tránh/ khắc phục - Lỗi: - Nguyên nhân: Chưa khởi trạo các biến - Khắc phục: khởi tạo các biến khi truyền tham số ref 4.2. Nạp chồng phương thức - Nạp chồng phương thức là các phương thức có cùng tên nhưng khác nhau về số tham số (số lượng tham số khác nhau, khác nhau về kiểu của tham số) - Ví dụ: public void GetTime(ref int h) { h = Hour; } public void GetTime(ref int h, ref int m) { h = Hour; m = Minute; } public void GetTime(ref int h, ref int m,ref int s) { h = Hour; m = Minute; s = Second; } 60
  60. Trình tự thực hiện - Chuột phải vào tên project\Add\Class Gõ tên lớp clsTime vào mục Name\Chọn Add Viết code lớp clsTime 61
  61. Viết code hàm Main sử dụng đối tượng thuộc lớp clsTime 62
  62. Biên dịch chương trình: Nhấp F6 Chạy chương trình: Nhấn F5 Sai hỏng thường gặp, nguyên nhân và biện pháp phòng tránh/ khắc phục - Lỗi: Nguyên nhân: nạp chồng phương thức có cùng số tham số và tham số có cùng kiểu Khắc phục: thay đổi tham số hoặc thay đổi kiểu của tham số, đặt lại tên hàm 5. Đóng gói dữ liệu với thuộc tính - Thuộc tính là khái niệm cho phép truy cập trạng thái của lớp thay vì thông qua truy cập trực tiếp các biến thành viên, nó sẽ đựơc thay thế bằng việc thực thi truy cập thông qua phương thức của lớp. - Thuộc tính được thiết kế nhắm vào hai mục đích: cung cấp một giao diện đơn cho phép truy cập các biến thành viên, Tuy nhiên cách thức thực thi truy cập giống như phương thức trong đó các dữ liệu được che dấu, đảm bảo cho yêu cầu thiết kế hướng đối tượng. - Cú pháp klhai báo thuộc tính public { // Truy cập lấy dữ liệu get 63
  63. { return ; } // Bộ truy cập thiết lập dữ liệu set { = value; } } - Ví dụ + Thiết lập thuộc tính Hour public int Hour { get { return hour; } set { hour = value; } } + Lấy dữ liệu từ thuộc tính Hour int theHour = t.Hour; Console.WriteLine(" Retrieved the hour: {0}", theHour); theHour++; t.Hour = theHour; Console.WriteLine("Updated the hour: {0}", theHour); 64
  64. Trình tự thực hiện - Chuột phải vào tên project\Add\Class Gõ tên lớp clsTime vào mục Name\Chọn Add 65
  65. Viết code lớp clsTime - Viết code cho hàm Main 66
  66. - Biên dịch chương trình: Nhấn F6 - Chạy chương trình: Nhấn F5 Sai hỏng thường gặp, nguyên nhân và biện pháp phòng tránh/ khắc phục - Lỗi Nguyên nhân: Viết sai giá trị mặc định: value thành values Biện pháp khắc phục: Sửa values thành value 6. Bài tập 1. Tạo lớp số phức bao gồm các thuộc tính và phương thức: - Các thành phần thuộc tính a,b là phần thực và ảo - Hàm thiết lập - Hàm nhập số phức - Hàm in số phức dạng a + ib - Khai báo toán tử + là hàm bạn của lớp số phức - Viết toán tử + để tính tổng 2 số phức - Viết toán tử - để tính hiệu 2 số phức - Viết chương trình nhập vào từ bàn phím với 2 đối tượng x,y. Tính và in ra tổng hiệu 2 số phức đó 2. Tạo lớp Student có các dữ liệu và phương thức sau: - SID (Mã số sinh viên) - Tên sinh viên - Khoa - Điểm TB 67
  67. - Viết các hàm tạo không đối và hàm tạo có đối - Viết các phương thức property cho cacsc thuộc tính trên - Viết các phương thức nhập, hiển thị thông tin; Tạo lớp Tester, trong lớp này chỉ có chứa duy nhất hàm main. Hàm cho phép người dùng nhập và hiển thị danh sách có n sinh viên. 3. Tạo lớp Giaovien có các thuộc tính và phương thức sau: - magv (Mã giáo viên) - hoten (họ và tên) - makhoa (mã khoa) - ngayvl (ngày vào làm) - Viết hàm tạo có đối và hàm tạo không đối - Viết phương thức nhập, hiển thị thông tin Viết hàm main sư dụng lớp vừa tạo. 68
  68. BÀI 5. KẾ THỪA – ĐA HÌNH Mã bài: MĐ20_B05 Giới thiệu: Trong bài này chúng ta sẽ nghiên cứu về Mục tiêu: - Trình bày được đặc điểm về thừa kế; - Mô tả được về đặc điểm đa hình; - Hiểu rõ về đặc điểm trừu tượng; - Sủ dụng được đặc điểm thừa kế; - Sử dụng được đặc điểm đa hình; - Biết cách áp dụng đặc điểm trừu tượng; - Biết cách áp dụng các phương thức, các thành phần static; - Biết cách áp dụng tham số và các phương thức nạp chồng; - Biết cách áp dụng thuộc tính; - Đảm bảo an toàn cho người và thiết bị. 1. Tạo lớp kế thừa - Đặc biệt hóa và tổng quát hóa Sự đặc biệt và tổng quát hoá có mối quan hệ tương hỗ và phân cấp. Khi ta nói ListBox và Button là những cửa sổ (Window), có nghĩa rằng ta tìm thấy được đầy đủ các đặc tính và hành vi của Window đều tồn tại trong hai loại trên. Ta nói rằng Window là tổng quát hoá của ListBox và Button; ngược lại ListBox và Button là hai đặc biệt hoá củaWindow. Window Button List Box Trong C#, mối quan hệ chi tiết hoá là một kiểu kế thừa. Sự kế thừa không cho mang ý nghĩa chi tiết hoá mà còn mang ý nghĩa chung của tự nhiên về mối quan hệ này. Khi ta nói rằng ListBox kế thừa từWindow có nghĩa là nó chi tiết hoá Window. Window được xem như là lớp cơ sở (base class) và ListBox được xem 69
  69. là lớp kế thừa (derived class). Lớp ListBox này nhận tất cả các đặc tính và hành vi của Window và chi tiết hoá nó bằng một số thuộc tính và phương thức của nó cần. - Cú pháp khai báo lớp kế thừa class : Ví dụ: public class clsListBox:clsWindow - Gọi hàm lớp cơ sở + Gọi hàm tạo :base(danh_sách_các_tham_số) Ví dụ: public clsListBox(int top, int left,string theContents):base(top, left) + Gọi phương thức base. Ví dụ: public new void DrawWindow() { base.DrawWindow(); Console.WriteLine(" ListBox write: {0}", mListBoxContents); } Trình tự thực hiện - Chuột phải vào tên project\Add\Class 70
  70. Gõ tên lớp clsTime vào mục Name\Chọn Add Viết code lớp clsWindow , lớp clsListbox kế thừa lớp clsWindow 71
  71. Viết hàm Main 72
  72. Biên dịch chương trình: Nhấn F6 Chạy chương trình: Nhấn F5 Sai hỏng thường gặp, nguyên nhân và biện pháp phòng tránh/ khắc phục - Sai hỏng thường gặp Nguyên nhân Khai báo phạm vi truy xuất của lớp ngầm định là private Biện pháp khắc phục Khai báo phạm vi truy xuất của lớp là public 2. Khai thác tính đa hình - Đa hình được hiểu như là khả năng sử dụng nhiều hình thức của một kiểu mà không cần phải quan tâm đến từng chi tiết. - Ví dụ: Khi một tổng đài điện thoại gởi cho máy điện thoại của chúng ta một tín hiệu có cuộc gọi. Tổng đài không quan tâm đến điện thoại của ta là loại nào. Có thể ta đang dùng một điện thoại cũ dùng motor để rung chuông, hay là một điện thoại điện tử phát ra tiếng nhạc số. Hoàn toàn các thông tin 73
  73. về điện thoại của ta không có ý nghĩa gì với tổng đài, tổng đài chỉ biết một kiểu cơ bản là điện thoại mà thôi và diện thoại này sẽ biết cách báo chuông. Còn việc báo chuông như thế nào thì tổng đài không quan tâm. Tóm lại, tổng đài chỉ cần bảo điện thoại hãy làm điều gì đó để reng. Còn phần còn lại tức là cách thức reng là tùy thuộc vào từng loại điện thoại. Đây chính là tính đa hình. - Kiểu đa hình - Phương thức đa hình + Ở lớp cơ sở: Để tạo một phương thức hỗ tính đa hình, chúng ta cần phải khai báo khóa virtual trong phương thức của lớp cơ sở. Ví dụ: Phương thức DrawWindow() của lớp Window public virtual void DrawWindow() + Lớp dẫn xuất: Để tạo phương thức chồng ở lớp dẫn xuất ta sử dụng từ khoá override. Khai báo phương thức DrawWindow() với từ khoá override public override void DrawWindow() { base.DrawWindow(); Console.WriteLine(“Writing string to the listbox: {0}”, listBoxContents); } Trình tự thực hiện - Tạo lớp mới Window - Viết code using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace vd23 { public class Window { public Window( int top, int left ) { this.top = top; this.left = left; 74
  74. } // phương thức được khai báo ảo public virtual void DrawWindow() { Console.WriteLine( "Window: drawing window at {0}, {1}", top, left ); } // biến thành viên của lớp protected int top; protected int left; } public class ListBox : Window { // phương thức khởi dựng có tham số public ListBox( int top, int left, string contents ): base( top, left) { listBoxContents = contents; } // thực hiện việc phủ quyết phương thức DrawWindow public override void DrawWindow() { base.DrawWindow(); Console.WriteLine(" Writing string to the listbox: {0}", listBoxContents); } // biến thành viên của ListBox private string listBoxContents; } public class Button : Window { public Button( int top, int left) : base( top, left ) { } // phủ quyết phương thức DrawWindow của lớp cơ sở public override void DrawWindow() { 75
  75. Console.WriteLine("Drawing a button at {0}: {1}", top, left); } } } - Viết code Hàm Main using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace vd23 { class Program { static void Main(string[] args) { Window win = new Window(1,2); ListBox lb = new ListBox( 3, 4, " Stand alone list box"); Button b = new Button( 5, 6 ); win.DrawWindow(); lb.DrawWindow(); b.DrawWindow(); Window[] winArray = new Window[3]; winArray[0] = new Window( 1, 2 ); winArray[1] = new ListBox( 3, 4, "List box is array"); winArray[2] = new Button( 5, 6 ); for( int i = 0; i < 3; i++) { winArray[i].DrawWindow(); } Console.ReadKey(); } } } - Biên dịch chương trình: Nhấn F6 - Chạy chương trình: Nhấn F5: 76
  76. Sai hỏng thường gặp, nguyên nhân và biện pháp phòng tránh/ khắc phục - Lỗi: - Nguyên nhân: Thiếu từ khoá override khi khai báo phương thức đa hình của lớp cơ sở - Biện pháp khắc phục Thêm từ khoá override vào phương thức đa hình của lớp cơ sở. 3. Tạo lớp trừu tượng - Một phương thức trừu tượng không có sự thực thi. Phương thức này chỉ đơn giản tạo ra một tên phương thức và ký hiệu của phương thức, phương thức này sẽ được thực thi ở các lớp dẫn xuất. Phương thức trừu tượng được thiết lập bằng cách thêm từ khóa abstract vào đầu của phần định nghĩa phương thức. Ví dụ; Phương thức trừ tượng DrawWindow() của lớp Window cú pháp thực hiện như sau: abstract public void DrawWindow( ); - Những lớp trừu tượng được thiết lập như là cơ sở cho những lớp dẫn xuất, nhưng việc tạo các thể hiện hay các đối tượng cho các lớp trừu tượng được xem là không hợp lệ. Một khi chúng ta khai báo một phương thức là trừu tượng, thì chúng ta phải ngăn cấm bất cứ việc tạo thể hiện cho lớp này. Nếu một hay nhiều phương thức được khai báo là trừu tượng, thì phần định nghĩa lớp phải được khai báo là abstract, với lớp Window ta có thể khai báo là lớp trừu tượng như sau: abstract public void Window 77
  77. Trình tự thực hiện - Tạo lớp mới - Viết code lớp using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace vd23 { abstract public class Window { // hàm khởi dựng lấy hai tham số public Window( int top, int left) { this.top = top; this.left = left; } // phương thức trừu tượng minh họa việc // vẽ ra cửa sổ abstract public void DrawWindow(); // biến thành viên protected int top; protected int left; } // lớp ListBox dẫn xuất từ lớp Window public class ListBox : Window { // hàm khởi dựng lấy ba tham số public ListBox( int top, int left, string contents) : base( top, left) { listBoxContents = contents; } // phủ quyết phương thức trừu tượng DrawWindow() public override void DrawWindow( ) { Console.WriteLine("Writing string to the listbox: {0}", listBoxContents); } // biến private của lớp private string listBoxContents; 78
  78. } // lớp Button dẫn xuất từ lớp Window public class Button : Window { // hàm khởi tạo nhận hai tham số public Button( int top, int left) : base( top, left) { } // thực thi phương thức trừu tượng public override void DrawWindow() { Console.WriteLine("Drawing button at {0}, {1}\n", top, left); } } } - Viết code hàm Main using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace vd23 { class Program { static void Main(string[] args) { Window[] winArray = new Window[3]; winArray[0] = new ListBox( 1, 2, "First List Box"); winArray[1] = new ListBox( 3, 4, "Second List Box"); winArray[2] = new Button( 5, 6); for( int i=0; i <3 ; i++) { winArray[i].DrawWindow( ); 79
  79. } Console.ReadKey(); } } } - Biên dịch: Nhấn F6 - Chạy chương trình: Nhấn F5 Sai hỏng thường gặp, nguyên nhân và biện pháp phòng tránh/ khắc phục - Lỗi - Nguyên nhân: Khai báo 1 thể hiện của lớp trừu tượng - Biện pháp khắc phục Bỏ Khai báo thể thiện của lớp trừu tượng 4. Tạo lớp lồng nhau Các lớp chứa những thành viên, và những thành viên này có thể là một lớp khác có kiểu do người dùng định nghĩa (user-defined type). Do vậy, một lớp Button có thể có một thành viên của kiểu Location, và kiểu Location này chứa thành viên của kiểu dữ liệu Point. Cuối cùng, Point có thể chứa chứa thành viên của kiểu int. Cho đến lúc này, các lớp được tạo ra chỉ để dùng cho các lớp bên ngoài, và chức năng của các lớp đó như là lớp trợ giúp (helper class). Chúng ta có thể định nghĩa một lớp trợ giúp bên trong các lớp ngoài (outer class). Các lớp được định nghĩa bên trong gọi là các lớp lồng (nested class), và lớp chứa được gọi đơn giản là lớp ngoài. Những lớp lồng bên trong có lợi là có khả năng truy cập đến tất cả các thành viên của lớp ngoài. Một phương thức của lớp lồng có thể truy cập đến biến thành viên private của lớp ngoài. Hơn nữa, lớp lồng bên trong có thể ẩn đối với tất cả các lớp khác, lớp lồng có thể là private cho lớp ngoài. 80
  80. Cuối cùng, một lớp làm lồng bên trong là public và được truy cập bên trong phạm vi của lớp ngoài. Nếu một lớp Outer là lớp ngoài, và lớp Nested là lớp public lồng bên trong lớp Outer, chúng ta có thể tham chiếu đến lớp Tested như Outer.Nested, khi đó lớp bên ngoài hành động ít nhiều giống như một namespace hay một phạm vi. Để khai báo lớp bên trong lớp chúng ta dùng từ khoá internal: internal class { // các thành phần của lớp } Ví dụ: Bên trong lớp Fraction khai báo lớp FractionArtist internal class FractionArtist { public void Draw( Fraction f) { Console.WriteLine("Drawing the numerator {0}", f.numerator); Console.WriteLine("Drawing the denominator {0}", f.denominator); } } Trình tự thực hiện - Tạo lớp mới Fraction -Viết code lớp Fraction using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace vd23 { public class Fraction { public Fraction( int numerator, int denominator) { this.numerator = numerator; this.denominator = denominator; 81
  81. } public override string ToString() { StringBuilder s = new StringBuilder(); s.AppendFormat("{0}/{1}",numerator, denominator); return s.ToString(); } internal class FractionArtist { public void Draw( Fraction f) { Console.WriteLine("Drawing the numerator {0}", f.numerator); Console.WriteLine("Drawing the denominator {0}", f.denominator); } } // biến thành viên private private int numerator; private int denominator; } } - Viết code hàm Main using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace vd23 { class Program { static void Main(string[] args) { Fraction f1 = new Fraction( 3, 4); Console.WriteLine("f1: {0}", f1.ToString()); Fraction.FractionArtist fa = new Fraction.FractionArtist(); fa.Draw( f1 ); 82
  82. Console.ReadKey(); } } } - Biên dịch chương trình: Nhấn F6 - Chạy chương trình: Nhấn F5 Sai hỏng thường gặp, nguyên nhân và biện pháp phòng tránh/ khắc phục - Lỗi - Nguyên nhân: Khai báo lớp bên trong không có từ khoá internal class FractionArtist - Khăc phục: Thêm từ khoá internal vào trước khai báo lớp bên trong internal class FractionArtist 5. Bài tập •Khai báo lớp sinhvien •Khai báo và định nghĩa hàm get() để lấy thông tin sinh viên. •Khai báo lớp gdthechat •Khai báo và định nghĩa hàm nhapdiemgdtc() để đọc điểm thể chất. •Tạo lớp thongtinsv được kế thừa từ hai lớp là sinhvien và gdthechat •Khai báo và định nghĩa hàm display() để tìm tổng điểm và điểm trung bình •Khai báo đối tượng obj của lớp kế thừa, gọi hàm nhapdiemkiemtra(), nhapdiemgdtc() và display(). 83
  83. BÀI 6. NẠP CHỒNG TOÁN TỬ Mã bài: MĐ20_B06 Giới thiệu: Trong bài này chúng ta sẽ nghiên cứu về nạp chồng toán tử . Mục tiêu: - Mô tả được về toán tử; - Xây dựng được lớp có nạp chồng toán tử trong các ngôn ngữ; - Đảm bảo an toàn cho người và thiết bị. 1. Nạp chồng toán tử toán học - Toán tử là một phương thức tĩnh dùng để cài đặt một phép toán nào đó trên các đối tượng. Mục đích của toán tử là để viết mã chương trình gọn gàng, dễ hiểu hơn thay vì phương thức. + Toán tử toán học bao gồm: +, -, *, /,% - Cú pháp khai báo nguyên mẫu của một toán tử T: public static kiểu_trả_về operator T(tham số1, tham số2) { // Các câu lệnh trong thân toán tử } Trong đó kiểu_trả_về cùng kiểu với kiểu của các tham số Trong thân của toán tử phải có lệnh trả về giá trị có kiểu là kiểu_trả_về - Khi cài đặt các toán tử toán học dạng +, -, *, /,% thì các toán tử +=,- =,*=,/=,%= cũng tự động được cài đặt. - Ví dụ: nạp chồng toán tử +, -, *,/ của hai phân số public static clsPhanso operator + (clsPhanso ps1, clsPhanso ps2) { clsPhanso ps = new clsPhanso(); ps.tu = ps1.tu * ps2.mau + ps2.tu * ps1.mau; ps.mau = ps1.mau * ps2.mau; return ps; } public static clsPhanso operator -(clsPhanso ps1, clsPhanso ps2) { clsPhanso ps = new clsPhanso(); ps.tu = ps1.tu * ps2.mau - ps2.tu * ps1.mau; 84
  84. ps.mau = ps1.mau * ps2.mau; return ps; } public static clsPhanso operator *(clsPhanso ps1, clsPhanso ps2) { clsPhanso ps = new clsPhanso(); ps.tu = ps1.tu * ps2.tu; ps.mau = ps1.mau * ps2.mau; return ps; } public static clsPhanso operator /(clsPhanso ps1, clsPhanso ps2) { clsPhanso ps = new clsPhanso(); ps.tu = ps1.tu * ps2.mau; ps.mau = ps1.mau * ps2.tu; return ps; } Trình tự thực hiện - Chuột phải vào tên project\Add\Class 85
  85. Gõ tên lớp clsTime vào mục Name\Chọn Add - Viết code lớp clsPhanso class clsPhanso { // biến thành viên int tu, mau; // hàm tạo không đối public clsPhanso() { tu = 0; mau = 1; } // hàm tạo có đối public clsPhanso(int t, int m) { tu = t; mau = m; } //Nạp chồng Toán tử + public static clsPhanso operator + (clsPhanso ps1, clsPhanso ps2) { clsPhanso ps = new clsPhanso(); ps.tu = ps1.tu * ps2.mau + ps2.tu * ps1.mau; ps.mau = ps1.mau * ps2.mau; return ps; } //Nạp chồng toán tử - public static clsPhanso operator -(clsPhanso ps1, clsPhanso ps2) { 86
  86. clsPhanso ps = new clsPhanso(); ps.tu = ps1.tu * ps2.mau - ps2.tu * ps1.mau; ps.mau = ps1.mau * ps2.mau; return ps; } //nạp chồng toán tử * public static clsPhanso operator *(clsPhanso ps1, clsPhanso ps2) { clsPhanso ps = new clsPhanso(); ps.tu = ps1.tu * ps2.tu; ps.mau = ps1.mau * ps2.mau; return ps; } //nạp chồng toán tử / public static clsPhanso operator /(clsPhanso ps1, clsPhanso ps2) { clsPhanso ps = new clsPhanso(); ps.tu = ps1.tu * ps2.mau; ps.mau = ps1.mau * ps2.tu; return ps; } //Phương thức hiển thị phân số public void hienthi() { Console.Write("{0}/{1}",tu,mau); } } - Viết code cho hàm Main - Biên dịch chương trình: Nhấn F6 - Chạy chương trình: Nhấn F5 87
  87. Sai hỏng thường gặp, nguyên nhân và biện pháp phòng tránh/ khắc phục - Sai hỏng thường gặp - Nguyên nhân Khai báo thiếu từ khoá static - Biện pháp khắc phục Thêm từ khoá static vào sau từ khoá public 2. Nạp chồng toán tử quan hệ so sánh Toán tử quan hệ so sánh bao gồm: ==, !=, >, =, <= - Cú pháp khai báo nguyên mẫu của một toán tử T: public static kiểu_trả_về operator T(tham số1, tham số2) { // Các câu lệnh trong thân toán tử } Trong đó kiểu_trả_về là kiểu bool Trong thân của toán tử phải có lệnh trả về giá trị kiểu bool - Ví dụ: //Nạp chồng Toán tử != public static bool operator !=(Phanso ps1, Phanso ps2) { if (ps1.tu * ps2.mau != ps2.tu * ps1.mau) return true; else return false; } //Nạp chồng Toán tử == public static bool operator == (Phanso ps1, Phanso ps2) { if (ps1.tu * ps2.mau == ps2.tu * ps1.mau) return true; else return false; } 88
  88. //Nạp chồng Toán tử > public static bool operator >(Phanso ps1, Phanso ps2) { if (ps1.tu * ps2.mau > ps2.tu * ps1.mau) return true; else return false; } //Nạp chồng Toán tử = public static bool operator >=(Phanso ps1, Phanso ps2) { if (ps1.tu * ps2.mau >= ps2.tu * ps1.mau) return true; else return false; } //Nạp chồng Toán tử <= public static bool operator <=(Phanso ps1, Phanso ps2) { if (ps1.tu * ps2.mau <= ps2.tu * ps1.mau) return true; else return false; } Trình tự thực hiện - Chuột phải vào tên project\Add\Class 89
  89. Gõ tên lớp clsTime vào mục Name\Chọn Add - Viết code lớp Phanso class Phanso { // biến thành viên int tu, mau; // hàm tạo không đối public Phanso() { 90
  90. tu = 0; mau = 1; } // hàm tạo có đối public Phanso(int t, int m) { tu = t; mau = m; } //Nạp chồng Toán tử != public static bool operator !=(Phanso ps1, Phanso ps2) { if (ps1.tu * ps2.mau != ps2.tu * ps1.mau) return true; else return false; } //Nạp chồng Toán tử == public static bool operator == (Phanso ps1, Phanso ps2) { if (ps1.tu * ps2.mau == ps2.tu * ps1.mau) return true; else return false; } //Nạp chồng Toán tử > public static bool operator >(Phanso ps1, Phanso ps2) { if (ps1.tu * ps2.mau > ps2.tu * ps1.mau) return true; else return false; } //Nạp chồng Toán tử < public static bool operator <(Phanso ps1, Phanso ps2) { if (ps1.tu * ps2.mau < ps2.tu * ps1.mau) return true; 91
  91. else return false; } //Nạp chồng Toán tử >= public static bool operator >=(Phanso ps1, Phanso ps2) { if (ps1.tu * ps2.mau >= ps2.tu * ps1.mau) return true; else return false; } //Nạp chồng Toán tử <= public static bool operator <=(Phanso ps1, Phanso ps2) { if (ps1.tu * ps2.mau <= ps2.tu * ps1.mau) return true; else return false; } // phương thức hiển thị public void hienthi() { Console.Write("{0}/{1}", tu, mau); } } - Viết code hàm Main 92
  92. - Biên dịch: Nhấn F6 - Chạy chương trình: Nhấn F5 Sai hỏng thường gặp, nguyên nhân và biện pháp phòng tránh/ khắc phục - Lỗi thường gặp - Nguyên nhân: Chưa nạp chồng toán tử != - Biện pháp khắc phục: Nạp chồng toán tử != 3. Bài tập Tạo lớp số phức bao gồm: - Thuộc tính: thực, ảo - Nạp chồng toán toán tử + hai số phức - Nạp chồng toán tử - hai số phức - Nạp chồng toán tử != - Nạp chồng toán tử >= - Nạp chồng toán tử <= - Nạp chồng toán tử == 93
  93. BÀI 7. MẢNG, CHỈ MỤC VÀ TẬP HỢP Mã bài: MĐ20_B06 Giới thiệu: Trong bài này chúng ta sẽ nghiên cứu về mảng, chỉ mục và tập hợp. Mục tiêu: - Trình bày được cú pháp khai báo mảng, chỉ mục và tập hợp; - Sử dụng thành thạo mảng; - Sử dụng thành thạo các loại tập hợp; - Sử dụng thành thạo chỉ mục; - Đảm bảo an toàn cho người và thiết bị. 1. Xây dựng và xử lý mảng Mục tiêu: - Trình bày được cú pháp khai báo mảng; - Vận dụng làm được các bài tập đơn giản về mảng. - Mảng là một tập hợp có thứ tự của những đối tượng, tất cả các đối tượng này cùng một kiểu. - Mảng trong ngôn ngữ C# có một vài sự khác biệt so với mảng trong ngôn ngữ C++ và một số ngôn ngữ khác, bởi vì chúng là những đối tượng. - Mảng có các phương thức và những thuộc tính như sau: Một số các thuộc tính và phương thức của lớp System.Array Thành viên Mô tả Phương thức tĩnh public tìm kiếm một mảng một BinarySearch() chiều đã sắp thứ tự. Phương thức tĩnh public thiết lập các thành phần Clear() của mảng về 0 hay null. Phương thức tĩnh public đã nạp chồng thực hiện Copy() sao chép một vùng của mảng vào mảng khác. Phương thức tĩnh public đã nạp chồng tạo một thể CreateInstance() hiện mới cho mảng Phương thức tĩnh public trả về chỉ mục của thể hiện IndexOf() đầu tiên chứa giá trị trong mảng một chiều Phương thức tĩnh public trả về chỉ mục của thể hiện LastIndexOf() cuối cùng của giá trị trong mảng một chiều 94
  94. Phương thức tĩnh public đảo thứ tự của các thành Reverse() phần trong mảng một chiều Phương thức tĩnh public sắp xếp giá trị trong mảng Sort() một chiều. Thuộc tính public giá trị bool thể hiện mảng có IsFixedSize kích thước cố định hay không. Thuộc tính public giá trị bool thể hiện mảng chỉ IsReadOnly đọc hay không Thuộc tính public giá trị bool thể hiện mảng có hỗ IsSynchronized trợ thread-safe Length Thuộc tính public chiều dài của mảng Rank Thuộc tính public chứa số chiều của mảng Thuộc tính public chứa đối tượng dùng để đồng bộ SyncRoot truy cập trong mảng GetEnumerator() Phương thức public trả về IEnumerator Phương thức public trả về kích thước của một chiều GetLength() cố định trong mảng Phương thức public trả về cận dưới của chiều xác GetLowerBound() định trong mảng Phương thức public trả về cận trên của chiều xác GetUpperBound() định trong mảng Khởi tạo tất cả giá trị trong mảng kiểu giá trị bằng Initialize() cách gọi bộ khởi dụng mặc định của từng giá trị. Phương thức public thiết lập giá trị cho một thành SetValue() phần xác định trong mảng. - Khai báo mảng [] = new [ ]; Hoặc [] ; = new [ ]; Trong đó Ví dụ: int[] a; // khai báo mảng số nguyên a. 95
  95. int[] a=new int[5]; // khai báo mảng 5 phần tử số nguyên - Giá trị mặc định: Khi chúng ta khai báo mảng thì mỗi phần tử mảng sẽ chứa giá trị mặc định của kiểu dữ liệu Ví dụ: int[] a=new int[5]; sẽ tạo ra một mảng năm số nguyên và mỗi phần tử được thiết laaph giá trị 0 mặc định - Truy cập các thành phần trong mảng [chỉ mục] chỉ mục nằm trong đoạn 0 n-1 Phần tử đầu tiên của mảng có chỉ mục là: 0 Ví dụ: int[] a = new int[10]; int i,n=5; for (i = 0; i in ) { // thực hiện thông qua tương ứng với // từng mục trong mảng hay tập hợp } Ví dụ: int[] myIntArrayq = { 2, 4, 6, 8, 10 }; foreach (int k in myIntArrayq) 96
  96. { Console.Write(k.ToString()+"\t"); } - Khởi tạo thành phần của mảng Chúng ta có thể khởi tạo nội dung của một mảng ngay lúc tạo thể hiện của mảng bằng cách đặt những giá trị bên trong dấu ngoặc ({}). Ví dụ: int[] myIntArray = new int[5] { 2, 4, 6, 8, 10 }; hoặc int[] myIntArray = { 2, 4, 6, 8, 10 }; Trình tự thực hiện - Tạo Project mới - Viết code cho hàm Main static void Main(string[] args) { int i,n=5; // khai bao mang int[] a = new int[10]; //nhap du lieu for (i = 0; i a[j]) { tg=a[i];a[i]=a[j];a[j]=tg; } //hien thi mang da sap xep Console.WriteLine("Mang sap xep theo chieu tang dan:"); for (i = 0; i < n; i++) { Console.Write("{0} ", a[i]); 97
  97. } Console.ReadKey(); } - Biên dịch chương trình: Nhấn F6 - Chạy chương trình: Nhấn F5 2. Xây dựng và xử lý bộ chỉ mục Mục tiêu: - Trình bày được cú pháp xây dựng bộ chỉ mục; - Xây dựng được lớp theo yêu cầu của bài tập. - Bộ chỉ mục là một cơ chế cho phép các thành phần client truy cập một tập hợp chứa bên trong một lớp bằng cách sử dụng cú pháp giống như truy cập mảng ([]). Chỉ mục là một loại thuộc tính đặc biệt và bao gồm các phương thức get() và set() để xác nhận những hành vi của chúng. - Khai báo thuộc tính chỉ mục bên trong của lớp bằng cách sử dụng cú pháp như sau: this [ ] { get; set; } Kiểu trả về được quyết định bởi kiểu của đối tượng được trả về bởi bộ chỉ mục, trong khi đó kiểu của đối mục được xác định bởi kiểu của đối mục dùng để làm chỉ số vào trong tập hợp chứa đối tượng đích. Từ khóa this tham chiếu đến đối tượng nơi mà chỉ mục xuất hiện. Ví dụ 9.9 khai báo một điều khiển ListBox, tên là clsListBox, đối tượng này chứa một mảng đơn giản (myStrings) và một chỉ mục để truy cập nội dung của mảng. public string this[int index] { get { if ( index = strings.Length) { // xử lý chỉ mục sai } return strings[index]; } 98
  98. set { if ( index >= ctr) { // xử lý lỗi chỉ mục không tồn tại } else strings[index] = value; } } Trình tự thực hiện - Chuột phải vào tên project\Add\Class Gõ tên lớp clsListBox vào mục Name\Chọn Add 99
  99. - Viết code lớp clsListBox using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace vd22 { class clsListBox { // các biến thành vịên lưu giữ mảng cho bộ chỉ mục private string[] strings; private int ctr = 0; // khởi tạo ListBox với một chuỗi public clsListBox( params string[] initialStrings) { // cấp phát không gian cho chuỗi strings = new String[256]; // copy chuỗi truyền từ tham số foreach ( string s in initialStrings) { strings[ctr++] = s; } } // thêm một chuỗi public void Add(string theString) { if (ctr >= strings.Length) { // xử lý khi chỉ mục sai } else strings[ctr++] = theString; } // thực hiện bộ truy cập public string this[int index] { get { if ( index = strings.Length) 100
  100. { // xử lý chỉ mục sai } return strings[index]; } set { if ( index >= ctr) { // xử lý lỗi chỉ mục không tồn tại } else strings[index] = value; } } // lấy số lượng chuỗi được lưu giữ public int GetNumEntries() { return ctr; } } } - Viết code hàm Main using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace vd22 { class Program { static void Main(string[] args) { // tạo một đối tượng ListBox mới và khởi tạo clsListBox lbt = new clsListBox("Hello", "World"); // thêm một số chuỗi vào lbt.Add("Who"); lbt.Add("is"); lbt.Add("Ngoc"); 101
  101. lbt.Add("Mun"); // dùng bộ chỉ mục string strTest = "Universe"; lbt[1] = strTest; // truy cập và xuất tất cả các chuỗi for (int i = 0; i < lbt.GetNumEntries(); i++) { Console.WriteLine("lbt[{0}]: {1}", i, lbt[i]); } Console.ReadKey(); } } } - Biên dịch chương trình: Nhấn F6 - Chạy chương trình: Nhấn F5 Sai hỏng thường gặp, nguyên nhân và biện pháp phòng tránh/ khắc phục - Sai hỏng thường gặp Nguyên nhân: Khi khai báo chỉ mục thiếu phạm vi truy xuất là public Biện pháp khắc phục Thêm từ khoá public vào trược khai báo chỉ mục 3. Tạo giao diện tập hợp Mục tiêu: - Trình bày được cách thức tạo giao diện tập hợp; - Xây dựng được lớp theo yêu cầu của bài tập. Môi trường .NET cung cấp những giao diện chuẩn cho việc liệt kê, so sánh, và tạo các tập hợp. Một số các giao diện trong số đó được liệt kê trong bảng 9.2 sau: Giao diện Mục đích Ienumerable Liệt kê thông qua một tập hợp bằng cách sử dụng foreach. 102
  102. Thực thi bởi tất cả các tập hợp để cung cấp phương thức CopyTo() cũng như các thuộc tính ICollection Count, ISReadOnly, ISSynchronized, và SyncRoot. So sánh giữa hai đối tượng lưu giữ trong tập Icomparer hợp để sắp xếp các đối tượng trong tập hợp. Ilist Sử dụng bởi những tập hợp mảng được chỉ mục Dùng trong các tập hợp dựa trên khóa và giá trị IDictionary như Cho phépHashtable liệt kê dùngvà SortedList. câu lệnh foreach qua tập IdictionaryEnumerator hợp hỗ trợ IDictionary. Giao diện IEnumerable Giao diện này chỉ có một phương thức duy nhất là GetEnumerator(), công việc của phương thức là trả về một sự thực thi đặc biệt của IEnumerator. Do vậy, ngữ nghĩa của lớp Enumerable là nó có thể cung cấp một Enumerator: public IEnumerator GetEnumerator() { return (IEnumerator) new ListBoxEnumerator(this); } Enumerator phải thực thi những phương thức và thuộc tính Ienumerator. Ví dụ: public ListBoxEnumerator(ListBoxTest lbt) { this.lbt = lbt; index = -1; } Phương thức MoveNext() gia tăng index và sau đó kiểm tra để đảm bảo rằng việc thực hiện không vượt quá số phần tử trong tập hợp của đối tượng: public bool MoveNext() { index++; if (index >= lbt.strings.Length) return false; else 103
  103. return true; } Ví dụ: Tạo lớp ListBox hỗ trợ enumerator. namespace Programming_CSharp { using System; using System.Collections; // tạo một control đơn giản public class ListBoxTest: IEnumerable { // lớp thực thi riêng ListBoxEnumerator private class ListBoxEnumerator : IEnumerator { public ListBoxEnumerator(ListBoxTest lbt) { th is.lbt = lbt; index = -1; } // gia tăng index và đảm bảo giá trị này hợp lệ public bool MoveNext() { index++; if (index >= lbt.strings.Len gth) return false; else return true; } public void Reset() { index = -1; } public object Current { 104
  104. get { return( lbt[index]); } } private ListBoxTest lbt; private int index; } // trả về Enumerator public IEnumerator GetEnumerator() { return (IEnumerator) new ListBoxEnumerator(this); } // khởi tạo listbox với chuỗi public ListBoxTest (params string[] initStr) { strings = new String[10]; // copy từ mảng chuỗi tham số foreach (string s in initStr) { strings[ctr++] = s; } } public void Add(string theString) { strings[ctr] = theString; ctr++; } // cho phép truy cập giống như mảng public string this[int index] { get { if ( index = strings.Length) { // xử lý index sai } return strings[index]; } 105
  105. set { strings[index] = value; } } // số chuỗi nắm giữ public int GetNumEntries() { return ctr; } private string[] strings; private int ctr = 0; } } Giao diện ICollection ICollection cung cấp bốn thuộc tính: Count, IsReadOnly, IsSynchronized, và SyncRoot. Ngoài ra ICollection cũng cung cấp một phương thức CopyTo(). Thuộc tính thường được sử dụng là Count, thuộc tính này trả về số thành phần trong tập hợp: for(int i = 0; i < myIntArray.Count; i++) { // } Giao diện IComparer Giao diện IComparer cung cấp phương thức Compare(), để so sánh hai phần tử trong một tập hợp có thứ tự. Phương thức Compare() thường được thực thi bằng cách gọi phương thức CompareTo() của một trong những đối tượng. CompareTo () là phương thức có trong tất cả đối tượng thực thi IComparable Trình tự thực hiện - Chuột phải vào tên project\Add\Class 106
  106. Gõ tên lớp ListBoxTest vào mục Name\Chọn Add - Viết code lớp ListBoxTest namespace Programming_CSharp { using System; using System.Collections; // tạo một control đơn giản public class ListBoxTest: IEnumerable { 107
  107. // lớp thực thi riêng ListBoxEnumerator private class ListBoxEnumerator : IEnumerator { public ListBoxEnumerator(ListBoxTest lbt) { this.lbt = lbt; index = -1; } // gia tăng index và đảm bảo giá trị này hợp lệ public bool MoveNext() { index++; if (index >= lbt.strings.Length) return false; else return true; } public void Reset() { index = -1; } public object Current { get { return( lbt[index]); } } private ListBoxTest lbt; private int index; } // trả về Enumerator public IEnumerator GetEnumerator() { return (IEnumerator) new ListBoxEnumerator(this); } // khởi tạo listbox với chuỗi public ListBoxTest (params string[] initStr) { 108
  108. strings = new String[10]; // copy từ mảng chuỗi tham số foreach (string s in initStr) { strings[ctr++] = s; } } public void Add(string theString) { strings[ctr] = theString; ctr++; } // cho phép truy cập giống như mảng public string this[int index] { get { if ( index = strings.Length) { // xử lý index sai } return strings[index]; } set { strings[index] = value; } } // số chuỗi nắm giữ public int GetNumEntries() { return ctr; } private string[] strings; private int ctr = 0; } } - Viết code hàm Main static void Main() { ListBoxTest lbt = new ListBoxTest(“Hello”, “World”); lbt.Add(“What”); lbt.Add(“Is”); 109
  109. lbt.Add(“The”); lbt.Add(“C”); lbt.Add(“Sharp”); string subst = “Universe”; lbt[1] = subst; // truy cập tất cả các chuỗi int count =1; foreach (string s in lbt) { Console.WriteLine(“Value {0}: {1}”,count, s); count++; } } } - Biên dịch chương trình: Nhấn F6 - Chạy chương trình: Nhấn F5 Sai hỏng thường gặp, nguyên nhân và biện pháp phòng tránh/ khắc phục - Sai hỏng thường gặp Nguyên nhân: Khi khai báo chỉ mục thiếu phạm vi truy xuất là public Biện pháp khắc phục Thêm từ khoá public vào trược khai báo chỉ mục 4. Bài tập Nhập vào một dãy n số nguyên A[1],A[2], ,A[n] . Đọc ra màn hình các thông tin sau : 1. Tổng các phần tử của dãy. 2. Số lượng các số hạng dương và tổng của các số hạng dương. 3. Số lượng các số hạng âm và tổng của các số hạng âm. 4. Trung bình cộng của cả dãy. Trung bình cộng các phần tử dương của mảng. Trung bình cộng các phần tử âm của mảng. 5. Chỉ số của số hạng dương đầu tiên của dãy. 110
  110. 6. Chỉ số của số hạng âm đầu tiên của dãy. 7. Chỉ số của số hạng dương cuối cùng của dãy. 8. Chỉ số của số hạng âm cuối cùng của dãy. 9. Số hạng lớn nhất của dãy và chỉ số của nó. 10. Số hạng nhỏ nhất của dãy và chỉ số của nó. 11. Số hạng âm lớn nhất của dãy và chỉ số của nó. 12. Số hạng dương nhỏ nhất của dãy và chỉ số của nó. 111
  111. BÀI 8. XỬ LÝ CHUỖI Mã bài: MĐ20_B08 Giới thiệu: Trong bài này chúng ta sẽ nghiên cứu về chuỗi trong C#. Mục tiêu: - Trình bày được cú pháp khai báo chuỗi trong C#; - Biết cách xử lý chuỗi trong các chương trình; - Đảm bảo an toàn cho người và thiết bị. 1. Tạo một chuỗi Lớp đối tượng String - C# xem những chuỗi như là những kiểu dữ liệu cơ bản tức là các lớp này rất linh hoạt, mạnh mẽ, và nhất là dễ sử dụng. Mỗi đối tượng chuỗi là một dãy cố định các ký tự Unicode - Khi chúng ta khai báo một chuỗi C# bằng cách dùng từ khóa string, là chúng ta đã khai báo một đối tượng của lớp System.String - Khai báo một đối tượng thuộc lớp string: string [= “chuỗi_gán”]; - Ví dụ: string hoten; string ngaysinh; string quequan; - Chuỗi nguyên văn: các ký tự trong chuỗi được giữ nguyên không thay đổi. Để gán chuỗi nguyên văn ta thêm @ vào trước chuỗi gán cho biến kiểu string như sau: string verbatim1 = @”\\MyDocs\CSharp\ProgrammingC#.cs”; Nếu bình thường không có @ ta sẽ khai báo và gán như sau: string verbatim1 = ”\\\\MyDocs\\CSharp\\ProgrammingC#.cs”; Vì muốn thể hiện các ký tự đặc biệt ta phải thêm \ đằng trước ký tự đó. \n: là ký tự xuống hàng Trình tự thực hiện - Chuột phải vào tên project\Add\Class 112
  112. Gõ tên lớp clsTime vào mục Name\Chọn Add - Viết code lớp clsSinhvien 113
  113. - Viết code cho hàm Main - Biên dịch chương trình: Nhấn F6 - Chạy chương trình: Nhấn F5\ Nhập thông tin sinh viên 114
  114. Sai hỏng thường gặp, nguyên nhân và biện pháp phòng tránh/ khắc phục - Sai hỏng thường gặp - Nguyên nhân: Sử dụng ký tự (‘’) để gán cho biên chuỗi - Biện pháp khắc phục Sử dụng ký tự (“”) để gán cho chuỗi. 2. Tạo chuỗi dùng phương thức ToString - Để tạo một chuỗi ta sử dụng phương thức ToString() của một đối tượng và gán kết quả đến một biến chuỗi. - Ví dụ: int a = 1900; string str = a.ToString(); Trình tự thực hiện - Tạo Project mới - Viết code hàm Main - Biên dịch: Nhấn F6 - Chạy chương trình: Nhấn F5 Sai hỏng thường gặp, nguyên nhân và biện pháp phòng tránh/ khắc phục 115
  115. - Lỗi - Nguyên nhân: Viết sai tên phương thức Tostring () - Biện pháp khắc phục: Sửa lại thành ToString () 3. Thao tác trên chuỗi Mục tiêu: - Trình bày được các phương thức cơ bản cơ lớp String; - Vận dụng được các phương thức để làm bài tập. - Lớp string cung cấp rất nhiều số lượng các phương thức để so sánh, tìm kiếm và thao tác trên chuỗi. Phương thức và thuộc tính của lớp String System.String Ý nghĩa Phương thức/ Trường Empty Trường public static thể hiện một chuỗi rỗng. Compare() Phương thức public static để so sánh hai chuỗi. Phương thức public static để so sánh hai CompareOrdinal() chuỗi không quan tâm đến thứ tự. Phương thức public static để tạo chuỗi mới Concat() từ một hay nhiều chuỗi. Phương thức public static tạo ra một chuỗi Copy() mới bằng sao từ chuỗi khác. Phương thức public static kiểm tra xem hai Equal() chuỗi có cùng giá trị hay không. Phương thức public static định dạng một Format() chuỗi dùng ký tự lệnh định dạng xác định. Phương thức public static trả về tham Intern() chiếu đến thể hiện của chuỗi. Phương thức public static trả về tham chiếu IsInterned() của chuỗi 116
  116. Phương thức public static kết nối các chuỗi Join() xác định giữa mỗi thành phần của mảng chuỗi. Chars() Indexer của chuỗi. Length() Chiều dài của chuỗi. Clone() Trả về chuỗi. CompareTo() So sánh hai chuỗi. Sao chép một số các ký tự xác định đến một CopyTo() mảng ký tự Unicode. Chỉ ra vị trí của chuỗi xác định phù hợp với EndsWidth() chuỗi đưa ra. Trả về chuỗi mới đã được chèn một chuỗi xác Insert() định. Chỉ ra vị trí xuất hiện cuối cùng của một LastIndexOf() chuỗi xác định trong chuỗi. Canh lề phải những ký tự trong chuỗi, chèn PadLeft() vào bên trái khoảng trắng hay các ký tự xác định. Canh lề trái những ký tự trong chuỗi, chèn PadRight() vào bên phải khoảng trắng hay các ký tự xác định. Remove() Xóa đi một số ký tự xác định. Trả về chuỗi được phân định bởi những ký tự Split() xác định trong chuỗi. Xem chuỗi có bắt đầu bằng một số ký tự xác StartWidth() định hay không. SubString() Lấy một chuỗi con. Sao chép những ký tự từ một chuỗi đến mảng ToCharArray() ký tự. ToLower() Trả về bản sao của chuỗi ở kiểu chữ thường. ToUpper() Trả về bản sao của chuỗi ở kiểu chữ hoa. 117
  117. Xóa bỏ tất cả sự xuất hiện của tập hợp ký tự Trim() xác định từ vị trí đầu tiên đến vị trí cuối cùng TrimEnd() Xóatrong như chuỗi. nhưng ở vị trí cuối. TrimStart() Xóa như Trim nhưng ở vị trí đầu. - Ví dụ: string s1 = "abcd"; string s2 = "ABCD"; // So sánh hai chuỗi với nhau có phân biệt chữ thường và chữ hoa result = string. Compare(s1, s2, flase); //hoặc string. Compare(s1, s2) mặc định tham số thứ 3 là false //So sánh không phân biệt chữ thường hay chữ hoa // Tham số thứ ba là true sẽ bỏ qua kiểm tra ký tự thường – hoa result = string. Compare(s1, s2, true); // phương thức nối các chuỗi string s4 = string.Concat(s1, s2); // sử dụng nạp chồng toán tử + string s5 = s1 + s2; // Sử dụng phương thức copy chuỗi string s6 = string.Copy(s5); Trình tự thực hiện - Tạo Project mới - Viết code hàm Main class Program { static void Main(string[] args) { // khởi tạo một số chuỗi để thao tác string s1 = "abcd"; string s2 = "ABCD"; string s3 = "Trung Tam Dao Tao CNTT Truong cao dang co gioi Ninh Binh"; int result; // So sánh hai chuỗi với nhau có phân biệt chữ thường và chữ hoa 118
  118. result = string.Compare( s1 ,s2); Console.WriteLine("So sanh hai chuoi S1: {0} và S2: {1} ket qua: {2} \n", s1 ,s2 ,result); // Sử dụng tiếp phương thức Compare() nhưng trường hợp này không biệt // chữ thường hay chữ hoa // Tham số thứ ba là true sẽ bỏ qua kiểm tra ký tự thường – hoa result = string. Compare(s1, s2, true); Console.WriteLine("Khong phan biet chu thuong va hoa\n"); Console.WriteLine("S1: {0} , S2: {1}, ket qua : {2}\n", s1, s2, result); // phương thức nối các chuỗi string s4 = string.Concat(s1, s2); Console.WriteLine("Chuoi S4 noi tu chuoi S1 va S2: {0}", s4); // sử dụng nạp chồng toán tử + string s5 = s1 + s2; Console.WriteLine("Chuoi S5 duoc noi tu chuoi S1 va S2: {0}", s5); // Sử dụng phương thức copy chuỗi string s6 = string.Copy(s5); Console.WriteLine("S6 duoc sao chep tu S5: {0}", s6); // Sử dụng nạp chồng toán tử = string s7 = s6; Console.WriteLine("S7 = S6: {0}", s7); // Sử dụng ba cách so sánh hai chuỗi // Cách 1 sử dụng một chuỗi để so sánh với chuỗi còn lại Console.WriteLine("S6.Equals(S7) ?: {0}", s6.Equals(s7)); // Cách 2 dùng hàm của lớp string so sánh hai chuỗi Console.WriteLine("Equals(S6, s7) ?: {0}", string.Equals(s6, s7)); // Cách 3 dùng toán tử so sánh Console.WriteLine("S6 == S7 ?: {0}", s6 == s7); // Sử dụng hai thuộc tính hay dùng là chỉ mục và chiều dài của chuỗi Console.WriteLine("\nChuoi S7 co chieu dai la : {0}", s7.Length); Console.WriteLine("Ky tu thu 3 cua chuoi S7 la : {0}", s7[2] ); // Kiểm tra xem một chuỗi có kết thúc với một nhóm ký 119
  119. // tự xác định hay không Console.WriteLine("S3: {0}\n ket thuc voi chu CNTT ? : {1}\n", s3, s3.EndsWith("CNTT")); Console.WriteLine("S3: {0}\n ket thuc voi chu Nam ? : {1}\n", s3, s3.EndsWith("Nam")); // Trả về chỉ mục của một chuỗi con Console.WriteLine("\nTim vi tri xuat hien dau tien cua chu CNTT "); Console.WriteLine("trong chuoi S3 là {0}\n", s3.IndexOf("CNTT")); // Chèn từ nhân lực vào trước CNTT trong chuỗi S3 string s8 = s3.Insert(18, "nhan luc "); Console.WriteLine(" S8 : {0}\n", s8); // Ngoài ra ta có thể kết hợp như sau string s9 = s3.Insert( s3.IndexOf( "CNTT" ) , "nhan luc "); Console.WriteLine(" S9 : {0}\n", s9); Console.ReadKey(); } } Sai hỏng thường gặp, nguyên nhân và biện pháp phòng tránh/ khắc phục - Sai hỏng thường gặp - Nguyên nhân Viết sai tên phương thức - Biện pháp khắc phục: Sửa cho đúng tên phương thức 4. Tìm một chuỗi con Để trích chuỗi con của một chuỗi ta sử dụng phương thức Substring() theo cú pháp sau: - Trích chuỗi con từ vị trí Startindex đến cuối cùng. String_name.Substring(int Start index) 120
  120. Ví dụ: string s1 = "Trung Tam Dao Tao CNTT Truong cao dang co gioi Ninh Binh"; string s2 = s1.Substring(23); Kết quả: Truong cao dang co gioi Ninh Binh - Trích chuỗi con từ vị trí Startindex và có độ dài length String_name.Substring(int Start index, int length) Ví dụ: string s1 = "Trung Tam Dao Tao CNTT Truong cao dang co gioi Ninh Binh"; string s3 = s1.Substring(18,4); Kết quả: CNTT Trình tự thực hiện - Tạo Project mới - Viết code hàm Main - Biên dịch chương trình: Nhấn F6 - Chạy chương trình: Nhấn F5 121
  121. Sai hỏng thường gặp, nguyên nhân và biện pháp phòng tránh/ khắc phục - Sai hỏng thường gặp - Nguyên nhân Viết sai tên phương thức - Biện pháp khắc phục: Sửa cho đúng tên phương thức 5. Chia chuỗi Để phân tích từ một chuỗi ra thành các chuỗi con ta dùng phương thức Split theo cú pháp sau: String_name.Split(char[] strarray_name) - strarray_name là mảng các ký tự. - Chuỗi String_name sẽ được tách thành các chuỗi con khi gặp ký tự thuộc mảng strarray. Kết quả trả về là một mảng các chuỗi được tách ra. Ví dụ: Tách các từ trong chuỗi: string s1 = "Trung Tam Dao Tao CNTT Truong cao dang co gioi Ninh Binh"; char[] strarray = new char[]{' ',','}; string strout=""; int ctr=1; foreach ( string subString in s1.Split(delimiters) ) { strout += ctr++; strout += ": "; strout += subString; strout += "\n"; } Kết quả là 122
  122. Trình tự thực hiện - Tạo Project - Viết code hàm Main - Biên dịch chương trình: Nhấn F6 - Chạy chương trình: Nhấn F5 123
  123. Sai hỏng thường gặp, nguyên nhân và biện pháp phòng tránh/ khắc phục - Sai hỏng thường gặp - Nguyên nhân Viết sai tên phương thức - Biện pháp khắc phục: Sửa cho đúng tên phương thức 6. Bài tập Viết lớp hocsinh bao gồm các thuộc tính và phương thức sau: - Masv - Hoten - Diemtoan - Diemly - Diemhoa - Hàm tạo không đối, hàm tạo có đối - Phương thức nhập, hiển thị thông tin Viết lớp dssv bao gồm các thuộc tính và phương thức sau: - Mảng ds kiểu hocsinh - Số học sinh - Phương thức nhập - Phương thức hiển thị - Phương thức tìm kiếm thông tin học sinh theo tên 124