Một chương trình bất kỳ của mọi ngôn ngữ lập trình đều được tạo nên từ tập hợp các câu lệnh. Mỗi câu lệnh là sự kết hợp của các từ theo qui tắc cấu trúc ngữ pháp xác
định, trong đó mỗi từđược cấu thành từ bộ ký tự riêng của mỗi ngôn ngữ. Bộ ký tự trong ngôn ngữC được chia thành các loại sau:
- Chữ cái: A…Z và a…z - Chữ số: 0…9
- Các ký hiệu toán học: + - * / = > < - Các dấu ngăn cách: , . ; : space tab - Các dấu ngoặc: ( ) [ ] { }
- Các ký tựđặc biệt: # % ? $ & ^ ! ~ _ ‘ “ | \ / @
Lưu ý: Trình biên dịch sẽ bỏ qua kí tự khoảng trắng (space) nếu nó không nằm trong một hằng chuỗi. Người ta thường dùng khoảng trắng để tách từ nhưng không được phép dùng nó chen giữa các kí tự trong từ khóa hoặc định danh.
1.2.2Từ khóa
Từ khóa (Keyword) là những từ đã được định nghĩa sẵn trong mỗi ngôn ngữ. Mỗi từ khóa có một ý nghĩa xác định và chúng ta không thể thay đổi nó. Từ khóa
thường được sử dụng dành riêng cho mục đích xác định như đặt tên cho các kiểu dữ
49 Dưới đây là bộ từ khóa của ngôn ngữ C:
auto const double float int short struct unsigned
break continue else for long signed switch void
case default enum goto register sizeof typedef volatile
char do extern if return static union while
Bảng 1.1 – Bộ từ khóa trong C
Khi sử dụng các từ khóa trong C cần phải chú ý những điểm sau: - Các từ khóa trong C phải được viết bằng chữthường
- Không thể sử dụng từ khóa cho mục đích khác nhưđặt tên cho biến, hằng, mảng, hàm,...
1.2.3Định danh(tên)
Định danh là một dãy kí tựdùng để gọi tên các đối tượng trong chương trình như
biến, hằng, hàm, mảng,… Khi đặt tên cho một đối tượng, người lập trình cần đặt sao cho phù hợp với ý nghĩa sử dụng của nó, làm cho chương trình dễ hiểu hơn.
Một số qui tắc cần tuân theo khi đặt tên trong C:
- Chỉ được sử dụng các ký tự gồm chữ cái (A..Z,a..z), chữ số (0..9) và dấu gạch dưới ‘_’.
- Không được bắt đầu bằng chữ số, không được trùng với từ khóa.
- Ngôn ngữ C phân biệt chữ hoa và chữthường nên sum và SUM là hai định danh khác nhau hoàn toàn. Mặc dù không bắt buộc, nhưng thông thường thì chữ thường được dùng cho tên biến, tên hàm, tên mảng còn chữ hoa dùng cho tên hằng số.
Ví dụ vềcác định danh hợp lệ:
Biến: i, j, count, top_of_page, name, emp_number, temp1
Hàm: sort, getValue, addition, isContain
Hằng: PI, MAX, MIN Ví dụ vềcác định danh không hợp lệ:
for : định danh trùng với từ khóa
3g, 9PI: định danh bắt đầu bằng chữ số
search elem, tong#le: định danh chứa ký tự không hợp lệ (khoảng trắng, #).
50
1.2.4Các kiểu dữ liệu cơ sở
Một kiểu dữ liệu được xác định bởi một tập hợp hữu hạn các giá trị mà mỗi dữ
liệu thuộc kiểu đó có thể nhận được cùng với một số phép toán có thể thực hiện được trên kiểu dữ liệu đó. Kiểu dữ liệu gắn liền với biến hoặc hằng sốđể xác định sốlượng byte cần cấp phát cho chúng.
Các kiểu dữ liệu cơ sở trong ngôn ngữ C gồm: kiểu số nguyên, kiểu số thực, kiểu kí tự, kiểu luận lý và kiểu void.
a. Kiểu số nguyên
Kiểu số nguyên bao gồm số nguyên có dấu và số nguyên không dấu. Kích thước của biến số nguyên phụ thuộc vào phần cứng và hệđiều hành của máy. Ví dụ, kiểu số
nguyên int trên hệ điều hành 16-bit có kích thước là 2 bytes, còn trong hệ điều hành 32-bit có kích thước 4 bytes. Như vậy, dựa vào kích thước của mỗi kiểu số nguyên, ta có thểxác định được miền giá trị mà dữ liệu thuộc kiểu đó có thể nhận được.
Các kiểu số nguyên có dấu trong hệ thống 16-bit:
Kiểu (Type) Kích thước (Byte) Miền giá trị (Range) char 1 –128 +127 int 2 –32.768 +32.767 short 2 –32.768 +32.767 long 4 –2.147.483.648 +2.147.483.647
Bảng 1.2 – Các kiểu số nguyên có dấu trong hệ thống 16-bit
Các kiểu số nguyên không dấu trong hệ thống 16-bit:
Kiểu (Type) Kích thước (Byte) Miền giá trị (Range) unsigned char 1 0 255 unsigned int 2 0 65.535 unsigned short 2 0 65.535 unsigned long 4 0 4.294.967.295
Bảng 1.3 – Các kiểu số nguyên không dấu trong hệ thống 16-bit
Với kích thước n bits, nếu là kiểu số nguyên có dấu thì miền giá trị sẽ nằm trong khoảng từ 2n-1 2n-1 – 1, còn nếu là kiểu số nguyên không dấu thì miền giá trị sẽ nằm trong khoảng từ 0 2n – 1.
b. Kiểu số thực
Kiểu số thực (kiểu dấu phẩy động) là kiểu dữ liệu dùng để lưu trữ các giá trị
thực. Ngôn ngữ C hỗ trợ 2 kiểu dấu phẩy động là float và double. Trong đó, kiểu
51
Bảng dưới đây thể hiện mối quan hệ giữa độ chính xác xấp xỉ, kích thước và miền giá trị của các kiểu số thực:
Kiểu
(Type) Độ chính xác
(Decimal digits) Kích thước
(Byte) Miền giá trị (Range) float 6 – 7 4 3.4*10–38 3.4*10 38 double 15 – 16 8 1.7*10–3081.7*10 308 Bảng 1.4 – Các kiểu số thực
Như vậy, nếu độ chính xác không quan trọng bằng kích thước lưu trữ thì ta nên sử dụng kiểu float. Ngược lại, nếu độ chính xác là tiêu chí quan trọng nhất, thì nên sử
dụng kiểu double.
c. Kiểu kí tự
Kiểu kí tựchar cho phép lưu trữ một kí tựđơn. Mỗi kí tự sẽđược biểu diễn bằng một giá trị số nguyên 8 bit trong máy tính. Giá trị số nguyên này chính là mã ASCII của kí tựđó. Vì vậy, ta có thể xem kiểu kí tự chính là một kiểu số nguyên. Ví dụ, lưu
giá trị65 tương ứng với kí tự ‘A’, giá trị97 tương ứng với kí tự ‘a’.
d. Kiểu luận lý
Ngôn ngữ C không hỗ trợ kiểu logic (boolean của Pascal) mà chỉ quan niệm ngầm định rằng giá trị0 tương ứng là false (sai), ngược lại giá trịkhác 0 tương ứng là
true (đúng). Kiểu luận lý được áp dụng khi xét giá trị của các biểu thức logic. Ví dụ: (1 > 2) có giá trị là false (0).
e. Kiểu void
Kiểu dữ liệu void là kiểu dữ liệu đặc biệt không lưu trữ giá trị nào cả. Nên người
ta thường không sử dụng nó để khai báo biến giống như các kiểu số nguyên hay số
thực. Kiểu dữ liệu này thường được sử dụng làm kiểu trả về cho hàm hoặc để khai báo con trỏ. Chẳng hạn như, trong chương trình C ta có thể khai báo hàm main() với kiểu trả về là void vì nó không cần trả về giá trị nào cả.
1.2.5Biến
Biến là một đại lượng dùng đểlưu trữ giá trị dữ liệu trong bộ nhớ. Biến cho phép cung cấp một tên có ý nghĩa cho mỗi vị trí ô nhớ. Thông qua tên biến, ta có thể truy cập đến các giá trị cụ thể trong ô nhớ mà không cần biết địa chỉ của chúng. HĐH sẽ đảm nhận việc cấp phát ô nhớ còn trống cho mỗi biến. Biến có thể lưu trữ dữ liệu thuộc nhiều kiểu khác nhau như số thực, số nguyên, kí tự,… Giá trị của biến có thể thay đổi trong chương trình, nhưng tại mỗi thời điểm một vị trí ô nhớ chỉ có thểlưu trữ
một giá trị duy nhất.
Cú pháp khai báo biến:
52
Ví dụ:
int n;
float phi;
Trong trường hợp cần khai báo nhiều biến có cùng kiểu, ta có thể sử dụng cú pháp sau:
kiểu_dữ _liệu tên_biến1, tên_biến2,…;
Ví dụ: float delta, result;
Cần lưu ý rằng, việc khai báo biến chỉ mới báo cho trình biên dịch biết được kích
thước của giá trị mà biến có thểlưu trữ, chứ lúc này bộ nhớ vẫn chưa được cấp phát. Vì vậy, cần phải khởi tạo giá trịban đầu cho biến:
kiểu_dữ _liệu tên_biến = giá_trị_khởi_tạo;
Ví dụ:
int x = 5, y; /* Khởi tạo giá trị ban đầu cho biến x */
x = 6; /* Gán giá trị khác cho biến x */
y = 7; /* Gán giá trị cho biến y sau khi khai báo */
Sau khi biến có giá trị xác định, thì nó sẽ được cấp phát một vùng nhớ có kích
thước tương ứng với kiểu của biến. Mỗi biến có một địa chỉ là địa chỉ của vùng nhớ
chứa biến đó. Để lấy ra địa chỉ của biến ta sử dụng toán tử lấy địa chỉ ‘&’ đặt trước tên biến: &tên_biến
Lưu ý:
- Biến phải được khai báo trước khi sử dụng.
- Kiểu dữ liệu của biến không được thay đổi trong toàn bộchương trình. - Tên biến nên đặt có ý nghĩa, phù hợp với mục đích sử dụng và tuân theo
các qui tắc đặt tên định danh đã nêu ở mục trước.
- Theo chuẩn ANSI C, vị trí khai báo các biến phải được đặt ngay sau dấu ‘{‘
đầu tiên của thân hàm hoặc của khối lệnh.
1.2.6Hằng
Hằng là cũng đại lượng giống như biến, chỉ khác là giá trị của nó không thay đổi trong quá trình chương trình thực hiện. Hằng thường được dùng để thay thế cho một giá trị lặp lại nhiều lần trong chương trình, giúp dễdàng thay đổi mã nguồn cũng như
cung cấp một cái tên có ý nghĩa cho giá trịđó. Hằng được chia ra làm 4 loại gồm hằng số nguyên, hằng số thực, hằng kí tự, và hằng chuỗi.
a. Hằng số nguyên
Trong ngôn ngữ C, hằng số nguyên có thểđược biểu diễn dưới 3 dạng sau: - Dạng thập phân: sốnguyên được biểu diễn bởi tập hợp các chữ số từ0 đến
53
- Dạng bát phân: sốnguyên được biểu diễn bởi tập hợp các chữ số từ0 đến 7 và thêm tiền tố 0 ởđầu.
- Dạng thập lục phân: sốnguyên được biểu diễn bởi tập hợp các chữ số từ 0
đến 9, và các chữcái A đến F hoặc a đến f. Ngoài ra, bổ sung thêm tiền tố
0x hoặc 0X ởđầu. Ví dụ:
Dạng thập phân Dạng bát phân Dạng thập lục phân
10 012 0xa or 0xA
132 0204 0x84
32179 076663 0x7dB3 or 0X7DB3
Ngoài ra, để biểu diễn các hằng kiểu long, unsigned, hoặc unsigned long người
ta thường thêm hậu tố L hoặc l, U hoặc u, UL hoặc ul vào cuối giá trị nguyên. Ví dụ:
- Hằng số nguyên kiểu unsigned int: 5000u, 1000U - Hằng số nguyên kiểu long: -300L, 32767L
b. Hằng số thực
Hằng số thực có thểđược viết theo hai dạng: - Dấu phẩy tĩnh (dạng thập phân):
[dấu] [phần nguyên] . [phần thập phân]
Trong đó, phần nguyên hoặc phần thập phân có thể vắng.
- Dấu phẩy động (dạng số mũ): số thực gồm phần định trị và phần bậc. Hai phần này cách nhau bởi ký tự e hoặc E. Dạng này được sử dụng khi hằng số
thực quá nhỏ hoặc quá lớn. Ví dụ:
Số thực dấu phẩy tĩnh Số thực dấu phẩy động
15.75 1.575E1 hoặc 1575e-2
-0.0025 -2.5e-3
.75 .0075e2 hoặc 75e-2
Hằng số thực có thể thuộc các kiểu float, double. Để phân biệt giữa các kiểu,
người ta thường thêm các hậu tố f, F vào cuối của giá trị thực. Ví dụ: Hằng số thực float: 100F
54
c. Hằng kí tự
Hằng kí tự là kí tựđơn nằm trong cặp dấu nháy đơn. Mỗi hằng kí tự sẽ có giá trị
là mã ASCII của nó, ví dụnhư kí tự ‘A’ có mã là 65. Một hằng kí tựkhông được có
độ dài lớn hơn 1. Đối với một số hằng kí tự đặc biệt, ta có thể biểu diễn ở dạng ‘\c’. Những kí tự này sẽ không được in ra hoặc hiển thị trực tiếp. Dưới đây là một số những kí tựđặc biệt trong C:
Kí tự Cách biểu diễn Mã ASCII
Kí tự kết thúc chuỗi ‘\0’ 0 Kí tự xuống dòng ‘\n’ 10 Kí tự về đầu dòng ‘\r’ 13 Kí tự tab ‘\t’ 9 Dấu gạch chéo \ ‘\\’ 92 Dấu nháy đơn ‘ ‘\’’ 39 Dấu nháy kép “ ‘\”’ 34
Hằng kí tự có thể tham gia vào các phép toán số học như mọi số nguyên khác. Chẳng hạn như: ‘8’ - ’6’ = 56 – 54 = 2.
d. Hằng chuỗi
Hằng chuỗi là một chuỗi các kí tự nằm trong cặp dấu nháy kép. Những kí tự
trong một chuỗi có thể là chữ cái, chữ số, dấu cách trắng, và các kí tựđặc biệt. Ví dụ: “Hello ! World” , “C programming language”, “1987”, …
Đối với một chuỗi quá dài, nó có thểđược viết trên nhiều dòng sử dụng kí tự ‘\’. Ví dụ: “This is a very long\
string\n”;
Chuỗi kí tựđược lưu trữ thành một mảng các kí tựđơn trong bộ nhớvà được kết thúc bởi kí tự NUL (‘\0’).
Lưu ý: hằng chuỗi “A” khác với hằng kí tự ‘A’. Kí tự ‘A’ có giá trịtương ứng là
65, nhưng chuỗi “A” không có giá trị gì cả. Ở dạng lưu trữ, ta thấy tận cùng của hằng chuỗi có ký tự NUL mà hằng kí tự không có , nên tồn tại chuỗi rỗng “”, chứ không có ký tự rỗng ‘’.
Ngôn ngữ C hỗ trợ hai cách khai báo hằng đó là dùng từ khóa const hoặc chỉ thị
tiền xử lí #define.
Khai báo với từ khóa const:
const kiểu_dữ _liệu tên_hằng = giá_trị;
Trong khai báo ở trên, giá_trị của đối tượng tên_hằng phải luôn luôn được xác
55
Ví dụ: const double PI = 3.14159;
Chỉ thị tiền xử lí #define là một cách khác linh động hơn để định nghĩa hằng
trong chương trình:
#define tên_hằng giá_trị
Lưu ý: Không có dấu chấm phẩy ở cuối chỉ thị #define.
Cách khai báo hằng này thường đặt ở đầu chương trình, nhưng chúng ta có thể đặt nó ở bất kì vị trí nào miễn là trước khi nó được sử dụng. Khi thực hiện biên dịch
chương trình, tất cả các vị trí sử dụng tên_hằng sẽ được thay thể bởi giá_trị. Vì vậy, tên_hằng được xem như là hằng kí hiệu thay cho một giá trị hằng. Kiểu dữ liệu của hằng sẽđược trình biên dịch xác định dựa vào giá_trị.
Ví dụ: #define PI 3.14159
1.2.7Hàm
Hàm là một đơn vị độc lập của chương trình, được thiết kế để thực hiện một tác vụ cụ thể. Mỗi hàm chứa các khai báo và nhóm các câu lệnh theo một trình tự logic. Tất cảcác chương trình C đều sử dụng hàm đểtăng khảnăng tái sử dụng, tính dễ hiểu, dễ theo dõi cho chương trình. Trong thư viện của C đã định nghĩa sẵn một số lượng lớn các hàm thực hiện chức năng khác nhau. Các hàmthư viện này đều được khai báo trong các tập tin tiêu đề. Để sử dụng chúng, ta chỉ cần khai báo tập tin tiêu đề ởđầu
chương trình. Ví dụ, để sử dụng các hàm toán học thì ta khai báo: #include <math.h>.
Một số hàm toán học thường được sử dụng trong C:
Hàm Kiểu
tham số Kivềểu trả Ý nghĩa Ví dụ
sqrt(x) double double Căn bậc 2 của x sqrt(9.0) = 3.0
pow(x,y) double double x mũ y pow(2.0 , 3.0) = 8.0
abs(x) double double Trị tuyệt đối của x abs(-9) = 9
exp(x) double double e mũ x exp(1.0) = 2.718282
log(x) double double Logarithm tự nhiên cơ
số e của x log(2.718282) = 1.0
log10(x) double double Logarithm tự nhiên cơ
số 10 của x log10(100.0) = 2.0
sin(x) double double sine của x sin(1.0) = 0.841471
cos(x) double double cosine của x cos(1.0) = 0.540302
ceil(x) double double Phần nguyên nhỏ nhất
không nhỏ hơn x ceil(2.3) = 3.0 ceil(-2.3) = -2.0 floor(x) double double Phần nguyên lớn nhất
56
1.2.8Biểu thức
Biểu thức là một chuỗi gồm các toán hạng và toán tửđược kết hợp với nhau. Cần chú ý rằng, đối với các biểu thức phức gồm sự kết hợp của nhiều toán tử và toán hạng với nhau thì nên sử dụng dấu ngoặc đơn để đảm bảo trình tự của các phép toán trong biểu thức được thực hiện đúng. Mỗi toán hạng có thể là hằng, biến, lời gọi hàm, hoặc biểu thức con. Toán tửtác động lên giá trị của toán hạng và cho ra một giá trị có kiểu nhất định. Vì vậy, mỗi biểu thức sẽ có một giá trị xác định. Giá trịđó có thể là giá trị
nguyên, giá trị thực, hoặc giá trị logic: true (1), false (0).