Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 127 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
127
Dung lượng
1,33 MB
Nội dung
1 TRƯỜNG ĐẠI HỌC NHA TRANG KHOA CÔNG NGHỆ THÔNG TIN Bài giảng KỸ THUẬT LẬP TRÌNH (Programming Methodology) 2 Chương I: Tổng quan về Kỹ thuật lập trình 1.1 Tổng quan Lập trình là một trong những công đoạn quan trọng trong lĩnh vực Công nghệ Thông tin. Việc xây dựng chương trình, dò lỗi, hoàn thiện, bảo đảm tính đúng đắn của chương trình và đáp ứng các yêu cầu của người sử dụng đòi hỏi nhiều kỹ thuật, trí tuệ và công sức. Lập trình có thể được coi như một ngành khoa học. Khoa học này nhằm đưa ra những nguyên lý và phương pháp nhằm nâng cao năng suấ t lao động của các lập trình viên. Năng suất ở đây cần được hiểu theo nghĩa ngoài việc tiết kiệm một byte hoặc một phần ngàn giây, điều quan trọng hơn hướng đến tính đúng đắn, dễ đọc, dễ thực hiện, dễ phát triển, tận dụng tối đa khả năng của ngôn ngữ lập trình, tận dụng tối đa khả năng c ủa thiết bị mà không phụ thuộc vào thiết bị. Tóm lại, kỹ thuật lập trình hướng đến mục tiêu cuối cùng là sử dụng tối ưu sự phối hợp giữa người và máy tính. Chỉ có thể kiểm soát được chương trình nếu nó được kiến trúc một cách đơn giản và tao nhã. Lập trình viên trước hết phải vượt lên trên, thoát khỏi những ràng buộc cụ thể về văn phạm củ a ngôn ngữ lập trình. Tiêu chuẩn đầu tiên của một lập trình viên là phải diễn đạt trong sáng và đúng đắn các chỉ thị chứ không phải biết bao nhiêu ngôn ngữ lập trình. Cần tránh việc “tư duy kiểu lập trình Visual Basic” hoặc “lập trình Pascal”. Trong thời kỳ đầu của Công nghệ Thông tin, các lập trình viên xây dựng chương trình bằng các ngôn ngữ lập trình bậc thấp, quá trình nạp và theo dõi hoạt động của chương trình một cách trực tiếp. Do v ậy, trước những năm 60, việc lập trình được coi như là hoạt động nghệ thuật tài nghệ cá nhân hơn là khoa học. Một số người nắm vững một số ngôn ngữ lập trình và tận dụng cấu hình vật lý cụ thể của hệ thống máy tính, có thể coi là chuyên gia nắm bắt được bí ẩn của nghệ thuật lập trình. Các hệ thống máy tính trong giai đoạn này có cấu hình yếu. Các chươ ng trình được xây dựng bằng kỹ thuật lập trình tuyến tính mà nổi bật nhất là ngôn ngữ lập trình Assembler và Fortran. Với phương pháp lập trình tuyến tính, lập trình viên chỉ được thể hiện chương trình trên hai cấu trúc lệnh là tuần tự (sequential) và nhảy không điều kiện (goto). Sau giai đoạn này, các nhà tin học lý thuyết đã đi sâu nghiên cứu bản chất của ngôn ngữ lập trình, thuật toán và hoạt động lập trình. Kế t quả nổi bật nhất của giai đoạn này là Knuth đã xuất bản 3 tập sách mang tên “Nghệ thuật lập trình” giới thiệu cơ sở lý thuyết bảo đảm toán học và các thuật toán. Năm 1968, Dijkstra khẳng định một số lỗi do lệnh GOTO gây nên không thể xác định được điểm bắt đầu của lỗi. Ngoài ra, do nhu cầu thực tế các phần mềm đòi hỏi ngày càng phức tạp, trong khi đ ó phương pháp lập trình tuyến tính tỏ ra kém hiệu quả và không thể kiểm soát được chương trình. Năm 1969, Hoarce đã phát biểu các tiên đề phục vụ cho việc chứng minh tính đúng đắn của chương trình. Sau đó, Dahl, Hoarce, Dijkstra đã phát triển thành ngôn ngữ lập trình có cấu trúc. 3 Theo phương pháp lập trình cấu trúc, chương trình được chia thành các chương trình con, mỗi chương trình con đảm nhận một công việc của hệ thống. Mỗi chương trình con lại chia thành những chương trình con nhỏ hơn và tiếp tục như vậy cho đến khi các chương trình con nhỏ đủ đơn giản trong cài đặt và sửa lỗi. Để triển khai các nguyên lý lập trình có cấu trúc, L. Wirth đã thiết kế và cài đặt ngôn ngữ ALGOL W là một biến thể của ALGOL 60. Sau này, K. L. Wirth ti ếp tục hoàn thiện trở thành ngôn ngữ lập trình Pascal. Năm 1978, Brian Barningham và Denit Ritche thiết kế ngôn ngữ lập trình C với tối thiểu các cấu trúc lệnh và hàm. Đồng thời, hai tác giả đã phát hành phiên bản Hệ điều hành UNIX viết chủ yếu bằng ngôn ngữ lập trình C, khẳng định thêm uy thế của C trong lập trình hệ thống. Từ những năm 90, phương pháp lập trình hướng đối tượng bắt đầu đượ c sử dụng và được những người làm tin học quan tâm nghiên cứu. Điểm căn bản của phương pháp này là thiết kế chương trình xoay quanh dữ liệu của hệ thống. Các thao tác xử lý của hệ thống được gắn liền với dữ liệu và như vậy, mỗi sự thay đổi nhỏ của dữ liệu chỉ ảnh hưởng đến một số nhỏ các hàm liên quan, Sự g ắn kết giữa dữ liệu và các hàm xử lý trên chúng tạo đối tượng. Ngoài ra, việc sử dụng lại và kế thừa làm tiết kiệm được mã nguồn, đồng thời tạo khả năng cho sự tiếp nối và mở rộng chương trình. Ngôn ngữ lập trình C++ kế thừa được các điểm mạnh của C và trở thành ngôn ngữ lập trình hướng đối tượng được chọn để minh họ a cho lập trình hướng đối tượng. Việc nắm bắt các khía cạnh độc đáo của ngôn ngữ và làm chủ các yếu tố cơ bản khi lập trình trong ngôn ngữ C++ sẽ là cơ sở để nâng cao hiểu biết và kỹ năng lập trình bằng ngôn ngữ lập trình Java, một công cụ không thể thiếu trong việc phát triển các ứng dụng trên mạng. 1.2 Những yêu cầu với 1 chương trình máy tính Lập trình là viết ra những chương trình nhằm giúp máy tính giải quyết những bài toán, những yêu cầu nào đó trong thực tế. Các yêu cầu nhất định cho việc viết chương trình: +Đúng đắn: chương trình phải đáp ứng được những yêu cầu được đặt ra. +Chính xác. +Tin cậy: bảo đảm cùng 1 dữ liệu nhập vào thì kết quả trả ra luôn luôn giống nhau +Tổng quát: người lập trình viên phải có khả năng nhìn thấy tấ t cả mọi khả năng có thể của dữ liệu nhập vào và chương trình phải làm việc tốt được với mọi dữ liệu nhập vào. +An toàn: chương trình phải làm việc tốt ngay cả trong những điều kiện bất thường xảy ra, hạn chế việc chương trình bị “treo” trong quá trình chạy vì nhiều nguyên nhân như dữ liệu nhập vào không phù hợp, lỗi truy cập vv +Hiệu quả: Ch ương trình phải tiết kiệm tài nguyên ở mức thấp nhất có thể, chạy nhanh nhất ở mức có thể +Dễ nâng cấp, bảo trì. 4 1.3 Các xu hướng thiết kế chương trình Hiện nay có 2 xu hướng chính được chọn lựa trong việc thiết kế chương trình máy tính là: hướng thủ tục và hướng đối tượng 1.3.1 Hướng thủ tục (POP: Procedure Oriented Programming) Thông qua 1 quá trình phân tích nhất định, lập trình viên sẽ tách vấn đề cần giải quyết hay yêu cầu ban đầu thành những bài toán con giản hơn và giải quyết từng bài toán một. Việc này sẽ giúp thực hiện được các bài toán phức tạp một cách dễ dàng hơn. Ngoài ra, còn giúp cho ch ương trình dễ đọc, dễ bảo trì hơn. Lập trình cấu trúc là một tập con của lập trình thủ tục. Trong một chương trình máy tính, các khối chức năng có thể được thực hiện không chỉ theo tuần tự mà còn có thể theo các tình huống và lặp lại nhiều lần. Phương pháp lập trình cấu trúc được dựa trên các mô hình toán học của Bohm và Guiseppe, theo đó, một chương trình máy tính có thể được viết dựa trên ba cấu trúc: tuần t ự, chọn lựa và vòng lặp. Tuần tự là các câu lệnh được thực hiện theo thứ tự nhất định: từ trên xuống dưới. Chọn lựa là sự qui định chương trình sẽ chọn lựa lệnh nào thực hiện phụ thuộc vào sự thoả mãn các điều kiện nhất định. Vòng lặp thể hiện sự thực hiện có tính lặp một số đoạn l ệnh của chương trình khi các điều kiện nào đó vẫn được thỏa mãn. Thông qua các cấu trúc trên, mã chương trình trở nên sáng sủa và dễ đọc. Vào cuối những năm 60, ngôn ngữ lập trình có cấu trúc ra đời. Các chương trình có cấu trúc được tổ chức theo các công việc mà chúng thực hiện. Về bản chất, chương trình chia nhỏ thành các chương trình con riêng rẽ (còn gọi là hàm hay thủ tục) thực hiện các công việc rời rạc trong quá trình lớn hơ n, phức tạp hơn. Các hàm này được giữ càng độc lập với nhau càng nhiều càng tốt, mỗi hàm có dữ liệu và logic riêng. Thông tin được chuyển giao giữa các hàm thông qua các tham số, các hàm có thể có các biến cục bộ mà không một ai nằm bên ngoài phạm vi của hàm lại có thể truy xuất được chúng. Như vậy, các hàm có thể được xem là các chương trình con được đặt chung với nhau để xây dựng nên một ứng dụng. Mục tiêu là làm sao cho việc triển khai các phần mềm d ễ dàng hơn đối với các lập trình viên mà vẫn cải thiện được tính tin cậy và dễ bảo quản chương trình. Một chương trình có cấu trúc được hình thành bằng cách phân chia các chức năng cơ bản của chương trình thành các phần nhỏ mà sau đó trở thành các hàm. Bằng cách phân chia các công việc vào trong các hàm, chương trình có cấu trúc có thể làm giảm khả năng của một hàm này ảnh hưởng đến một hàm khác. Việc này cũng làm cho việc tách các vấn đề trở nên dễ dàng hơn. Sự gói gọn này cho phép có thể viết các chương trình sáng sủa hơn và giữ được điều khiển trên từng hàm. Các tham số và biến cục bộ có phạm vi nhỏ hơn và dễ kiểm soát hơn. Cách tổ chức tốt hơn này giúp quản lý logic của cấu trúc chương trình, làm cho việc triển khai và bảo trì chương trình hữu hiện hơn. 5 Một khái niệm lớn đã được đưa ra trong lập trình có cấu trúc là sự trừu tượng hóa (Abstraction). Sự trừu tượng hóa có thể xem như khả năng quan sát một sự việc mà không cần xem xét đến các chi tiết bên trong của nó. Trong một chương trình có cấu trúc, chỉ cần biết một hàm đã cho có thể làm được một công việc cụ thể gì là đủ. Điều này gọi là sự trừu tượng hóa theo chức năng (Functional abstraction) và là nề n tảng của lập trình có cấu trúc. Ngày nay, các kỹ thuật thiết kế và lập trình có cấu trúc được sử rộng rãi. Gần như mọi ngôn ngữ lập trình đều có các phương tiện cần thiết để cho phép lập trình có cấu trúc. Chương trình có cấu trúc dễ viết, dễ bảo dưỡng hơn các chương trình không cấu trúc. Sự nâng cấp như vậy cho các kiểu dữ liệu trong các ứng dụng mà các lập trình viên đ ang viết cũng đang tiếp tục diễn ra. Khi độ phức tạp của một chương trình tăng lên, sự phụ thuộc của nó vào các kiểu dữ liệu cơ bản mà nó xử lý cũng tăng theo. Vấn đề trở rõ ràng là cấu trúc dữ liệu trong chương trình quan trọng chẳng kém gì các phép toán thực hiện trên chúng. Điều này càng trở rõ ràng hơn khi kích thước của chương trình càng tăng. Các kiểu dữ liệu được x ử lý trong nhiều hàm khác nhau bên trong một chương trình có cấu trúc. Khi có sự thay đổi trong các dữ liệu này thì cũng cần phải thực hiện cả các thay đổi ở mọi nơi có các thao tác tác động trên chúng. Đây có thể là một công việc tốn thời gian và kém hiệu quả đối với các chương trình có hàng ngàn dòng lệnh và hàng trăm hàm trở lên. Một yếu điểm nữa của việc lập trình có cấu trúc là khi có nhiều lập trình viên làm việc theo nhóm cùng một ứng dụng nào đó. Trong một chương trình có cấu trúc, các lập trình viên được phân công viết một tập hợp các hàm và các kiểu dữ liệu. Vì có nhiều lập trình viên khác nhau quản lý các hàm riêng, có liên quan đến các kiểu dữ liệu dùng chung nên các thay đổi mà lập trình viên tạo ra trên một phần tử dữ liệu sẽ làm ảnh hưởng đến công việc của tất cả các người còn lại trong nhóm. Mặc dù trong bối cảnh làm việc theo nhóm, việc viết các chương trình có cấu trúc thì dễ dàng hơn nhưng sai sót trong việc trao đổi thông tin giữa các thành viên trong nhóm có thể dẫn tới hậu quả là mất rất nhiều thời gian để sửa chữa chương trình. 1.3.2 Hướng đối tượng(OOP: Object Oriented Programming) Lập trình hướng đối ượng hay chi tiết hơn là Lập trình định hướng đối tượng, chính là phương pháp lập trình lấy đối tượng làm nền tảng để xây dựng thuật giải, xây dựng chương trình. Thực chất đây không phải là một phương pháp mới mà là một cách nhìn mới trong việc lập trình. Đối tượng ở đây không chỉ đơn giản là “dữ liệu” mà mỗi đối tượng ngoài dữ liệu còn mang trong nó những thao tác, hành vi của riêng đối tượng đó và đối tượng tương tác với các đối tượng khác thông qua các hành vi này. Và các đối tượng giống nhau sẽ có cùng những hành vi giống nhau. Đây là tính đóng gói của hướng đối tượng. Ngoài ra hướng đối t ượng còn có tính thừa kế nghĩa là tất cả những kiểu đối tượng con 6 dẫn xuất từ cùng một kiểu đối tượng cha sẽ được thừa kế những “đặc tính” di truyền của cha. Lập trình hướng đối tượng liên kết cấu trúc dữ liệu với các thao tác, theo cách mà tất cả thường nghĩ về thế giới quanh mình. Chúng ta thường gắn một số các hoạt động cụ thể với một loại hoạt động nào đó và đặt các giả thiết củ a mình trên các quan hệ đó. Mỗi một đối tượng có riêng cho mình một bản sao các phần tử dữ liệu của lớp còn gọi là các biến thực thể (Instance variable). Các phương thức định nghĩa trong một lớp có thể được gọi bởi các đối tượng của lớp đó. Điều này được gọi là gửi một thông điệp (Message) cho đối tượng. Các thông điệp này phụ thuộc vào đối t ượng, chỉ đối tượng nào nhận thông điệp mới phải làm việc theo thông điệp đó. Các đối tượng đều độc lập với nhau vì vậy các thay đổi trên các biến thể hiện của đối tượng này không ảnh hưởng gì trên các biến thể hiện của các đối tượng khác và việc gửi thông điệp cho một đối tượng này không ảnh hưởng gì đến các đối tượng khác. Như vậy, đối tượng được hiểu theo nghĩa là một thực thể mà trong đó các dữ liệu và phương thức tác động lên dữ liệu đã được đóng gói lại với nhau. Hay “đối tượng được đặc trưng bởi một số thao tác (operation) và các thông tin (information) ghi nhớ sự tác động của các thao tác này.” Các thao tác trong đối tượng được gọi là các phương thức hay hành vi của đối tượng đó. Phương thức và dữ liệu của đối tượng luôn tác động lẫn nhau và có vai trò ngang nhau trong đối tượng, Phương thức của đối tượng được qui định bởi dữ liệu và ngược lại, dữ liệu của đối tượng được đặt trưng bởi các phương thức của đối tượng. Chính nhờ sự gắn bó đó, ta có thể gởi cùng một thông điệp đến những đối tượng khác nhau. Điều này giúp người lậ p trình không phải xử lý trong chương trình của mình một dãy các cấu trúc điều khiển tuỳ theo thông điệp nhận vào, mà chương trình được xử lý vào thời điểm thực hiện. Tóm lại, so sánh lập trình cấu trúc với chương trình con làm nền tảng: Chương trình = Cấu trúc dữ liệu + Thuật giải Trong lập trình hướng đối tượng chúng ta có: Đối tượng = Phương thức + Dữ liệu Đây là 2 quan điểm lậ p trình đang tồn tại và phát triển trong thế giới ngày nay. 1.4 Các phương pháp thiết kế 14.1 Phương pháp thiết kế Top-down Quá trình phân tích bài toán được thực hiện từ trên xuống dưới. Đi từ vấn đề chung nhất đến vấn đề cụ thể nhất. Từ mức trừu tượng mang tính chất tổng quan tới mức đơn giản nhất là đơn vị chương trình Đây là phương pháp thiết kế mang tính đi sâu vào tổng quát trước. Ở từng tầng của phương pháp thiết kế này ch ức năng tổng quát nhất được đem ra làm tên gọi, sau đó bạn phát triển những tầng tiếp theo nhỏ hơn của chức năng đó. Và cứ tiếp tục phân 7 tầng như vậy cho tới khi các chức năng đã được đơn giản ở mức có thể thực hiện dễ dàng và hiệu quả. Quá trình phân rã bài toán được thực hiện theo từng mức khác nhau. Mức thấp nhất là mức tổng quan (gọi là Mức 0) cho phép nhìn tổng thể hệ thống thông qua các chức năng của nó. Mức này trả lời câu hỏi “Hệ thống có thể thực hiện những gì?”. Mứ c tiếp theo là mức các chức năng chính, các chức năng được mô tả cụ thể. Một hệ thống có thể được phân tích thành nhiều mức khác nhau, mức thấp được sử dụng các dịch vụ ở mức cao. Quá trình phân tích tiếp tục phân rã hệ thống theo từng chức năng cho đến khi nhận được mức các đơn thể (function, procedure) khi đó tiến hành cài đặt. Ví dụ: Cần viết chương trình dọc dữ li ệu từ một tập tin chứa các thông tin về số nhân viên, thông tin của từng nhân viên của một công ty, xử lí và trả lại thông tin về lương sẽ trả tháng này của từng nhân viên. Như vậy nếu để y nguyên như vậy mà làm sẽ rất không thuận tiện và khi có sai sót sẽ rất khó dò lỗi trong một khối chương trình gộp chung như vậy. Vì vậy, tách quá chương trình ra thành một số quá trình đơn giản hơn như sau: - Xử lí việc đọc tập tin. - Xứ lí thông tin đọc được từ tập tin. - Xử lí việc thông báo kết quả. Từ các quá trình này có thể tách thêm các quá trình con nữa nếu cần. Như vậy khi xảy ra lỗi trong lập trình thì việc tìm lỗi và sữ chữa sẽ dễ dàng hơn. Chẳng hạn khi lỗi thuộc về việc đọc tập tin thì chỉ cần dò tìm lỗi trong đoạn chương trình viết dùng để đọc file. 1.4.2 Phươ ng pháp thiết kế Bottom-up Quá trình phân tích bài toán được thực hiện từ dưới lên trên. Đi từ vấn đề riêng đến vấn đề chung. Từ mức giản nhất là đơn vị chương trình đến mức tổng thể Trong phương pháp Top-Down phân rã vấn đề một cách hệ thông từ trên xuống dưới được ứng dụng chủ yếu cho quá trình phân tích và thiết kế hệ thống, đối với phương pháp Bottom-Up thường được sử d ụng cho quá trình cái đặt hệ thống. Ngược lại với kiểu thiết kế top-down là kiểu bottom-up. Kiểu này được sử dụng chủ yếu khi cần xây dựng chương trình từ những thứ đã có sẵn. Như vậy, chỉ cần tìm các thành phần cần thiết từ những thứ đã có. Một ví dụ đơn giản là khi sử dụng các hàm đã có sẵn và được hỗ trợ của ngôn ngữ lập trình để xây dựng một ứng dụng đơn giản nào đó. 1.4.3 Ví dụ: Xây dựng các phép toán trên phân số Mức 0: Xét một cặp PS=<P,F>, trong đó P là tập các phân số và F là tập các phép toán trên phân số: F={+, - , * , /}. Những bộ đôi như vậy được gọi là đại số hệ. Tổng quát một đại số hệ A=<P,F> là một bộ đôi trong đó P là tập các phần tử gọi là tập nền, F là các phép toán trên P. Mỗi phần t ử f trong F là một ánh xạ f: P n → P trong đó P n là ký hiệu biểu diễn cho tích Descartes bậc n. Tập các phân số P gồm các cặp tử số và mẫu số, trong đó tử số là số nguyên và mẫu số là số tự nhiên. 8 P = {x/y: x∈Z , y∈N} F={+, - , * , /} với các phép toán là các ánh xạ: P*P → P Mức 1: Cụ thể hơn các phép toán phân số: +: P*P → P z = x+y được mô tả: tử số(z)=tửsố(x) * mẫusố(y)+ tửsố(y)*mẫusố(x); mẫu số (z) = mẫusố(x)*mẫusố(y) ; tối giản(z) ; -: P*P → P z = x-y được mô tả: tử số(z)=tửsố(x) * mẫusố(y)+ tửsố(y)*mẫusố(x); mẫu số (z) = mẫusố(x)*mẫusố(y) ; tối giản(z) ; *: P*P → P z = x*y được mô tả: tử số(z)=tử số(x) * tử số(y) ; mẫu số (z) = mẫusố(x) * mẫusố (y); tối giản(z) ; /: P*P → P z = x/y được mô tả: yêu cầu : tử số (y) ≠0 ; tử số(z)=tử số(x) * mẫu số(y) ; mẫu số (z) = mẫusố(x) * tử số (y); tối giản(z) ; M ức 2: Tiếp tục triển khai thao tác tối giản : tối giản(x): được mô tả: d=USCLN(tử số(x), mẫu số (x)); tử số(x) = tử số(x) / d ; mẫu số(x) = mẫusố(x) / d ; Mức 3: Triển khai thao tác tìm USCLN : USCLN: N*N → N: trong khi (a ≠ b) Nếu (a>b) thì a=a-b ngược lại b=b-a USCLN =a Mức 4: 1. Mô tả kiểu phân số P = {x/y: x∈Z , y∈N} Nếu p=x/y thì Tử số (p) = x; Mẫu số (p) = y ; 2. Phép cộng 2 phân số +: P*P → P Input: x,y ∈ P Output: z ∈ P : z= x+y tử số(z)=tửsố(x) * mẫusố(y)+ mẫusố(y)*tửsố(x); mẫu số (z) = mẫusố(x)*mẫusố(y) ; tối giản(z) ; 3. Phép trừ 2 phân số 9 +: P*P → P Input: x,y ∈ P Output: z ∈ P : z= x-y tử số(z)=tửsố(x) * mẫusố(y)- mẫusố(y)*tửsố(x); mẫu số (z) = mẫusố(x)*mẫusố(y) ; tối giản(z) ; 4. Phép nhân 2 phân số +: P*P → P Input: x,y ∈ P Output: z ∈ P : z= x*y tử số(z)=tử số(x) * tử số(y) ; mẫu số (z) = mẫusố(x) * mẫusố (y); tối giản(z) ; 5. Phép chia 2 phân số +: P*P → P Input: x,y ∈ P Output: z ∈ P : z= x/y Điều kiện : tử số (y) ≠ 0 Nếu tử số (y) =0 thì Báo lỗi (Chia cho 0) ; Dừng chương trình ; tử số(z)=tử số(x) * mẫu số(y) ; mẫu số (z) = mẫusố(x) * tử số (y); Nếu mẫu số (z) <0 thì (*Do tửsố(y)<0*) Tử số (z) = - Tử số (z) ; Mẫusố (z) = - Mẫusố(z) tối giản(z) ; 6. Tìm USCLN USCLN: N*N → N Input: x,y ∈ N Output: d ∈ N (*là uscnn của x và y*) trong khi (a ≠ b) Nếu (a>b) thì a=a-b ngược lại b=b-a USCLN =a 7. Xuất phân số ra màn hình Input: p∈ P Output: dạng biểu diễn của p ra màn hình in (tử số(p),’ /’,mẫu số(p)); 10 //Chuong trinh thuc hien cac phep toan phan so #include <stdio.h> #include <conio.h> typedef struct { int tu,mau; }phanso; //Ham nhap pha nso: void Nhap(phanso *ps) { printf("\nNhap tu so:"); scanf("%d",&ps->tu); printf("Nhap mau so:"); scanf("%d",&ps->mau); } //Ham in phan so ra man hinh void Inra(phanso ps) { if(ps.mau ==0) printf("Co loi \n"); else printf(" %d/%d ",ps.tu,ps.mau); } //Ham tim uscln int uscln(int a,int b) { while (a!=b) if (a>b) a-=b; else b-=a; return a; } //Toi gian 1 phan so void toigian(phanso *ps) { int t; t=uscln(ps->tu,ps->mau); ps->tu /=t; ps->mau /=t; } //HAm cong 2 phan so ps1,ps2 ket qua ps3 void cong(phanso ps1,phanso ps2, phanso *ps3) { ps3->tu = ps1.tu*ps2.mau + ps1.mau * ps2.tu; ps3->mau = ps1.mau * ps2.mau; toigian(ps3); } [...]... gợi ý cho trình biên dịch thực hiện Nói chung, việc sử dụng inline nên có hạn chế chỉ cho các hàm đơn giản được sử dụng thường xuyên mà thôi Việc sử dụng inline cho các hàm dài và phức tạp quá thì chắc chắn bị bỏ qua bởi trình biên dịch 3.7 Đệ qui Một hàm gọi chính nó được gọi là đệ qui Đệ qui là một kỹ thuật lập trình tổng quát có thể ứng dụng cho các bài toán mà có thể định nghĩa theo thuật ngữ của... xếp để khử đệ qui của chương trình Nếu một chương trình con đệ qui P(x) được gọi từ chương trình chính ta nói chương trình con được thực hiện ở mức 1 Chương trình con này gọi chính nó, ta nói nó đi sâu vào mức 2 cho đến một mức k Rõ ràng mức k phải thực hiện xong thì mức k-1 mới được thực hiện tiếp tục, hay ta còn nói là chương trình con quay về mức k-1 Trong khi một chương trình con từ mức i đi vào... phải tính (k-2)!, , suy ra cuối cùng phải tính được 0!, nhưng vì 0!=1 nên qúa trình kết thúc Các ngôn ngữ lập trình cho phép các chương trình con đệ qui Một thủ tục hay hàm có thể gọi chính nó, khi đó ta nói có sự đệ qui // Ham tinh n! bang de qui long gt(int n) { if (n==0) return 1; else return n*gt(n-1); } Khi nhập n=4, qúa trình gọi các hàm được diễn giải như sau: gt(4) =4*gt(3) =4*3*gt(2) =4*3*2*gt(1)... gian sang cọc đích } } Để khử đệ qui ta phải nắm nguyên tắc sau đây: Mỗi khi chương trình con đệ qui được gọi, ứng với việc đi từ mức i vào mức i+1, ta phải lưu trữ các biến cục bộ của chương trình con ở bước i vào ngăn xếp Ta cũng phải lưu "địa chỉ mã lệnh" chưa được thi hành của chương trình con ở mức i Tuy nhiên khi lập trình bằng ngôn ngữ cấp cao thì đây không phải là địa chỉ ô nhớ chứa mã lệnh của... số hàng lệnh được tạo ra sẵn cho một chương trình C++ thông qua hàm main Có hai cách định nghĩa một hàm main: int main (void); int main (int argc, const char* argv[]); Cách sau được sử dụng khi chương trình được dự tính để chấp nhận các đối số hàng lệnh Tham số đầu, argc, biểu thị số các đối số được truyền tới chương trình (bao gồm cả tên của chính chương trình) Tham số thứ hai, argv , là một mảng của... thấy được ở mức chương trình nên chúng cũng phải là duy nhất ở mức chương trình Điều này nghĩa là cùng các biến hoặc hàm toàn cục có thể không được định nghĩa nhiều hơn một lần ở mức toàn cục (Tuy nhiên chúng ta sẽ thấy sau này một tên hàm có thể được sử dụng lại) Thông thường các biến hay hàm toàn cục có thể được truy xuất từ mọi nơi trong chương trình Mỗi khối trong một chương trình định nghĩa một... cục tồn tại suốt thời gian thực hiện chương trình trong khi các biến cục bộ được tạo ra khi phạm vi của chúng bắt đầu và mất đi khi phạm vi của chúng kết thúc Không gian bộ nhớ cho các biến toàn cục được dành riêng trước khi sự thực hiện của chương trình bắt đầu nhưng ngược lại không gian bộ nhớ cho các biến cục bộ được cấp phát ở thời điểm thực hiện chương trình 3.4 Toán tử phạm vi Bởi vì phạm vi cục... các đối tượng động trong thời gian thực thi chương trình Không giống như các đối tượng bình thường (toàn cục và cục bộ) được cấp phát lưu trữ trên runtime stack, một đối tượng động được cấp phát vùng nhớ từ vùng lưu trữ khác được gọi là heap Các đối tượng không tuân theo các luật phạm vi thông thường Phạm vi của chúng được điều khiển rõ ràng bởi lập trình viên Tham chiếu (reference) cung cấp một tên... lệnh Khi một chương trình được thực thi dưới một hệ điều hành (như là DOS hay UNIX) nó có thể nhận không hay nhiều đối số từ dòng lệnh Các đối số này xuất hiện sau tên chương trình có thể thực thi và được phân cách bởi các khoảng trắng Bởi vì chúng xuất hiện trên cùng hàng nơi mà các lệnh của hệ điều hành phát ra nên chúng được gọi là các đối số hàng lệnh Ví dụ như xem xét một chương trình được đặt tên... động Ngoài vùng nhớ stack của chương trình (thành phần được sử dụng để lưu trữ các biến toàn cục và các khung stack cho các lời gọi hàm), một vùng bộ nhớ khác gọi là heap được cung cấp Heap được sử dụng cho việc cấp phát động các khối bộ nhớ trong thời gian thực thi chương trình Vì thế heap cũng được gọi là bộ nhớ động (dynamic memory) Vùng nhớ stack của chương trình cũng được gọi là bộ nhớ tĩnh (static . Bài giảng KỸ THUẬT LẬP TRÌNH (Programming Methodology) 2 Chương I: Tổng quan về Kỹ thuật lập trình 1.1 Tổng quan Lập trình là một trong những. của nghệ thuật lập trình. Các hệ thống máy tính trong giai đoạn này có cấu hình yếu. Các chươ ng trình được xây dựng bằng kỹ thuật lập trình tuyến tính mà nổi bật nhất là ngôn ngữ lập trình Assembler. tảng của lập trình có cấu trúc. Ngày nay, các kỹ thuật thiết kế và lập trình có cấu trúc được sử rộng rãi. Gần như mọi ngôn ngữ lập trình đều có các phương tiện cần thiết để cho phép lập trình