CHƯƠNG 1 GIỚI THIỆU Mục tiêu: Sau khi kết thúc chương này, người đọc có thể: - Phân biệt được các loại ngôn ngữ lập trình. - Vẽ được lưu đồ giải thuật cho các yêu cầu lập trình. - Sử dụng được các thành phần cơ bản trong ngôn ngữ C: câu lệnh, câu chú thích, biến, hằng, phép toán. - Sử dụng được các hàm xuất, nhập dữ liệu trong C.
- Viết được các chương trình C cơ bản theo đúng cấu trúc chương trình. CHƯƠNG TRÌNH VÀ NGÔN NGỮ LẬP TRÌNH Chương trình máy tính (computer program) là một chuỗi các lệnh được viết bởi một loại ngôn ngữ lập trình để thực hiện một hoặc một số tác vụ nào đó. Trong đó ngôn ngữ lập trình là một tập quy ước cụ thể được sử dụng để viết chương trình cho máy tính. Nói cách khác, chương trình được xem như một loạt các lệnh mà máy tính có thể đọc hiểu và thực thi theo đó.
Khi nói đến chương trình máy tính, người ta thường hình dung ra chương trình được chạy trên một máy tính. Tuy nhiên, chương trình, nhìn ở góc độ kỹ thuật thì là một chuỗi các mã lệnh dùng để điều khiển phần cứng, cụ thể là bộ vi xử lý, bộ vi điều khiển. Có nhiều loại ngôn ngữ lập trình khác nhau. Các ngôn ngữ lập trình được phân loại theo mức độ trừu tượng, trong đó gồm có: 9 Ngôn ngữ máy (machine language) hay còn được gọi là mã máy (machine code).
Ngôn ngữ lập trình cấp thấp (low-level programming language). Ngôn ngữ lập trình cấp cao (high-level programming language). Phân loại ngôn ngữ lập trình Ngôn ngữ cấp thấp cũng được chia ra 2 mức khác nhau, ngôn ngữ máy hay mã máy và hợp ngữ (assembly language). Ngôn ngữ máy (machine code) là các đoạn mã hệ 16 (hexadecimal code) hoặc mã nhị phân (binary code) được sử dụng để lập trình cho các hệ thống máy tính đầu tiên và được xem là thế hệ đầu tiên của ngôn ngữ lập trình.
Mã máy được viết dưới dạng nhị phân (0 và 1) giúp máy tính (hay phần cứng hệ thống số) có thể đọc và thực thi trực tiếp các tác vụ mà người lập trình thiết kế. Một lợi thế của ngôn ngữ máy là máy tính có thể đọc trực tiếp và thực thi mà không cần tới một trình biên dịch, hay chuyển đổi nào. Điều này giúp các chương trình được 10 viết dưới dạng ngôn ngữ máy có thể thực thi nhanh và chính xác. Tuy nhiên, bên cạnh những ưu điểm, lập trình bằng ngôn ngữ máy cũng có nhiều nhược điểm.
Cụ thể là các mã nhị phân làm cho người lập trình khó nhớ, khó hiểu, khó chỉnh sửa. Hơn nữa, việc sửa lỗi, tìm lỗi chương trình cũng trở nên khó khăn thông qua việc dò, tham chiếu các mã nhị phân với các lệnh. Một ví dụ chương trình được viết bằng ngôn ngữ máy như sau: Lệnh bằng mã nhị phân Lệnh bằng mã Hex 0010 0001 0000 0100 2104 0001 0001 0000 0101 1105 0011 0001 0000 0110 3106 0111 0000 0000 0001 7001 0000 0000 0101 0011 0053 1111 1111 1111 1110 FFFE Hợp ngữ (Assemly language) là ngôn ngữ thế hệ thứ 2 của ngôn ngữ lập trình. Thay vì sử dụng mã nhị phân, 0 và 1, để thể hiện các lệnh, hợp ngữ sử dụng các từ khóa, các ký hiệu bằng tiếng Anh để diễn tả các câu lệnh.
Hợp ngữ giúp cho người lập trình có thể hiểu được mỗi dòng lệnh dễ dàng hơn, từ đó việc chỉnh sửa, thay đổi chương trình, cũng như quản lý chương trình đơn giản hơn so với lập trình bằng ngôn ngữ máy. Tuy nhiên, máy tính nói chung và các bộ xử lý nói riêng chỉ có thể hiểu được ngôn ngữ máy hay các mã nhị phân, do đó, cần một trình chuyển đổi hay biên dịch (compiler) để chuyển từ hợp ngữ sang mã máy, giúp máy tính nói chung và các bộ vi xử lý nói riêng có thể đọc hiểu và thực thi chương trình. 11 Ví dụ một chương trình được viết bằng hợp ngữ như sau: section .text global _start ;must be declared for linker (gcc) _start: ;tell linker entry point mov edx,len ;message length mov ecx,msg ;message to write mov ebx,1 ;file descriptor (stdout) mov eax,4 ;system call number (sys_write) int 0x80 ;call kernel mov edx,9 ;message length mov ecx,s2 ;message to write mov ebx,1 ;file descriptor (stdout) mov eax,4 ;system call number (sys_write) int 0x80 ;call kernel mov eax,1 ;system call number (sys_exit) int 0x80 ;call kernel section .data msg db ‘Displaying 9 stars’,0xa ;a message len equ $ - msg ;length of message s2 times 9 db ‘*’ Ngôn ngữ cấp cao (high-level programming language) là ngôn ngữ gần với ngôn ngữ con người và được sử dụng phổ biến hiện nay. Chương trình được viết bằng ngôn ngữ cấp cao giúp người lập trình dễ đọc, dễ hiểu, dễ chỉnh sửa.
Với ngôn ngữ cấp cao, người lập trình dễ dàng chuyển đổi ý tưởng, các giải thuật thành các đoạn chương trình mà không cần quan tâm nhiều đến việc quản lý bộ nhớ, quản lý các thanh ghi, các chi tiết phần cứng như đã làm trong lập trình bằng ngôn ngữ cấp thấp. Cũng giống như hợp ngữ, ngôn ngữ cấp cao cần được chuyển đổi sang mã máy (ngôn ngữ máy) trước khi được thực thi. Có nhiều ngôn ngữ cấp cao được phát triển đến thời điểm hiện tại. Trong đó một số ngôn ngữ hình thành lâu đời như C, Pascal, Fortran, Basic, Java.
12 Ví dụ, một chương trình viết bằng ngôn ngữ cấp cao như sau: #include <stdio.h> int main() { printf(“Hello, World!\n”); return 0; } 1. GIẢI THUẬT VÀ LƯU ĐỒ Một chương trình được xem như một sự kết hợp của giải thuật và cách thể hiện của giải thuật thông qua ngôn ngữ lập trình. Giải thuật (Algorithm) là các cách để giải quyết bài toán lập trình, hay phương pháp cụ thể để thực hiện các tác vụ. Giải thuật được xem là cốt lõi để giải quyết các vấn đề lập trình.
Giải thuật còn thể hiện các ý tưởng của người lập trình nhằm giúp chương trình đạt hiệu quả cao nhất. Chương trình cuối cùng là tập hợp của các miêu tả giải thuật thông qua một ngôn ngữ lập trình nào đó. Lập trình là một quá trình tư duy logic giải quyết một vấn đề nào đó. Do đó, giải thuật là một yếu tố quan trọng trong lập trình.
Ví dụ, để giải một phương trình bậc 2, người lập trình phải biết các bước cần thiết để tự giải một phương trình. Nói cách khác là người lập trình có thể tự giải được thông qua các bước, các bước đó chính là giải thuật. Khi chúng ta không biết giải quyết vấn đề từ đâu, thì thật khó để viết một chương trình máy tính để giải quyết vấn đề đó. Lưu đồ là thể hiện của giải thuật bằng hình ảnh.
Nó thể hiện các bước giải quyết một vấn đề dựa trên một giải thuật nào đó. Các sinh viên mới học lập trình hoặc đã biết lập trình ở mức cơ bản thường có thói quen bỏ qua bước vẽ lưu đồ nhằm tiết kiệm thời gian. Điều này mang tính chất chủ quan vì các bạn cho rằng mình đã quen với ngôn ngữ và các công việc lập trình. Việc viết lưu đồ mang tính hình thức và mất thêm thời gian, điều này có thể đúng với một số chương trình nhỏ, một vài ví dụ cơ bản mà các bạn 13 đã nắm trong đầu từng bước xử lý.
Tuy nhiên, sẽ trở nên tai hại khi xây dựng các chương trình xử lý ở mức độ phức tạp mà bỏ qua bước xây dựng lưu đồ. Khi bắt đầu một chương trình, các ý tưởng cần được liệt kê, phân tích một cách cụ thể. Tiếp theo đó, lưu đồ để thực hiện các ý tưởng, các yêu cầu đó phải được viết ra một cách cẩn thận. Thực tế cho thấy, nhiều sinh viên viết hoàn chỉnh chương trình trước rồi sau đó mới viết lại lưu đồ giải thuật do yêu cầu phải trình bày trong báo cáo.
Điều này đi ngược với quá trình lập trình. Việc xây dựng và kiểm tra kỹ lưu đồ cho phép người lập trình đánh giá, kiểm tra chương trình đã đáp ứng được yêu cầu hay chưa; nó cho phép người lập trình tìm ra được các lỗi mà chương trình khi chạy thực tế có thể mắc phải hoặc phát hiện một số trường hợp bị bỏ sót. Khi lưu đồ đã hoàn chỉnh, việc lập trình chỉ là một cách biên dịch từ các hình khối sang một ngôn ngữ nào đó. Vì thế, khi viết lưu đồ có thể dùng ngôn ngữ mô tả sao cho đọc hiểu được, không nhất thiết phải dùng một ngôn ngữ nhất định nào.
Người lập trình dựa vào các bộ nguyên tắc cụ thể của ngôn ngữ lập trình mà mình hướng tới, xây dựng chương trình từ lưu đồ. Như vậy, tính chính xác, tính khoa học, logic của một chương trình thể hiện ở chỗ xây dựng lưu đồ, giải thuật có logic, chính xác hay không. Nếu lưu đồ giải thuật chính xác và logic, mà chương trình chạy chưa chính xác thì giống như bạn viết một bài văn mà sai chính tả, hoặc bạn dịch một bài từ tiếng Việt sang tiếng Anh mà sai ngữ pháp, từ vựng. Vấn đề tác giả muốn nhấn mạnh ở đây là các bạn mới học lập trình cần xây dựng tốt lưu đồ giải thuật, cũng như học cách thể hiện ý tưởng thông qua lưu đồ, giải thuật.
Lưu đồ (Flowchart) là cách biểu diễn bằng hình ảnh của giải thuật hay các bước xử lý và thực hiện của chương trình. Lưu đồ được viết dưới dạng các khối được quy ước cụ thể nhằm giúp người lập trình có thể đọc hiểu và chuyển các ý tưởng, giải thuật sang ngôn ngữ lập trình. Trong quá trình vẽ lưu đồ giải thuật, các ký hiệu, từ khóa, ngôn ngữ thể hiện có thể tùy chọn sao cho người đọc có thể hiểu được. Ngôn ngữ thể hiện ở đây không nhất thiết là một ngôn ngữ lập trình cụ thể nào.
Nó có thể là một ngôn ngữ thông thường mà người không có kiến thức lập 14 trình cũng có thể đọc và hiểu được. Các ngôn ngữ dùng để biểu diễn trong lưu đồ như vậy còn được gọi là code giả (Psuedo code). Một số quy ước khi biểu diễn giải thuật dưới dạng lưu đồ như sau: Bắt đầu hay kết thúc của một chương trình. Nhập hay xuất dữ liệu Các xử lý, tính toán Rẽ nhánh hay các quyết định có điều kiện Chương trình con, hàm, thủ tục Các điểm đầu cuối dùng để nối lưu đồ khi sang trang Chiều đi của quá trình xử lý Ví dụ 1.
Lưu đồ cho chương trình cộng 2 số được nhập từ bàn phím. Start Declare variables num1, num2, and sum Read num1 and num2 sum ←num1+num2 Display sum Stop 15 Trong lưu đồ trên, điểm đầu cuối cho quá trình bắt đầu và kết thúc được phân biệt bởi từ khóa start và end trong hình oval.