Bài giảng Tin học cơ sở 2: Phần 1 cung cấp cho học viên những kiến thức về ngôn ngữ lập trình, thuật toán; một số kiến thức cơ sở về bộ kí tự, từ khóa, tên, cấu trúc chương trình trong C, biến, hằng, câu lệnh và các phép toán; các cấu trúc lệnh điều khiển; hàm và phạm vi hoạt động của biến;... Mời các bạn cùng tham khảo!
GIỚI THIỆU CHUNG
Ngôn ngữ lập trình
Trong phần "Tin học cơ sở 1", chúng ta đã khám phá các phần mềm Winword và Excel, được sử dụng chủ yếu cho soạn thảo văn bản và tính toán bảng Các phần mềm ứng dụng này thường có phạm vi chức năng rõ ràng và cung cấp nhiều công cụ để hoàn thành nhiệm vụ Tuy nhiên, người dùng thường bị giới hạn bởi các quy định của phần mềm, như việc khó khăn trong việc sử dụng Excel để giải quyết các bài toán phức tạp như phương trình vi phân hay hệ phương trình tuyến tính Mặc dù có nhiều phần mềm đa dạng trong các lĩnh vực như xây dựng, thiết kế, hội họa và âm nhạc, nhưng chúng vẫn không thể giải quyết hết mọi vấn đề phát sinh trong thực tế phong phú.
Ngôn ngữ lập trình là một công cụ thiết yếu không chỉ cho các chuyên gia công nghệ thông tin mà còn cho những người sử dụng, đặc biệt là cán bộ kỹ thuật Nó cung cấp phần mềm linh hoạt và đa năng, giúp người dùng thực hiện nhiều nhiệm vụ khác nhau trên máy tính Ngôn ngữ lập trình bao gồm một tập hợp từ khóa và quy tắc cú pháp, cho phép biên soạn các lệnh để máy tính thực hiện theo yêu cầu của người sử dụng.
Máy tính chỉ có thể biểu diễn các số 0 và 1, vì vậy ngôn ngữ mà máy hiểu trực tiếp là ngôn ngữ máy, trong đó các lệnh được thể hiện dưới dạng dãy số nhị phân Tất cả các ngôn ngữ lập trình khác đều cần phải được thông dịch hoặc biên dịch sang ngôn ngữ máy để máy tính có thể thực thi.
Compiler - biên dịch thành 1 chương trình ngôn ngữ máy hoàn chỉnh, do vậy chạy nhanh hơn thông dịch)
Có nhiều loại ngôn ngữ lập trình, và không có ngôn ngữ nào có thể đáp ứng mọi nhu cầu của lập trình viên Các ngôn ngữ lập trình thường được chia thành hai loại chính: ngôn ngữ bậc thấp và ngôn ngữ bậc cao.
Ngôn ngữ lập trình bậc thấp (low-level programming language):
Hợp ngữ, hay còn gọi là ngôn ngữ lập trình bậc thấp, là một dạng ngôn ngữ máy với các mã biểu thị chức năng chính mà máy tính thực hiện Hợp ngữ khác với ngôn ngữ máy ở chỗ nó sử dụng các ký hiệu dễ hiểu hơn để lập trình, giúp lập trình viên tương tác với phần cứng một cách hiệu quả hơn.
Lập trình bằng hợp ngữ rất phức tạp và tốn thời gian, với nhiều dòng mã cần thiết chỉ để thực hiện những phép toán đơn giản như cộng hai số Các chương trình hợp ngữ thường khó viết, thiếu cấu trúc rõ ràng và khó chuyển đổi giữa các loại máy tính khác nhau vì chúng phụ thuộc vào tập lệnh của từng bộ vi xử lý Mặc dù mã hợp ngữ gọn và chạy nhanh, khiến nó trở thành lựa chọn phổ biến cho các hệ điều hành, nhưng do sự phức tạp trong lập trình, nhiều nhà phát triển phần mềm chuyên dụng đã chuyển sang sử dụng ngôn ngữ C Ngôn ngữ C, được phát triển bởi Bell Laboratories của AT&T, kết hợp cấu trúc của ngôn ngữ bậc cao với hiệu suất của hợp ngữ, cho phép nhúng các lệnh hợp ngữ vào trong chương trình.
Ngôn ngữ lập trình bậc cao:
Các ngôn ngữ lập trình bậc cao như Basic, Pascal, C, C++ cho phép lập trình viên viết chương trình bằng các từ khóa gần gũi với ngôn ngữ tự nhiên Chúng được gọi là "bậc cao" vì giúp lập trình viên không phải lo lắng về cách mà máy tính thực hiện từng lệnh, vì bộ phận thông dịch hoặc biên dịch sẽ xử lý các chi tiết này Một câu lệnh trong ngôn ngữ bậc cao tương ứng với nhiều lệnh ngôn ngữ máy, giúp tăng tốc độ lập trình Tuy nhiên, chương trình ngôn ngữ máy được dịch từ mã nguồn bậc cao thường chứa nhiều chi tiết thừa, dẫn đến tốc độ chạy chậm hơn so với chương trình viết bằng hợp ngữ Thông thường, một trình biên dịch có thể sinh ra số lệnh mã máy gấp đôi hoặc nhiều hơn so với số lệnh cần thiết nếu viết bằng mã máy.
Một cách phân loại khác của các ngôn ngữ lập trình:
Ngôn ngữ thủ tục yêu cầu lập trình viên xác định các bước cụ thể mà máy tính cần thực hiện để hoàn thành một nhiệm vụ nhất định Một số ví dụ điển hình của ngôn ngữ thủ tục bao gồm Basic, C và Fortran.
Ngôn ngữ khai báo định nghĩa các yếu tố và quan hệ, cho phép xếp hàng kết quả xác định, ví dụ như Prolog và SQL Quan trọng trong lập trình chuyên dụng là môdun hóa ngôn ngữ, giúp phân phối nhiệm vụ cho các thành viên trong nhóm lập trình Ngôn ngữ lập trình môdun như Module-2 hoặc ngôn ngữ hướng đối tượng như C++ cho phép lập trình viên tập trung vào mã hóa, biên dịch và gỡ rối các module riêng biệt Mỗi module có thể được kiểm tra riêng lẻ, và khi hoạt động tốt, chúng sẽ được liên kết mà không gặp trục trặc.
Thuật toán (Algorithm)
Thuật ngữ Algorithm đƣợc dịch ra tiếng Việt là thuật toán, thuật giải hoặc giải thuật Ở đây dùng từ thuật toán là cách gọi quen thuộc với nhiều người
Thuật toán là một chuỗi các bước hữu hạn, với mỗi bước mô tả rõ ràng các phép toán hoặc hành động cần thực hiện nhằm giải quyết một vấn đề Để nắm bắt đầy đủ khái niệm thuật toán, chúng ta cần xem xét 6 đặc trưng cơ bản của nó.
Input Mỗi thuật toán thường có một số dữ liệu vào
Output Mỗi thuật toán thường có một số dữ liệu ra
Tính xác định (Definiteness) Mỗi bước được mô tả chính xác, chỉ có một cách hiểu duy nhất và đủ đơn giản để có thể thực hiện đƣợc
Tính dừng (Finiteness) Thuật toán phải dừng sau một số hữu hạn bước thực hiện
Tính hiệu quả (Effectiveness) Các phép toán trong các bước phải đủ đơn giản để có thể thực hiện đƣợc
Tính tổng quát (Generalness) Thuật toán phải có tính tổng quát, có thể áp dụng cho một lớp đối tƣợng
Thuật toán Euclid: Tìm ước số chung lớn nhất của hai số tự nhiên m,n
Output: g là ước số chung lớn nhất của m và n
Ngược lại (r>0) m:=n; n:=r và quay lại bước 1.
Sự ra đời và phát triển của ngôn ngữ C
Vào năm 1970, Ken Thompson đã phát triển ngôn ngữ B cho hệ điều hành UNIX trên máy tính DEC PD-7, với tên gọi B cũng là viết tắt của BCPL (Basic Combined Programming Language) do Martin Richards sáng tạo Đến năm 1972, Dennis Ritchie cùng Ken Thompson đã cho ra đời ngôn ngữ C nhằm nâng cao hiệu quả của ngôn ngữ B Ban đầu, C không được ưa chuộng, nhưng sau khi D Ritchie xuất bản cuốn "The C Programming Language", ngôn ngữ này nhanh chóng thu hút sự chú ý và trở nên phổ biến C đã được sử dụng để phát triển hệ điều hành đa nhiệm UNIX, O/S 2 và ngôn ngữ Dbase Ngôn ngữ C đã trải qua nhiều phiên bản cải tiến, bao gồm Turbo C từ phiên bản 1 đến 5 và Microsoft C từ phiên bản 1 đến 6 Hiện nay, C đã được phát triển thành C++ với ba trình biên dịch nổi bật: Borland C++, Visual C++ và Turbo C++.
Mặc dù có nhiều ngôn ngữ lập trình mới ra đời, ngôn ngữ C vẫn giữ vị trí quan trọng và được ưa chuộng C được sử dụng rộng rãi để phát triển phần mềm trong nhiều lĩnh vực, đặc biệt là trong khoa học kỹ thuật.
MỘT SỐ KIẾN THỨC CƠ SỞ
Bộ kí tự, từ khóa,tên
Mọi ngôn ngữ đều đƣợc xây dựng trên một bộ kí tự (các chữ, các kí hiệu) Đối với ngôn ngữ C sử dụng bộ kí tự sau:
Tập các chữ cái in hoa: A, B, C, D, , Z
Tập các chữ cái in thường: a, b, c, d, , z
Các kí tự không nhìn thấy: dấu trống (Space), dấu Tab, dấu xuống dòng (Enter),
Keywords are specific terms used within a language, each carrying its own unique meaning and function They cannot be redefined or used to name objects Below is a list of commonly used keywords in C: auto, break, base, char, continue, default, do, double, else, extern, float, for, goto, if, int, long, register, return, short, sizeof, static, struct, switch, typedef, union, unsigned, void, public, while, and volatile.
2.1.3 Tên và cách đặt tên
Tên hay còn gọi là định danh (identifier) là yếu tố quan trọng để gọi các biến, hằng hoặc hàm trong ngôn ngữ lập trình C Trước khi sử dụng, mọi tên phải được khai báo Tên được tạo thành từ các ký tự liên tiếp, bao gồm chữ cái a-z, A-Z, chữ số 0-9 và dấu gạch dưới, thường được dùng để liên kết các thành phần trong tên Tuy nhiên, tên không được bắt đầu bằng chữ số, không chứa các ký tự đặc biệt như dấu cách, dấu tab hay dấu chấm câu, và không được trùng với các từ khóa của ngôn ngữ C.
Ví dụ về cách đặt tên đúng: Delta, E_Mu_X, Function1
Ví dụ về cách đặt tên sai:
2Delta: bắt đầu bằng kí tự số
Ngôn ngữ C phân biệt chữ in hoa và chữ in thường, vì vậy các tên như x và X, While và while, For và for được xem là khác nhau Điều này yêu cầu chúng ta phải chú ý khi viết chương trình Thông thường, tên biến và hàm được đặt bằng chữ in thường, trong khi tên hằng được viết bằng chữ in hoa.
Khi lập trình, việc thêm chú thích và giải thích là cần thiết để làm cho mã nguồn dễ hiểu và dễ đọc hơn Những chú thích này không ảnh hưởng đến mã chương trình và sẽ bị trình biên dịch bỏ qua Chú thích có thể kéo dài qua nhiều dòng và được đánh dấu bằng cặp ký hiệu /* đoạn văn bản ghi chú */.
Cấu trúc chương trình trong C
2.2.1 Cấu trúc tổng quát của chương trình trong C
Chương trình tổng quát viết bằng ngôn ngữ C bao gồm 6 phần, với một số phần có thể tùy chọn dựa trên nội dung và ý định của lập trình viên.
Phần 1: Khai báo các chỉ thị đầu tệp và định nghĩa các hằng sử dụng trong chương trình
Phần 2: Định nghĩa các cấu trúc dữ liệu mới (user type) để sử dụng trong khi viết chương trình
Phần 3: Khai báo các biến ngoài (biến toàn cục) được sử dụng trong chương trình Phần 4: Khai báo nguyên mẫu cho hàm (Function Ptototype) Nếu khai báo qui cách xây dựng và chuyền tham biến cho hàm, compiler sẽ tự động kiểm tra giữa nguyên mẫu của hàm có phù hợp với phương thức xây dựng hàm hay không trong văn bản chương trình
Phần 5: Mô tả chi tiết các hàm, các hàm đƣợc mô tả phải phù hợp với nguyên mẫu đã đƣợc khai báo cho hàm
Phần 6: Hàm main(), hàm xác định điểm bắt đầu thực hiện chương trình và điểm kết thúc thực hiện chương trình
2.2.2 Các bước cơ bản khi viết chương trình ước 1: Soạn thảo chương trình (dùng Turbo )
Soạn thảo chương trình là quá trình sử dụng chương trình soạn thảo để viết mã nguồn Turbo C cung cấp chương trình soạn thảo, biên dịch và thực thi mã ngay trong môi trường C thông qua TC.EXE TC.EXE cũng được trang bị các phím chức năng tương tự như TURBO.EXE để hỗ trợ soạn thảo Khi lưu file văn bản chương trình, TC.EXE tự động gán phần mở rộng cho file.
*.C mà ta thường gọi là chương trình nguồn (source program) Sau đây là một số phím chức năng cơ bản nhất của TC.EXE
F1 (help) : Thực hiện chương trình trợ giúp trong khi viết chương trình
CTRL + F1 : Thực hiện trợ giúp nhanh trong khi soạn thảo
F2 (save) : Ghi file văn bản chương trình lên đĩa với phần mở rộng là *.c
CTRL + F2 : Ghi file văn bản chương trình lên đĩa với một tên khác có phần mở rộng là
F3 : Mở file mới để thực hiện soạn thảo
Alt + F3 : Đóng file văn bản đang trong cửa sổ soạn thảo hiện thời
F4 : Dịch và thực hiện chương trình cho tới khi gặp dòng lệnh mà tại vị trí đó chúng ta bấm F4
F5 : Mở rộng hoặc thu nhỏ vùng soạn thảo trên màn hình
Alt+F5 : Nhìn lại kết quả thực hiện chương trình của lần chạy trước đó
F6 : Thay đổi cửa sổ màn hình soạn thảo
Alt +1, 2, 3: Qui định các cửa sổ màn hình 1, 2, 3 trên cùng một trang màn hình
F7 : Thực hiện chương trình theo chế độ từng dòng lệnh kể cả các lệnh trong thân của hàm
F8 : Thực hiện chương trình theo chế độ từng dòng lệnh nhưng coi các lời gọi hàm là một lệnh
F9 : Dịch chương trình nguồn thành file *.OBJ
CTRL + F9 : Dịch và thực hiện chương trình (đồng thời tạo file *.OBJ sau đó tạo file mã máy *.EXE)
F10 : Thực hiện trong chế độ thực đơn
Home : Đƣa con trỏ về đầu dòng
End : Đƣa con trỏ về cuối dòng
PgUp : Đƣa con trỏ lên phía trên một trang màn hình
PgDn : Đưa con trỏ xuống phía dưới một trang màn hình
Del : Xoá kí tự tại vị trí con trỏ
Back Space : Xoá kí tự nằm bên trái con trỏ
CTRL+ PgUp : Đƣa con trỏ về đầu văn bản
CTRL+ PgDn : Đƣa con trỏ về cuối văn bản
Shift + : Đánh dấu khối văn bản sang bên trái
Shift + : Đánh dấu khối văn bản sang bên phải
Shift + : Đánh dấu khối văn bản theo từng dòng lên phía trên
Shift + : Đánh dấu khối văn bản theo từng dòng lên phía dứới
CTRL + Y : Xoá cả dòng chứa con trỏ
CTRL+Q+Y : Xoá tới cuối dòng kể từ vị trí con trỏ
CTRL +K+Y : Xoá khối văn bản đã được đánh dấu trước đó
CTRL+K+C : Copy khối văn bản đã đƣợc đánh dấu tới vị trí hiện tại của con trỏ
CTRL+K+V : Chuyển khối văn bản đã đƣợc đánh dấu tới vị trí hiện tại của con trỏ
CTRL+K+W : Ghi khối đã đƣợc đánh dấu lên đĩa Nếu tên tệp là PRN thì nội dung của nó sẽ đƣợc chuyển qua máy in
CTRL+K+R : Đọc một tệp khác từ đĩa vào, phần đƣợc đọc coi nhƣ một khối đƣợc đánh dấu
CTRL +Q+F : Tìm cụm từ đầu tiên xuất hiện trong văn bản
CTRL+Q+A : Tìm và thay thế cụm từ xuất hiện đầu tiên trong văn bản
CTRL+L : Tìm hoặc thay thế từ tiếp theo xuất hiện trong văn bản ước 2: Dịch và hiệu chỉnh chương trình (dùng turbo c)
Để gọi chương trình dịch C trong chế độ soạn thảo, người dùng chỉ cần nhấn phím F9 Chương trình dịch sẽ chuyển đổi mã nguồn với phần mở rộng *.C thành tệp *.OBJ, sau đó liên kết các tệp này để tạo ra chương trình mã máy có định dạng *.COM (đã nén) hoặc *.EXE (chưa nén) Quá trình liên kết được thực hiện thông qua trình liên kết Linker.
Trong quá trình dịch, chương trình có thể gặp lỗi, có ba loại lỗi chính (không kể tới lỗi do giải thuật) Đó là:
Lỗi cú pháp, được thông báo bởi từ khóa "error", thường xảy ra trong quá trình lập trình Những lỗi này có thể xuất phát từ việc viết sai các từ khóa, chẳng hạn như sử dụng "Int" thay vì "int", hoặc do thiếu các dấu ngoặc đơn, ngoặc kép, hoặc dấu chấm phẩy khi kết thúc một lệnh Ngoài ra, lỗi cũng có thể xảy ra nếu chưa khai báo nguyên mẫu cho hàm.
Lỗi cảnh báo (Warning) thường xuất hiện khi biến được khai báo nhưng không được sử dụng, hoặc khi các biểu thức kiểm tra biến không xác định được giá trị của chúng, hay do thứ tự ưu tiên của các phép toán Cả hai loại lỗi error và warning đều được thông báo ngay khi biên dịch chương trình thành file *.OBJ Quá trình liên kết các file *.OBJ để tạo ra file mã máy *.EXE chỉ tiếp tục khi tất cả các lỗi error được khắc phục, trong khi lỗi warning chỉ là cảnh báo và chương trình vẫn có thể chạy mà không cần sửa chữa Tuy nhiên, lập trình viên nên khắc phục các lỗi warning để cải thiện chất lượng mã nguồn.
Lỗi thứ ba trong quá trình liên kết thường xảy ra khi gọi các hàm mà chỉ có nguyên mẫu mà chưa được mô tả chi tiết, hoặc khi tên hàm gọi không chính xác Để khắc phục lỗi này, cần bổ sung đoạn chương trình con mô tả chi tiết cho hàm hoặc sửa đổi các lời gọi hàm cho đúng.
Chương trình được thực hiện bằng cách sử dụng tổ hợp phím CTRL+F9 trong môi trường soạn thảo TC.EXE hoặc qua môi trường DOS như các chương trình thông thường Nếu kết quả không chính xác, lỗi này thuộc về thuật toán mà máy tính không thể phát hiện Để đảm bảo tính đúng đắn của thuật toán, lập trình viên thường sử dụng một số bộ giá trị đặc biệt làm đầu vào.
2.2.3 Chương trình đơn giản nhất trong C
Ví dụ: Viết chương trình in ra dòng thông báo "Ngôn ngữ lập trình C"
Để tạo ra văn bản chương trình trong Turbo C, bạn cần sử dụng trình soạn thảo TC.EXE, thường nằm trong thư mục C:\TC\BIN Trình soạn thảo này tương tự như của Pascal, nhưng với phần mở rộng mặc định là *.C cho văn bản chương trình Khi soạn thảo, hãy nhớ lưu chương trình bằng phím F2 hoặc chọn File/Save từ menu Trong ví dụ này, chúng ta sẽ lưu với tên SmallPrg.c.
Để dịch chương trình thành file SmallPrg.EXE, bạn chỉ cần nhấn phím F9 Nếu muốn vừa dịch vừa thực thi chương trình, hãy sử dụng tổ hợp phím CTRL + F9 để xem kết quả trên màn hình Trong trường hợp có lỗi, trình dịch C sẽ thông báo để bạn có thể chỉnh sửa và hiệu đính lại chương trình Chương trình sẽ hiển thị dòng chữ "Ngôn ngữ lập trình" trên màn hình.
C" đƣợc viết đơn giản nhƣ sau:
/* khai báo việc sử dụng các hàm printf(), getch() trong conio.h*/ void main(void)
{ printf ("Ngôn ngữ lập trình C\ n");/* in ra màn hình*/ getch(); /* lệnh này chờ nhận một kí tự gõ vào*/
Kết quả thực hiện chương trình: Dòng chữ được in ra
Ngôn ngữ lập trình C Để tiếp tục hãy bấm tiếp một phím bất kì ta sẽ trở về với trình soạn thảo trong Turbo C
Chỉ thị #include trong C là chỉ thị tiền xử lý dùng để liên kết với tệp tương ứng, thường được đặt trong ký tự < tên file đầu tệp > Các tệp này có định dạng *.h, chứa nguyên mẫu của các hàm và thường nằm trong thư mục C:\TC\INCLUDE Ví dụ, chỉ thị #include cho phép sử dụng các hàm trong tệp conio.h, như hàm printf() và getch().
Một chương trình C, với bất kì kích thước nào, cũng đều bao gồm một hoặc nhiều
Hàm trong lập trình chứa các lệnh hoặc lời gọi hàm, và mỗi lệnh kết thúc bằng ký tự ';' Những lời gọi hàm này xác định các thao tác tính toán cụ thể cần thực hiện trong quá trình xử lý dữ liệu.
Trong ngôn ngữ lập trình C, hàm main đóng vai trò quan trọng tương tự như các hàm và chương trình con trong FORTRAN hay thủ tục trong PASCAL Main là tên đặc biệt, nơi chương trình bắt đầu thực thi, vì vậy mọi chương trình C đều phải có hàm main Hàm main sẽ khởi động các hàm khác để thực hiện nhiệm vụ của mình, bao gồm cả những hàm được định nghĩa trong mã nguồn và những hàm từ các thư viện đã được xây dựng trước.
Phương pháp trao đổi dữ liệu giữa các hàm trong lập trình C được thực hiện thông qua đối số của hàm Dấu ngoặc theo sau tên hàm bao quanh danh sách đối số, và mỗi hàm thường trả về một giá trị, mặc dù cũng có những hàm không có giá trị trả về Kiểu giá trị trả về được ghi trước tên hàm, trong trường hợp không có giá trị trả về, từ khóa void được sử dụng (ví dụ, hàm main không có giá trị trả về) Thân hàm được bao quanh bởi dấu ngoặc nhọn {}, tương tự như cấu trúc Begin End trong Pascal Tất cả chương trình trong C đều phải được bao trong { } và không có dấu chấm phẩy ở cuối văn bản chương trình Hàm được gọi thông qua tên của nó, kèm theo danh sách các đối số trong ngoặc, và nếu không có đối số, vẫn cần phải có dấu ngoặc tròn, mặc dù có thể để trống.
Dòng đƣợc viết printf ("Ngôn ngữ lập trình C\ n");
Hàm printf được gọi với tham số là chuỗi ký tự "Ngôn ngữ lập trình C\n", nhằm hiển thị kết quả trên màn hình Đây là một hàm thư viện dùng để xuất dữ liệu, trừ khi được chỉ định thiết bị nhận khác Trong trường hợp này, hàm sẽ hiển thị chuỗi ký tự đã được cung cấp.
Các kiểu dữ liệu cơ sở
Một kiểu dữ liệu (Data Type) là tập hợp các giá trị mà biến thuộc kiểu đó có thể nhận, cùng với các phép toán liên quan Trong ngôn ngữ lập trình C, các kiểu dữ liệu cơ bản bao gồm số nguyên (int, long), số thực (float, double) và ký tự (char) Khác với Pascal, C không có kiểu Boolean, vì kiểu này thực chất là kiểu nguyên chỉ nhận hai giá trị khác 0 hoặc bằng 0.
Kiểu dữ liệu char, với kích thước 1 byte, được sử dụng để biểu diễn một ký tự trong bảng mã ASCII Thực chất, nó là một số nguyên không dấu có giá trị từ 0 đến 255 Chúng ta sẽ thảo luận chi tiết hơn về kiểu dữ liệu char trong các phần tiếp theo.
Biến kiểu số nguyên trong lập trình bao gồm các loại như int, long int, với khả năng lưu trữ các số nguyên có dấu (âm, dương) thông qua từ khóa signed int, signed long Ngoài ra, còn có kiểu số nguyên không dấu như unsigned int và unsigned long Điểm khác biệt chính giữa int và long nằm ở kích thước của chúng.
Biến có kiểu float biểu diễn các số thực có độ chính xác đơn
Biến có kiểu double biểu diễn các số thực có độ chính xác kép
Sau đây là bảng các giá trị có thể của các kiểu dữ liệu cơ bản của C:
Kiểu Miền xác định ích thước char 0 255 1 byte int -32768 32767 2 byte long -2147483648 2147483647 4 byte unsigned int 0 65535 2 byte unsigned long 0 2147483647*2B94967295 4 byte float 3 4e-38 3.4e + 38 4 byte double 1.7e-308 1.7e + 308 8 byte
Toán tử sizeof(tên_kiểu) cho phép xác định kích thước của kiểu dữ liệu tính bằng byte Chương trình dưới đây sẽ hiển thị kích thước của từng kiểu dữ liệu cơ bản.
/* Chương trình kiểm tra kích cỡ các kiểu dữ liệu cơ bản*/
In this C program, the `clrscr()` function is used to clear the screen, followed by several `printf()` statements that display the sizes of various data types in bytes The program outputs the size of the character type (`char`), integer type (`int`), long integer type (`long`), single-precision floating-point type (`float`), and double-precision floating-point type (`double`) Finally, it waits for a user input with `getch()` before terminating.
Biến,hằng, câu lệnh và các phép toán
Biến là một thành phần quan trọng trong lập trình, có giá trị thay đổi trong quá trình thực thi chương trình Mỗi biến được xác định bằng một tên riêng và có một địa chỉ trong bộ nhớ Để sử dụng biến, người lập trình cần phải khai báo nó trước, tuân theo các quy tắc khai báo cụ thể.
Trong lập trình, chúng ta có thể khai báo nhiều biến cùng kiểu dữ liệu trên một dòng bằng cú pháp "Tên_kiểu_dữ_liệu tên_biến", trong đó các biến được phân cách bởi dấu phẩy Đồng thời, có thể gán giá trị ban đầu cho các biến ngay trong quá trình khai báo.
Trong đoạn mã này, chúng ta khai báo một số biến với các kiểu dữ liệu khác nhau Đầu tiên, ba biến nguyên a, b, c được khai báo, trong đó c được gán giá trị 0 Tiếp theo, ba biến kiểu float e, f, g được khai báo, với g được gán giá trị 1.5 Ngoài ra, hai biến i và j được khai báo với kiểu long Hai biến k và m được khai báo là kiểu số nguyên dương (unsigned) Cuối cùng, biến key được khai báo với kiểu char.
Hằng là một đại lượng có giá trị không thay đổi trong suốt quá trình thực hiện chương trình Để định nghĩa các hằng, C sử dụng chỉ thị #define.
Hằng có giá trị trong miền xác định của kiểu int là hằng kiểu nguyên (nếu không có l ở cuối)
Hằng có giá trị trong miền xác định của kiểu int và có kí hiệu 0x ở đầu là hằng kiểu nguyên biểu diễn theo cơ số hệ 16 (0xFF)
Hằng có giá trị trong miền xác định của kiểu long và có kí hiệu L (l) ở cuối cũng đƣợc coi là hằng kiểu long (135L)
Hằng có giá trị trong miền xác định của kiểu long là hằng kiểu long
Hằng có giá trị trong miền xác định của kiểu float là hằng kiểu số thực (3.414)
Hằng có giá trị là một kí tự đƣợc bao trong dấu nháy đơn đƣợc gọi là hằng kí tự ('A')
Hằng có giá trị là một dãy các kí tự đƣợc bao trong dấu nháy kép đƣợc gọi là hằng xâu kí tự "Hằng String"
#define MAX 100 /* định nghĩa hằng kiểu nguyên*/
#define MIN 0xFF /* hằng nguyên biểu diễn theo cơ số hệ 16*/
#define KITU 'A' /* hằng kí tự */
#define STR "XAU KI TU" /*hằng xâu kí tự*/
Câu lệnh trong lập trình xác định công việc mà chương trình cần thực hiện để xử lý dữ liệu đã được mô tả và khai báo Trong ngôn ngữ C, các câu lệnh được phân cách bằng dấu chấm phẩy Chúng được chia thành hai loại chính: câu lệnh đơn giản và câu lệnh có cấu trúc.
Câu lệnh đơn giản là những lệnh không bao gồm các lệnh khác như lệnh gán Lệnh gán được sử dụng để gán giá trị của một biểu thức hoặc một hằng số vào một biến Cách viết tổng quát của phép gán là: biến = biểu thức.
Câu lệnh có cấu trúc: Bao gồm nhiều lệnh đơn giản và có khi có cả lệnh cáu trúc khác bển trong Các lệnh loại này nhƣ :
+ Cấu trúc lệnh khối ( lệnh ghép hay lệnh hợp)
+ Các lệnh lặp: for, while, do… while
Các phép toán số học cơ bản bao gồm cộng (+), trừ (-), nhân (*), chia (/), và lấy phần dư (%) Khi thực hiện phép chia giữa hai số nguyên, kết quả sẽ là một số nguyên, tương tự như phép chia nguyên.
Trong lập trình, việc khai báo biến là rất quan trọng Ví dụ, ta có thể khai báo ba biến nguyên với cú pháp: `int a=3, b=5, c;` và ba biến thực với cú pháp: `float d=3, e=2, f;` Các phép toán cơ bản như cộng, trừ, chia và chia lấy dư có thể được thực hiện trên các biến này, như `c = a + b;` cho kết quả là 8, hay `c = a - b;` cho kết quả là -2 Đặc biệt, trong C, có các phép toán tăng và giảm như `a++` tương đương với `a = a + 1` và `a ` tương đương với `a = a - 1`, giúp đơn giản hóa việc viết chương trình và giảm thiểu ký hiệu trong các biểu thức số học.
Lưu ý rằng cả hai phép toán ++a và a++ đều làm tăng giá trị của a lên một đơn vị, nhưng cách thức hoạt động của chúng khác nhau trong các biểu thức so sánh Cụ thể, ++a sẽ tăng a trước khi thực hiện so sánh, trong khi a++ sẽ thực hiện so sánh trước rồi mới tăng a Tương tự, a và a cũng hoạt động theo cách như vậy.
Ví dụ 4.3: Kiểm tra lại các phép toán số học trên hai số nguyên a và b;
#include void main(void)
{ int a=5, b=2; clrscr(); printf("\ tổng a + b = %d", a + b); printf("\ hiệu a - b = %d", a - b); printf("\ tích a * b = %d", a * b); printf("\ thương a / b = %d", a / b);
Trong bài viết này, chúng ta sẽ tìm hiểu về các phép toán cơ bản với hai số nguyên a và b Đầu tiên, chúng ta sử dụng phép toán phần dư để tính a % b và in ra kết quả Sau đó, a được tăng thêm 1 và b giảm đi 1, với kết quả được hiển thị Tiếp theo, a được tăng thêm giá trị của b, và kết quả cũng được in ra Chúng ta sẽ tiếp tục với phép trừ, nhân và chia giữa a và b, cùng với các phép toán tương ứng, để thấy được sự thay đổi giá trị của a sau mỗi phép toán Cuối cùng, chúng ta sử dụng phép toán modul để lấy phần dư của a khi chia cho b và in kết quả ra màn hình.
- Các phép toán so sánh: Gồm có các phép >, =, b) { } /* nếu a lớn hơn b*/ if ( a>=b) { } /* nếu a lớn hơn hoặc bằng b*/ if ( a==b) { } /* nếu a đúng bằng b*/ if ( a!=b) { } /* nếu a khác b*/
Phép và logic chỉ mang lại giá trị đúng khi cả hai biểu thức tham gia đều có giá trị đúng, trong đó giá trị đúng của một biểu thức trong ngôn ngữ lập trình C được hiểu là khi biểu thức đó có giá trị khác 0.
|| : Phép hoặc logic chỉ cho giá trị sai khi cả hai biểu thức tham gia đều có giá trị sai
! : Phép phủ định cho giá trị đúng nếu biểu thức có giá trị sai và ngƣợc lại cho giá trị sai khi biểu thức có giá trị đúng
Ví dụ: int a =3, b =5; if ( (a !=0) && (b!=0) ) /* nếu a khác 0 và b khác 0*/ if ((a!=0) || (b!=0)) /* nếu a khác 0 hoặc b khác 0*/ if ( !(a) ) /* phủ định a khác 0*/
- Các toán tử thao tác bít:
Các toán tử thao tác bít không sử dụng cho float và double:
& : Phép và (and) các bít
| : Phép hoặc (or) các bít
^ : Phép hoặc loại trừ bít (XOR)
> : Phép dịch phải (dịch sang phải n bít có giá trị 0)
Giả sử (a) 10 =3, (b) 10 =5 khi đó (c) 10 = a & b cho ta kết quả là 1:
0000.0000.0000.0001 c =1 c = a | b; cho ta kết quả là 7;
0000.0000.0000.0111 c =7 c = a ^ b; cho ta kết quả là 6;
0000.0000.0000.0110 c =6 c = ~a; cho ta kết quả là 65532;
1111.1111.1111.1100 c = 65532 c = a1; cho ta kết quả là (0000.0000.0000.0001) 2
- Toán tử chuyển đổi kiểu :
Chúng ta có thể sử dụng toán tử chuyển đổi kiểu để đạt được kết quả tính toán mong muốn Quy tắc chuyển đổi kiểu được thực hiện theo cú pháp: (kiểu) biến.
Ví dụ: Tính giá trị phép chia hai số nguyên a và b
{ int a=3, b=5; float c; c= (float) a / (float) b; printf("\n thương c = a / b =%6.2f", c); getch();
- Thứ tự ƣu tiên các phép toán
Khi viết biểu thức, việc nắm rõ thứ tự ưu tiên trong tính toán các phép toán là rất quan trọng Các bảng tổng hợp dưới đây sẽ giúp bạn hiểu rõ hơn về trật tự ưu tiên của các phép toán số học và phép toán so sánh.
Bảng tổng hợp thứ tự ƣu tiên tính toán các phép toán số học và so sánh
Tên toán tử hiều tính toán
Thủ tục vào và ra chuẩn
2.5.1 Vào ra ra bằng getchar(), putchar()
Cơ chế vào đơn giản nhất trong lập trình là sử dụng hàm getchar để đọc từng ký tự từ thiết bị đầu vào như bàn phím hoặc màn hình Mỗi lần gọi hàm getchar(), nó sẽ trả về ký tự tiếp theo, và khi gặp cuối tệp, hàm này sẽ trả về giá trị EOF, được định nghĩa là -1 trong thư viện chuẩn (stdio.h) Tuy nhiên, để đảm bảo tính độc lập với giá trị cụ thể, các phép kiểm tra nên sử dụng EOF thay vì -1 Để xuất ký tự ra, hàm putchar(c) sẽ gửi ký tự đó đến thiết bị đầu ra chuẩn, thường là màn hình.
Việc đƣa ra cho printf cũng chuyển tới thiết bị ra chuẩn, các lời gọi tới putchar và printf có thể chen lẫn nhau
Nhiều chương trình chỉ cho phép đọc dữ liệu từ một thiết bị và ghi dữ liệu ra một thiết bị khác; trong trường hợp này, việc sử dụng getchar, putchar kết hợp với printf là hoàn toàn thích hợp Điều này đặc biệt quan trọng khi làm việc với tệp và sử dụng công cụ ống để nối đầu ra của chương trình này thành đầu vào của chương trình tiếp theo Ví dụ, chương trình lower có chức năng chuyển đổi ký tự đầu vào thành chữ thường.
#include void main() /*chuyển kí tự vào thành chữ thường*/
{ int c; while ((c = getchar()) ! = EOF) putchar(isupper(c) ? tolower(c) : c);
Các macro isupper và tolower được định nghĩa trong stdio.h Macro isupper kiểm tra xem ký tự đầu vào có phải là chữ hoa không, trả về giá trị khác 0 nếu đúng và 0 nếu là chữ thường Trong khi đó, macro tolower chuyển đổi ký tự từ chữ hoa sang chữ thường.
Người dùng không cần quan tâm đến cách cài đặt cụ thể của các hàm, vì hành vi bên ngoài của chúng vẫn giống nhau Do đó, các chương trình sử dụng những hàm này không cần chú ý đến tập ký tự.
Trong thư viện chuẩn, các hàm getchar và putchar được định nghĩa dưới dạng macro, giúp giảm thiểu chi phí khi gọi hàm cho từng ký tự.
2.5.2 In ra theo khuôn dạng - Printf
Hàm printf và scanf cho phép chuyển đổi giữa các biểu diễn ký tự và số, đồng thời hỗ trợ sinh ra hoặc thông dịch các dòng có khuôn dạng Trong các chương trước, chúng ta đã sử dụng printf mà chưa giải thích đầy đủ về nó Hàm printf (control, arg1, arg2, ) thực hiện việc chuyển đổi, tạo khuôn dạng và in các đối số ra thiết bị chuẩn theo điều khiển của xâu control Xâu điều khiển bắt đầu bằng ký tự % và kết thúc bằng ký tự chuyển dạng, có thể kèm theo dấu trừ (-) để xác định việc dồn trái cho đối được chuyển dạng trong trường.
Xâu chữ số xác định chiều ngang tối thiểu của trường, và số được chuyển dạng sẽ được in ra trong trường với chiều ngang này Nếu đối tượng được chuyển có ít ký tự hơn chiều ngang của trường, nó sẽ được bổ sung thêm ký tự bên trái hoặc bên phải (nếu có chỉ báo dồn trái) để đạt đủ chiều rộng Ký tự bổ sung sẽ là dấu trống hoặc số 0 nếu chiều ngang trường được xác định bằng số.
Dấu chấm phân tách chiều ngang trường với xâu chữ số tiếp
Xâu chữ số (độ chính xác) xác định số lượng tối đa các ký tự cần in ra từ một xâu, cũng như số chữ số cần hiển thị ở bên phải dấu chấm thập phân của kiểu dữ liệu float hoặc double.
Bộ thay đổi chiều dài l (chữ ell) chỉ ra rằng phần dữ liệu tương ứng là long chứ không phải là int
Các ký tự chuyển dạng và ý nghĩa của chúng bao gồm: d chuyển đối tượng sang ký pháp thập phân; o chuyển sang ký pháp hệ tám; x chuyển sang cú pháp hệ mười sáu không dấu; u chuyển sang ký pháp thập phân không dấu; c coi đối tượng là một ký tự riêng biệt; s là xâu ký tự, in các ký tự cho đến khi gặp ký tự trống hoặc đạt số lượng ký tự theo độ chính xác; e xem đối tượng là float hoặc double, chuyển sang ký pháp thập phân với dạng [-]m.nnnnnnE[+]xx, độ chính xác mặc định là 6; f cũng xem là float hoặc double, chuyển sang ký pháp thập phân với dạng [-]mmm.nnnnn, độ chính xác mặc định là 6; g sử dụng %e hoặc %f tùy theo loại nào ngắn hơn và không in các số không vô nghĩa.
Nếu kí tự đứng sau % không phải là kí tự chuyển dạng thì kí tự đó sẽ đƣợc in ra; vậy % sẽ đƣợc in ra bởi %%
Hầu hết các chuyển dạng đều rõ ràng và đã được trình bày trong các chương trước, ngoại trừ độ chính xác liên quan đến các chuỗi Bảng dưới đây sẽ minh họa hiệu quả của các loại đặc tả khi in ra chuỗi “hello, world” (12 ký tự), với dấu hai chấm được đặt quanh chuỗi để thể hiện sự trải rộng của nó.
Lưu ý rằng hàm printf sử dụng đối số đầu tiên để xác định số lượng và kiểu các đối số theo sau Nếu số lượng đối số không đủ hoặc kiểu của chúng sai, hàm sẽ hoạt động không chính xác và trả về kết quả vô nghĩa.
2.5.3 Nhập vào có khuôn dạng - scanf
Hàm scanf hoạt động tương tự như hàm printf, nhưng thực hiện chức năng chuyển đổi dữ liệu theo chiều ngược lại Cú pháp của hàm là scanf(control, arg1, arg2, ), trong đó hàm này đọc các ký tự từ thiết bị vào chuẩn và diễn giải chúng dựa trên khuôn dạng được xác định trong tham số control Kết quả sẽ được lưu trữ trong các tham số còn lại, trong đó các tham số này cần phải là con trỏ để chỉ ra vị trí lưu trữ dữ liệu tương ứng.
Xâu điều khiển thường chứa các đặc tả chuyển dạng, được dùng để thông dịch trực tiếp dãy vào Xâu điều khiển có thể chứa:
Dấu cách, dấu tab và dấu xuống dòng, thường được gọi là các kí tự khoảng trắng, thường bị bỏ qua trong quá trình xử lý văn bản Những kí tự này, cùng với các kí tự thông thường khác, được coi là tương đương với kí tự khoảng trắng trong dòng vào.
Các đặc tả chuyển dạng bao gồm kí tự %, kí tự cắt bỏ gán *(tuỳ chọn), và một số tuỳ chọn xác định chiều ngang tối đa của trường Chúng điều khiển cách chuyển đổi dữ liệu vào trường tiếp theo, với kết quả thường được gán cho biến tương ứng Nếu kí tự * được sử dụng, trường vào sẽ bị bỏ qua Trường vào được xác định là một chuỗi kí tự không phải khoảng trắng, kéo dài đến kí tự khoảng trắng tiếp theo hoặc đến chiều rộng tối đa đã chỉ định.
Kí tự chuyển dạng trong ngôn ngữ lập trình C cho phép thực hiện việc thông dịch dữ liệu đầu vào Các kí tự hợp pháp bao gồm: %d cho số nguyên, yêu cầu con trỏ nguyên; %o cho số nguyên hệ tám, cũng yêu cầu con trỏ nguyên; %x cho số nguyên hệ mười sáu, yêu cầu con trỏ nguyên; %h cho số nguyên short, yêu cầu con trỏ short; %c cho một kí tự, yêu cầu con trỏ kí tự mà không bỏ qua khoảng trắng; %s cho xâu kí tự, yêu cầu con trỏ tới xâu đủ lớn và không nhận khoảng trắng; và %f cho số dấu phẩy động, yêu cầu con trỏ tới float, với kí tự chuyển dạng %e đồng nghĩa với %f Khuôn dạng cho float bao gồm dấu tùy chọn, chuỗi số có thể chứa dấu chấm thập phân và trường mũ tùy chọn.
CÁC CẤU TRÚC LỆNH ĐIỀU KHIỂN
Câu lệnh khối
Tập các câu lệnh đƣợc bao bởi hai dấu { } đƣợc gọi là một câu lệnh khối
Cú pháp cho phép đặt câu lệnh khối ở bất kỳ vị trí nào trong chương trình, nhưng nên bố trí chúng theo các chu trình điều khiển như for, while, do while, if else, và switch để làm rõ cấu trúc của chương trình.
Ví dụ: if (a > b ) { câu_lệnh;
Cấu trúc lệnh if
Dạng 1: if ( biểu thức) câu_lệnh;
Nếu biểu thức đúng, thực hiện câu lệnh; câu lệnh có thể là đơn hoặc khối, và nếu là khối, cần được bao trong dấu ngoặc nhọn { }.
Dạng 2: if (biểu_thức) câu_lệnh_A; else câu_lệnh_B;
Nếu biểu thức có giá trị đúng thì câu_lệnh_A sẽ đƣợc thực hiện, nếu biểu thức có giá trị sai thì câu_lệnh_B sẽ đƣợc thực hiện
Dạng 3: Đƣợc sử dụng khi có nhiều lệnh if lồng nhau hoặc phải kiểm tra nhiều biểu thức khác nhau if (biểu_thức_1) câu_lệnh_1; else if (biểu_thức_2) câu_lệnh_2;
Câu_lệnh_k; else câu_lệnh_k+1;
Nếu biểu thức i có giá trị đúng (0 < i