Vì xâu kí tự là một mảng nên không thể gán một xâu cho một biến, vì vậy
muốn thực hiện việc này thì phải viết một vòng lặp để copy từng kí tự một. Tuy
nhiên C cung cấp cho chúng ta một hàm strcpy(xâu1,xâu2) để copy xâu 2 lên
xâu1. Tuy nhiên hàm này không kiểm tra tính đúng đắn về kích thước ô nhớ của
xâu1 có đủ chứa xâu2 hay không, vì vậy khi sử dụng bạn phải kiểm tra vấn đề này.
64 trang |
Chia sẻ: nguyenlam99 | Lượt xem: 1007 | Lượt tải: 0
Bạn đang xem trước 20 trang tài liệu Bài giảng cơ sở lập trình (ngành hệ thống thông tin quản lý), để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
là địa chỉ của biến. Địa chỉ biến dùng
trong một số hàm như hàm scanf. Để nhận địa chỉ biến ta dùng phép toán :
&tên biến
2.2.2.2. Hằng
Hằng là các đại lượng mà giá trị của nó không thay đổi trong quá trình tính
toán. Dưới đây trình bày các loại hằng được sử dụng trong C :
a. Hằng dấu phẩy động (float và double) được viết theo hai cách
Cách 1: (dạng thập phân) : Số gồm phần nguyên, dấu chấm thập phân và
phần phân. Ví dụ : 123.45 -12345.67 1234.0
24
Chú ý: Phần nguyên hay phần phân có thể vắng mặt nhưng dấu chấm không
thể thiếu. Ví dụ: .34 hay 12.
Cách 2 (dạng khoa học hay dạng mũ) : Số được tách thành 2 phần là định trị
và phần bậc. Phần định trị là một số nguyên hoặc số thực dạng thập phân, phần bậc
là một số nguyên. Hai phần này cách nhau bởi ký tự e hoặc E. Ví dụ :
123.46E-4: Biểu diễn giá trị 0.012346
0.12E3: Biểu diễn giá trị 120.0
-12.5e-3: Biểu diễn giá trị -0.125
1E8: Biểu diễn giá trị 100000000.0
b. Hằng int: Là số nguyên có giá trị trong khoảng từ -32768 đến 32767.
Ví dụ :
-45 1234
Chú ý : phân biệt 123 và 123.0 : Số 123 là hằng nguyên còn 123.0 là hằng
thực (dấu phẩy động)
c. Hằng long được biết theo hai cách:
-4893L hoặc -4893l
(thêm L hoặc l vào đuôi). Một số số nguyên vượt ra ngoài miền xác định của
int cũng được xem là hằng long. Ví dụ : 453946L và 4563946 là hai hằng long có
cùng giá trị.
d. Hằng int hệ 8 được viết theo cách:
0c1c2c3.
Ở đây ci là một số nguyên trong khoảng từ 0 đến 7. Hằng nguyên hệ 8 luôn
luôn nhận giá trị dương. Ví dụ :
0345 là một hằng nguyên hệ 8. Giá trị của nó trong hệ 10 là
3*8*8 + 4*8 + 5 =229
e. Hằng nguyên hệ 16. Trong hệ này sử dụng 16 ký tự: 0,1,2,3,4,,15. Để
tránh nhầm lẫn giữa chữ số 11 và hai số 1 người ta dùng quy ước sau:
Cách viết Ý nghĩa
A hoặc a 10
B hoặc b 11
C hoặc c 12
25
D hoặc d 13
E hoặc e 14
F hoặc f 15
Hằng số hệ 16 có dạng : 0xc1c2c3 hoặc 0Xc1c2c3 trong đó ci là một
chữ số hệ 16. Ví dụ : 0xa9, 0Xa9, 0XA9 là 4 hằng số hệ 16 như nhau. Giá trị của
chúng trong hệ 10 là :
10*16+9=169 ;
f. Hằng ký tự là một ký tự riêng biệt được viết trong 2 dấu nháy đơn, ví dụ
‘a’. Giá trị của ‘a’ chính là mã ASCII của chữ a. Như vậy, giá trị của ‘a’ là 97 (xem
bảng mã ASCII). Hằng ký tự có thể tham gia vào các phép toán như mọi số nguyên
khác. Ví dụ
‘9’-‘0’=57-48=9
Hằng ký tự còn có thể được viết theo cách
‘\1c2c3’
Trong đó, c1c2c3 là một số hệ 8 mà giá trị của nó bằng mã ASCII của ký tự
cần biểu diễn. Ví dụ : chữ a có hệ 10 là 97 đổi hệ 8 là 0141. Vậy hằng ký tự ‘a’ có
thể viết dưới dụng’\144’. Đối với một vài hằng ký tự đặc biệt ta cần sử dụng cách
viết sau (thêm dấu \) :
Cách viết Ký tự
‘\’’ ’
‘\’’’ ’’
‘\\’ \
‘\n’ Chuyển dòng
‘\0’ (Null)
‘\t’ Tab
‘\b’ Backspace
‘\r’ CR (về đầu dòng)
‘\f’ LF (sang trang)
26
Chú ý :
Cần phân biệt các hằng ký tự ‘0’ và ‘\0’. Hằng ‘0’ ứng với chữ số 0 có mã
48, còn hằng ‘\0’ ứng với ký tự 0 (ký tự null) có mã 0.
Hằng ký tự thực sự là một số nguyên, vì vậy có thể dùng các số nguyên hệ
10 để biểu diễn ký tự. Ví dụ :
- Lệnh printf(‘‘%c%c’’,65,66) ; sẽ in ra AB
- Lệnh prinf(‘‘%c%c%c’’,7,7,7) ; phát ra 3 tiếng chuông.
g. Hằng xâu ký tự là một dãy ký tự bất kỳ đặt trong hai dấu nháy kép. Ví dụ :
“Ha noi”
“Hai Phong”
“” /* xâu rỗng*/
Xâu ký tự được lưu trữ trong máy dưới dạng một mảng có các phần tử là các
ký tự riêng biệt. Trình biên dịch tự động thêm ký tự xóa \0 vào cuỗi mỗi xâu – Ký
tự \0 được xem là dấu hiệu kết thúc của một xâu ký tự.
Chú ý: Cần phân biệt ‘a’ và “a”, ‘a’ là hằng ký tự được lưu trữ trong một
byte, còn “a” là hằng xâu ký tự được lưu trữ trong một mảng hai phần tử: phần tử
thứ nhất chứa mã chữ a còn phần tử thứ hai chứa \0.
h. Tên hằng
#define MaX 1000
Nghĩa là: tất cả các tên MAX trong chương trình xuất hiện sau toán tử này
đều được thay thế bằng 1000. Vì vậy, ta thường gọi MAX là tên hằng (hay macro),
nó biểu diễn số 1000. Một ví dụ khác, cho toán tử sau đây:
#define Pi 3.141593 đặt tên cho hằng float 3.141593 là Pi.
i. Một số ứng dụng của các hằng ký tự.
Các hằng kiểu int, long, float, double thường dùng trong tính toán, còn các
hằng ký tự và hằng xâu ký tự thường dùng trong in ấn.
#include"stdio.h"
main()
{
printf("\n hang dau phay dong: %10.2f %10.2f %10.2f
%10.2f",1456.456,123E4,-2.123,2345.5);
printf("\n\n hang nguyen: %10ld %10ld %10ld
%10ld",1456.456,123E4,-2.123,2345.5); }
27
2.2.3. Các kiểu dữ liệu
2.2.3.1. Khái niệm về kiểu dữ liệu
Dữ liệu là tất cả những gì được máy tính xử lý. Kiểu dữ liệu là một tập hợp các
giá trị và một tập hợp các phép toán trên các giá trị đó
Các kiểu dữ liệu cần tới máy xử lý có rất nhiều, tồn tại ở nhiều dạng khác
nhau về bản chất, về ý nghĩa.
Một kiểu dữ liệu được định nghĩa với 2 điểm chính là:
- Một tập hợp các giá trị mà một biến thuộc kiểu đó có thể nhận được
- Trên đó xác định một số phép toán
Dữ liệu được chứa trong bộ nhớ máy tính với một số lượng ô nhớ nhất định
tính theo đơn vị byte, ví dụ số nguyên loại int được lưu trữ trong 2 byte bộ nhớ.
Phân loại các kiểu dữ liệu
2.2.3.2 . Kiểu số nguyên
Một giá trị thuộc kiểu số nguyên là một phần tử thuộc tập các số nguyên mà
ta có thể biểu diễn được trên máy. Trong C có nhiều kiểu số nguyên với các giá trị
khác nhau. Kiểu số nguyên cơ bản nhất trong C là kiểu số nguyên có dấu được định
nghĩa với từ khoá int chiếm 2 bytes, phạm vi biểu diễn của nó là -32768 đến 32767.
Cách biểu diễn một số nguyên int như sau:
các kiểu số
nguyên
các kiểu số thực
kiểu ký tự
kiểu logic boolean
kiểu
dữ
liệu
kiểu vô
hướng
kiểu dữ liệu
có cấu trúc
kiểu con trỏ
kiểu cơ sở
kiểu vô hướng
do người lập
trình tự định
nghĩa
kiểu liệt
kê
kiểu array
kiểu struct
kiểu file
28
bit số 1: bit dấu
Nếu bit dấu =0 thì biểu diễn số dương
Nếu bit dấu =1 thì biểu diễn số âm
Các bit 2 ,3 , .., 16 biểu diễn giá trị của số dưới dạng số nhị phân
ví dụ
Biểu diễn cho số -653
Các hằng số nguyên được viết ra dưới dạng 0, 1, 2, 3 ... Với dấu dương +
hoặc dấu âm – hoặc không có dấu.
Trong C có nhiều kiểu số nguyên, với các dải giá trị khác nhau. Đặc biệt kiểu
char thực chất là kiểu kí tự, trong C cho phép dùng kiểu kí tự này như là kiểu số
nguyên. Nghĩa là trong các biểu thức số học thì kiểu char được sử dụng là số nguyên.
Bảng sau cho biết các kiểu số nguyên với các dải giá trị của nó
Kiểu biến Từ khoá Số byte Dải giá trị
character char 1 -128 127
integer int 2 -32768 32767
short integer short 2 - 32768 32767
long integer long 4 -21474836582147483647
unsigned character unsigned char 1 0255
unsigned integer unsigned int 2 065535
Unsigned short
integer
unsigned short 2 064535
unsigned long
integer
unsigned long 4 04294967295
Các phép toán trên số nguyên
Các phép tính số học: + (phép cộng ), - (phép trừ), * (phép nhân), / (phép
chia lấy nguyên), % (phép chia lấy dư)
29
Các phép tính logic số học & (phép and theo bit), | (phép or theo bit), ^ (phép
xor theo bit), ~ (phép phủ định theo bit, còn gọi là đảo bit)
Các phép so sánh: = (lớn hơn hay bằng), == (bằng
nhau), != (khác nhau), (lớn hơn).
Chú ý:
Phép chia 2 số nguyên là số nguyên, không phải là số thực (điều này khác
với ngôn ngữ lập trình pascal), muốn viết nó dưới dạng chính xác thì cần phải viết
(float) x/y (đây còn gọi là đổi kiểu).
Khi thực hiện các phép tính số học với các số nguyên cần lưu ý tránh sự tràn số.
Ngoài cách viết số dưới dạng thập phân, C còn cho phép biểu diễn các số
dưới dạng hexa (hệ 16) hoặc số hệ 8 với quy định: số hexa được viết bắt đầu là 0x
hoặc 0x. Ví dụ số 65 (thập phân) được viết là 0x41 hay 0x41, số 15 được viết là 0xf
hay 0xf. Còn số hệ 8 được viết bắt đầu là số 0. Ví dụ số 15 thập phân được viết là
017, số 34 được viết là 042 ....
Tuy nhiên các cách dùng này thường được sử dụng trong lập trình hệ thống
vì rất có lợi, còn thông thường ta nên hạn chế.
Khởi tạo giá trị cho một biến nguyên: trong một số trường hợp ta cần gán giá
trị ban đầu cho một biến nguyên, khi đó ta viết như sau:
int tên_biến=giá_trị;
ví dụ: int i, j=3; thay bởi cách viết thông thường int i,j; j=3;
Hằng số nguyên có định trước kiểu: để đảm bảo độ chính xác của hằng số
khi sử dụng, ta có thể định trước kiểu tường minh cho các hằng số nguyên theo quy
định là thêm một ký tự vào cuối dãy các chữ số, chữ l cho kiểu long integer; chữ
u cho kiểu unsigned; chữ ul cho kiểu unsigned long
ví dụ: 20000u: là số nguyên kiểu unsigned
123455660l : là số nguyên kiểu long integer
560ul là số nguyên kiểu unsigned long integer
0x3000l : là số nguyên kiểu long integer viết dưới dạng số hexa
012345u: là số nguyên kiểu unsigned viết dưới dạng hệ cơ số 8.
2.2.3.3. Kiểu số thực
Kiểu số thực là tập hợp các số thực có thể biểu diễn được trong máy tính và
được máy định nghĩa sẵn với từ khoá: float, double, long double
Bảng sau cho biết các kiểu số thực và dải giá trị của chúng
30
Kiểu biến Từ
khoá
Số byte dải giá trị
số thực với độ chính xác đơn
single-precision floating-point
float 4 1.2e-38 – 3.4e38
độ dài chính xác khoảng 7 chữ
số
số thực với độ chính xác kép
double-precision floating-point
doubl
e
8 2.2e-308 – 1.8e308
độ dài chính xác khoảng 15 chữ
số
số thực với độ chính xác kép
long double-precision floating-
point. Độ dài lớn
float 10 3.4e-4932 – 3.4e4932
độ dài chính xác khoảng 19 chữ
số
Cách viết số thực:
* Cách viết dưới dạng thập phân bình thường (số thực dấu phẩy tĩnh):
dùng dấu chấm để phân cách giữa phần nguyên và phần thập phân.
Ví dụ: 3.1416; -0.2234; 2.0
* Dạng viết có phần mũ hay dạng viết khoa học (số thực dấu phẩy
động): gồm 2 phần, phần định trị và phần mũ
Ví dụ: 456.576e+3 = 4.56576x102 sẽ được viết lại cho máy tính là
4.56576 e +2
phần định trị phần mũ
Phần định trị và phần mũ đều có thể có dấu đi kèm
Phạm vi biểu diễn của số thực lớn hơn rất nhiều so với số nguyên, nên số
thực thích hợp đối với những đại lượng có giá trị lớn với độ chính xác cao
Cách viết các hằng số thực trong c
Viết không cần phần thập phân: ví dụ 4.
Không cần dấu chấm (.) ở phần định trị nếu có phần mũ: 2e-3
Viết bình thường: 5.9
Không cần có số 0 đầu tiên: .987
Có thể dùng chữ e: 6.0e45
Chú ý:
31
Nhất thiết phải có dấu chấm (.)
Không được viết dấu cách ở phần mũ
Không dùng dấu phẩy (,).
Các phép toán các phép toán +, -, *, / đều có thể áp dụng cho các toán hạng
là các số thực, phép chia hai số thực cho kết quả là số thực. Không tồn tại phép % cho
kiểu số thực.
Khởi tạo giá trị đầu cho biến số thực tương tự số nguyên
Hằng số thực định trước kiểu: ta có thể viết trước hằng số thực định trước
kiểu tương tự như số nguyên bằng cách viết thêm một ký tự vào cuối dãy số theo
nguyên tắc: chữ l cho kiểu long; chữ f cho kiểu float.
Ví dụ: 0.908f là hằng số thực kiểu float
8756.908e-2l là hằng số thực kiểu long double
2.2.3.4. Kiểu kí tự (kiểu Char)
Các kí tự là tất cả các chữ viết mà ta thường dùng như các chữ cái a,b, ... ,
các chữ số 0, 1, 2, ... Các dấu phân đoạn câu như ; , ! ....
Kiểu kí tự trong C được định nghĩa với từ khoá char. Một giá trị kiểu kí tự là
một phần tử thuộc tập hữu hạn các kí tự được xếp có thứ tự và một trong các sắp
xếp đó là bảng mã ASCII, trong đó các kí tự được mã hoá bằng 1 byte, vì vậy bảng
mã có thể mã hoá được 256 kí tự, tuy vậy số kí tự cơ bản được gói trong 128 số đầu,
còn các số sau được gọi là phần mã mở rộng dùng để mã hoá các kí tự riêng của các
ngôn ngữ. Trong bảng mã ASCII, các kí tự từ 0 đến 31 là các kí tự điều khiển,
không in ra được, dùng để điều khiển các thiết bị ngoại vi. Phần còn lại bố trí toàn
bộ các chữ cái, các chữ số và các kí tự đặc biệt. riêng kí tự 127 lại là kí tự điều
khiển xoá.
Các kí tự điều khiển không nhìn thấy được mã hoá bằng dãy escape với cách
dùng dấu ‘\’.
Biểu diễn một hằng kí tự ta có thể dùng:
- Viết kí tự đó trong cặp ‘ ‘. Ví dụ ‘a’; ‘2’ ...
\ x hhh trong đó hhh là giá trị hexa- deciment của kí tự trong bảng mã ASCII
\ ddd trong đó ddd là giá trị giá trị số viết dưới dạng hệ cơ số 8 của kí tự trong bảng
mã ASCII.
32
Sau đây là bảng liệt kê các các kí tự điều khiển được mã hoá
Kí tự Dã
y mã
Giá trị trong bảng ASCII
đổ chuông (bel) \ a x07 7
xoá trái (backsspace) \ b x08 8
nhảy cách ngang \ t x09 9
nhảy cách đứng \ v x0b 11
xuống dòng mới \ n x0a 10
xuống dòng dưới \ f x0c 12
về đầu dòng \ x x0d 13
dấu “ \ “ x22 34
dấu ‘ / ‘ x27 39
dấu ? / ? x3f 39
dấu \ \ \ x5c 92
mã null (không) \ 0 x00 00
Bảng mã ASCII với 128 kí tự đầu
hexa-
decimal
0 1 2 3 4 5 6 7
0 0 @ p ` p
0 16 32 48 64 80 96 112
1 ! 1 a q a q
1 17 33 49 65 81 97 113
2 " 2 b r b r
2 18 34 50 66 82 98 114
3 # 3 c s c s
3 19 35 51 67 83 99 115
4 $ 4 d t d t
33
4 20 36 52 68 84 100 116
5 % 5 e u e u
5 21 37 53 69 85 101 117
6 & 6 f v f v
6 22 38 54 70 86 102 118
7 ' 7 g w g w
7 23 39 55 71 87 103 119
8 ( 8 h x h x
8 24 40 56 72 88 104 120
9 ) 9 i y i y
9 25 41 57 73 89 105 121
a * : j z j z
10 26 42 58 74 90 106 122
b + ; k [ k {
11 27 43 59 75 91 107 123
c , < l \ l |
12 28 44 60 76 92 108 124
d - = m ] m }
13 29 45 61 77 93 109 125
e . > n ^ n ~
14 30 46 62 78 94 110 126
f / ? o _ o
15 31 47 63 79 95 111 127
34
2.2.4.. Các phép toán
Trong C người ta phân biệt các loại phép toán sau:
a. Các phép toán số học:
phép toán ý nghĩa ví dụ
- đổi dấu một số thực hoặc nguyên -12 ; -a
+ cộng hai số thực hoặc nguyên 12+13.5 ; a+b
- trừ hai số thực hoặc nguyên 15-10; l2.l-3.2; a-b
* nhân hai số thực hoặc nguyên a*b; 12*5; 12.3 *2
/ chia hai số thực hoặc nguyên a/b; 23/3 ;23.3/2
% lấy phần dư của phép chia hai số nguyên a%b ;12%5 bằng 2
Các phép toán + và - (hai ngôi) có cùng độ ưu tiên, và nhỏ hơn số ưu tiên của
hai phép toán * và /. Bốn phép toán này lại có độ ưu tiên thấp hơn so với phép trừ
một ngôi.
b. Các phép toán quan hệ:
Phép toán Ý nghĩa Ví dụ
> so sánh lớn hơn, toán hạng là số
nguyên hay số thực
a>b
3>7 có giá trị 0
>= so sánh lớn hơn hoặc bằng, toán hạng
là số nguyên hoặc số thực
a>=b
7>=7 có giá trị 0
< so sánh nhỏ hơn, toán hạng là số
nguyên hay số thực
a<b
6<7 có giá trị 1
<= so sánh nhỏ hơn hoặc bằng, toán hạng
là số nguyên hay số thực
a<b
3<=7 có giá trị 1
== so sánh bằng nhau, toán hạng có thể là
số nguyên hay số thực
a==b
7= =7 có giá trị 1
!= so sánh không bằng nhau a!=b
7!=7 có giá trị 0
c. Các phép toán logic:
Trong C sử dụng 3 phép toán logic:
35
Liên từ ý nghĩa ví dụ
&& liên kết hai biểu thức logic. Giá trị cả hai
toán hạng có giá trị 1
ch >=’0’ && ch <=’9’
36 có giá trị 1
|| liên kết hai biểu thức quan hệ. Giá trị của
biểu thức là 1 khi một trong hai toán
hạng bằng 1
n =100 có giá trị
là l
! phép phủ định một ngôi.
!a
!12 có giá trị 0
!0 có giá trị là l
Hai phép toán && và || có số ưu tiên thấp hơn so với các phép toán quan hệ.
Tất cả các phép toán này lại có số ưu tiên thấp hơn phép phủ định một ngôi.
Các phép toán quan hệ và logic được sử dụng để thiết lập điều kiện rẽ nhánh
trong lệnh if và điều kiện kết thúc chu trình trong các câu lệnh for, while, do while.
Giá trị của toán hạng khác 0 sẽ được coi là true và ngược lại giá trị bằng 0 sẽ được
coi là false. Giá trị biểu thức quan hệ và lôgic sẽ bằng l nếu đúng và bằng 0 nếu sai.
d. Các phép toán tăng, giảm:
Giả định có câu lệnh: so = so+ 1;
Ta có thể viết gọn như sau: so++ ;
Toán tử ++ cho phép tăng giá trị của biến so (kiểu số nguyên hay con trỏ)
thêm 1 đơn vị.
Trong C có hai phép toán một ngôi để tăng và giảm các biến. Toán tử tăng
++ sẽ cộng thêm 1 vào toán hạng của nó, toán tử giảm -- sẽ trừ toán hạng đi 1. Toán
hạng ở đây có thể là biến nguyên, biến thực hoặc biến con trỏ (sẽ đề cập trong
chương 3). Các dấu phép toán ++ và -- có thể đứng trước hoặc đứng sau toán hạng,
như vậy chúng ta có thể viết:
toán tử trước khi dùng sau khi dùng
tăng 1 đơn vị ++ n n ++
giảm 1 đơn vị -- n n --
36
Sự khác nhau của n++ và ++n là ở chỗ: trong phép n++ thì n được tăng sau
khi giá trị của nó được sử dụng, còn trong phép ++n thì giá trị của n được tăng trước
khi nó được sử dụng. Đối với n-- và --n cũng vậy. Bảng sau tổng kết các nhận định
trên.
Giả sử trước mỗi phép tính i=3 và j =15
Phép toán Tương đương Kết quả
i = ++j; tăng trước j =j+1; i = j; i=16 và j =16
i = j++; tăng sau i = j; j = j+l; i =15 và j = 16
i++ ; i = i + l; i = 4
j = ++ i + 5; i= i + l; j = i + 5; i = 4 và j = 9
j = i++ +5; j = i + 5; i = i + l; i = 4 và i = 8
Các phép toán thao tác trên bit: đây là các phép toán thường gặp ở hợp ngữ
hơn là ở ngôn ngữ cấp cao, chúng cho phép xử lý đến từng bit của một số nguyên.
Các phép toán này không được dùng cho float hay double.
Phép toán ý nghĩa
& và nhị phân
| hoặc nhị phân
^ hoặc có loại trừ
<< dịch trái
>> dịch phải
~ bù 1
Ta nhắc lại rằng:
1&1 =1
1&0 = 0
0&1 = 0
0&0 = 0
1|1 = 1
1|0 = 1
0|1 = 1
0|0 = 0
1^1 = 0
1^0 =1
0^1 = 1
0^0 = 0
~1 = 0
~0 = 1
a<<n = a*2n
a>>n = a/2n
37
Chú ý về các phép chuyển dịch. Cũng như hợp ngữ, C phân biệt:
Các phép dịch chuyển số học, thực hiện trên các giá trị nguyên, bảo toàn bit
dấu, các phép dịch chuyển logic, thực hiện trên các giá trị unsigned, bít dấu không
đóng vai trò gì cả, cũng bị dịch chuyển như các bit khác.
e. Thứ tự thực hiện các phép toán
Dưới đây là bảng tổng hợp về thứ tự thực hiện các phép toán số học và quan
hệ trong C.
toán tử chiều tính toán
() [ ] -> trái -> phải
- ++ -- ! sizeof() là các toán tử một ngôi phải -> trái
* / % trái -> phải
+ - trái -> phải
> trái -> phải
>= trái -> phải
== != trái -> phải
& trái -> phải
^ trái -> phải
| trái -> phải
&& trái -> phải
| | trái -> phải
?: phải -> trái
= += -= *= /= %= &= ^= >= phải – trái
2.3. Các cấu trúc điều khiển
2.3.1. Lệnh vào/ra
2.3.1.1. Lệnh nhận giá trị cho biến từ bàn phím (hàm scanf())
Là lệnh cho phép đọc dữ liệu từ bàn phím và gán cho các biến trong chương
trình khi chương trình thực thi. Trong ngôn ngữ C, sử dụng hàm scanf, hàm này
nằm trong thư viện stdio.h.
38
Cú pháp: scanf(“Chuỗi định dạng”, địa chỉ của các biến);
Giải thích:- Chuỗi định dạng: dùng để qui định kiểu dữ liệu, cách biểu diễn,
độ rộng, số chữ số thập phân... Một số định dạng khi nhập kiểu số nguyên, số thực,
ký tự.
- Địa chỉ của các biến: là địa chỉ (&) của các biến mà chúng ta cần nhập giá
trị cho nó. Được viết như sau: &.
Ví dụ:
scanf(“%d”,&bien1);/*Doc gia tri cho bien1 co kieu nguyen*/
scanf(“%f”,&bien2); /*Doc gia tri cho bien2 co kieu thưc*/
scanf(“%d%f”,&bien1,&bien2); /*Doc gia tri cho bien1 co kieu nguyen,
bien2 co kieu thuc*/
scanf(“%d%f%c”,&bien1,&bien2,&bien3);/*bien3 co kieu char*/
Lưu ý:
Chuỗi định dạng phải đặt trong cặp dấu nháy kép (“”). Các biến (địa chỉ
biến) phải cách nhau bởi dấu phẩy (,). Có bao nhiêu biến thì phải có bấy nhiêu định
dạng. Thứ tự của các định dạng phải phù hợp với thứ tự của các biến.
Để nhập giá trị kiểu char được chính xác, nên dùng hàm fflush(stdin) để loại
bỏ các ký tự còn nằm trong vùng đệm bàn phím trước hàm scanf(). Để nhập vào
một chuỗi ký tự (không chứa khoảng trắng hay kết thúc bằng khoảng trắng), chúng
ta phải khai báo kiểu mảng ký tự hay con trỏ ký tự, sử dụng định dạng %s và tên
biến thay cho địa chỉ biến.
Để đọc vào một chuỗi ký tự có chứa khoảng trắng (kết thúc bằng phím
Enter) thì phải dùng hàm gets().
Ví dụ:
int biennguyen;
float bienthuc;
char bienchar;
char chuoi1[20], *chuoi2;
39
Nhập giá trị cho các biến: scanf(“%3d”,&biennguyen); Nếu ta nhập 1234455
thì giá trị của biennguyen là 3 ký số đầu tiên (123). Các ký số còn lại sẽ còn nằm lại
trong vùng đệm. scanf(“%5f”,&bienthuc); Nếu ta nhập 123.446 thì giá trị của
bienthuc là 123.4, các ký số còn lại sẽ còn nằm trong vùng đệm.
scanf(“%2d%5f”,&biennguyen, &bienthuc); Nếu ta nhập liên tiếp 2 số cách
nhau bởi khoảng trắng như sau: 1223 3.142325- 2 ký số đầu tiên (12) sẽ được đọc
vào cho biennguyen.- 2 ký số tiếp theo trước khoảng trắng (23) sẽ được đọc vào cho
bienthuc.
scanf(“%2d%5f%c”,&biennguyen, &bienthuc,&bienchar); Nếu ta nhập liên
tiếp 2 số cách nhau bởi khoảng trắng như sau: 12345 3.142325:
- 2 ký số đầu tiên (12) sẽ được đọc vào cho biennguyen.
- 3 ký số tiếp theo trước khoảng trắng (345) sẽ được đọc vào cho bienthuc.
- Khoảng trắng sẽ được đọc cho bienchar.
Nếu ta chỉ nhập 1 số gồm nhiều ký số như sau: 123456789:
- 2 ký số đầu tiên (12) sẽ được đọc vào cho biennguyen.
- 5 ký số tiếp theo (34567) sẽ được đọc vào cho bienthuc.
- bienchar sẽ có giá trị là ký số tiếp theo ‘8’.
scanf(“%s”,chuoi1); hoặc scanf(“%s”,chuoi2)
Nếu ta nhập chuỗi như sau: Nguyen Van Linh thì giá trị của biến chuoi1 hay
chuoi2 chỉ là Nguyen .
scanf(“%s%s”,chuoi1, chuoi2);
Nếu ta nhập chuỗi như sau: Duong Van Hieu thì giá trị của biến chuoi1 là
Duong và giá trị của biến chuoi2 là Van.Vì sao như vậy? C sẽ đọc từ đầu đến khi
gặp khoảng trắng và gán giá trị cho biến đầu tiên, phần còn lại sau khoảng trắng là
giá trị của các biến tiếp theo.gets(chuoi1);
Nếu nhập chuỗi : Nguyen Van Linh thì giá trị của biến chuoi1 là Nguyen
Van Linh
2.3.1.2. Lệnh xuất của biểu thức lên màn hình (hàm printf)
Là lệnh xuất giá trị của biểu thức lên màn hình. Trong C sử dụng hàm printf để thực
hiện lệnh này. Hàm này có trong thư viện stdio.h.
Cú pháp:printf(“Chuỗi định dạng ”, Các biểu thức);
Giải thích:
40
- Chuỗi định dạng: dùng để qui định kiểu dữ liệu, cách biểu diễn, độ rộng, số chữ số
thập phân...
Một số định dạng khi đối với số nguyên, số thực, ký tự.
Định dạng Ý nghĩa
%d Xuất số nguyên
%[.số chữ số
thập phân] f
Xuất số thực có theo quy tắc làm
tròn số.
%o Xuất số nguyên hệ bát phân
%x Xuất số nguyên hệ thập lục phân
%c Xuất một ký tự
%s Xuất chuỗi ký tự
%e hoặc %E
hoặc %g hoặc
%G
Xuất số nguyên dạng khoa học (nhân 10 mũ x)
Ví dụ
%d In ra số nguyên
%4d In số nguyên tối đa 4 ký số, nếu số cần in nhiều hơn 4 ký
số thì in hết
%f In số thực
%6f In số thực tối đa 6 ký số (tính luôn dấu chấm), nếu số cần
in nhiều hơn 6 ký số thì in hết
- Các biểu thức: là các biểu thức mà chúng ta cần xuất giá trị của nó lên màn hình,
mỗi biểu thức phân cách nhau bởi dấu phẩy (,).
Ví dụ:includeint
main(){
int bien_nguyen=1234, i=65;float bien_thuc=123.456703;
printf(“Gia tri nguyen cua bien nguyen =%d\n”,bien_nguyen);
printf(“Gia tri thuc cua bien thuc =%f\n”,bien_thuc);
printf(“Truoc khi lam tron=%f \n Sau khi lam tron=%.2f”,bien_thuc, bien_thuc);
return 0;}
Lưu ý: Đối với các ký tự điều khiển, ta không thể sử dụng cách viết thông
thường để hiển thị chúng.Ký tự điều khiển là các ký tự dùng để điều khiển các thao
tác xuất, nhập dữ liệu. Một số ký tự điều khiển được mô tả trong bảng:
41
Ký tự điều
khiển
Giá trị thập
lục phân
Ký tự
được hiển
thị
Ý nghĩa
\a 0x07 BEL Phát ra tiếng chuông
\b 0x08 BS Di chuyển con trỏ sang trái 1 ký tự và
xóa ký tự bên trái (backspace)
\f 0x0C FF Sang trang
\n 0x0A LF Xuống dòng
\r 0x0D CR Trở về đầu dòng
\t 0x09 HT Tab theo cột (giống gõ phím Tab)
\\ 0x5C \ Dấu \
\ddd ddd Ký tự có mã ACSII trong hệ bát phân là số ddd
\xHHH oxHHH Ký tự có mã ACSII trong hệ thập lục phân là HHH
Ví dụ:
#include
#include
int main ()
{
clrscr();
printf("\n Tieng Beep \a");
printf("\n Doi con tro sang trai 1 ky tu\b");
printf("\n Dau Tab \tva dau backslash \\");
printf("\n Dau nhay don \' va dau nhay kep \"");
printf("\n Dau cham hoi \?");
printf("\n Ky tu co ma bat phan 101 la \101");
printf("\n Ky tu co ma thap luc phan 41 la \x041");
printf("\n Dong hien tai, xin go enter");
getch();
printf("\rVe dau dong");
getch();
return 0;
}
2.3.2. Lệnh lựa chọn if
Toán tử if cho phép lựa chọn một trong hai nhánh tuỳ thuộc vào sự bằng
không hay khác không của một biểu thức:
Mẫu lệnh 1:
if (biểu thức) lệnh_1 else lệnh_2;
42
Hoạt động: khi gặp lệnh này, máy sẽ tính giá trị biểu thức, nếu biểu thức
cho giá trị khác không thì máy sẽ thực hiện lệnh_1, nếu biểu thức cho giá trị bằng 0
thì máy sẽ thực hiện lệnh_2.
Mẫu lệnh 2:
Hoạt động: khi gặp lệnh này, máy sẽ kiểm tra biểu thức, nếu biểu thức cho
giá trị khác không thì máy sẽ thực hiện lệnh_1, ngược lại thì thoát khỏi lệnh if.
Lệnh_1, lệnh_2 có thể là:
Một câu lệnh đơn giản, kết thúc bằng dấu chấm phẩy
Một khối lệnh nằm giữa cặp dấu { }
Câu lệnh có cấu trúc
Ví dụ:
Nhập vào hai số, đưa ra màn hình giá trị lớn nhất, nhỏ nhất của hai số đó
#include
#include
void main(){
int x,y,min,max;
clrscr();
printf(“hay go vao so nguyen thu nhat: “);
scanf("%d",&x);
printf(“\nhay go vao so nguyen thu hai: “);
scanf("%d",&y);
if (x>y) {
max=x;
min=y;
}
else {
max=y;
min=x;
}
printf(“gia tri lon nhat la: %d”,max);
if (biểu thức) lệnh_1 ;
43
printf(“\ngia tri nho nhat la: %d”,min);
getch();
}
Ta có thể thay thế câu lệnh if ... else ... Bằng toán tử điều kiện
max= (x>y)?x:y
min= (x<y) ? x:y
Hoặc
(x<y)?(min=y, max=x):(max=x, min=y)
Trong trường hợp này ta thấy lại khái niệm toán tử dãy phép tính (min=y,
max=x), trong đó các phép gán được phân cách nhau bởi dấu phảy ”,” chứ không
phải dấu chấm phảy “;”. sự khác nhau là nếu ta dùng dấu chấm phảy “;” thì ta có
hẳn hai câu lệnh là hai phép gán, còn nếu ta dùng dấu phảy ”,” thì đó là dãy phép
tính mô tả một câu lệnh được đặt trong dấu ().
+ Các lệnh if lồng nhau: trong các câu lệnh if (biểu thức điều kiện)
câu_lệnh; thì câu_lệnh có thể là bất cứ lệnh nào, vậy nó có thẻ là một lệnh if khác,
trong các trường hợp như vậy ta có các lệnh if lồng nhau.
Nếu trong một câu lệnh có nhiều if ... else thì ta luôn nhớ một nguyên tắc
sau: Else luôn gắn thuộc về if cuối cùng nếu như chưa có else nào gắn với nó.
Ví dụ: in hoá đơn thuế vat và chiết khấu %. số liệu ban đầu là giá hàng hoá
không thuế, sau đó tính giá bán chính thức bằng cách cộng thêm thuế giá trị gia tăng
= 18.6%. một tỷ lệ chiết khấu thưởng % cho khách hàng sẽ phụ thuộc vào giá trị lô
hàng là bao nhiêu:
0% nếu giá trị mặt hàng < 1000000 đồng
3% nếu giá trị mặt hàng >1000 000 đồng và <=10000000 đồng
6% nếu giá trị mặt hàng < 50 000 000 đồng
Văn bản chương trình
#include
#include
#define vat 18.6
void main(){
clrscr();
double nguyen_gia, gia_ban, ty_le,
chiet_khau,gia_tra;
44
printf("cho gia hang nguyen goc chua tinh thue:");
scanf("%lf",&nguyen_gia);
gia_ban=nguyen_gia*(1+vat/100);
if (gia_ban<1000000.) ty_le=0;
else if (gia_ban<10000000.) ty_le=3;
else if (gia_ban>50000000.) ty_le=6;
chiet_khau=gia_ban*ty_le/100;
gia_tra=gia_ban-chiet_khau;
printf("\ngia ban: %10.2lf",gia_ban);
printf("\nchiet khau: %10.2lf",chiet_khau);
printf("\ngia phai tra: %10.2lf",gia_tra);
getch();
}
2.3.3. Lệnh switch
Lệnh switch cho phép chọn một trong nhiều phương án
Mẫu lệnh
switch (biểu thức){
case hằng_1: {dãy lệnh 1};
case hằng_2: {dãy lệnh 2};
...
case hằng_n: {dãy lệnh n};
[default : {dãy lệnh n+1}]
}
Trong đó:
- biểu thức: là một biểu thức nguyên bất kì
- hằng_i: là các giá trị mà biểu thức có thể nhận được
- dãy lệnh i: một dãy các lệnh có thể thực hiện khi biểu
thức nhận giá trị hằng_i.
Hoạt động: khi gặp lệnh này, máy sẽ tính giá trị biểu thức, nếu biểu thức
nhận giá trị là hằng_1 thì máy sẽ thực hiện dãy lệnh_1, nếu biểu thức nhận giá trị là
hằng_2 thì máy sẽ thực hiện dãy lệnh 2, .... nếu trong câu lệnh có dùng tuỳ chọn
45
defaul: {dãy lệnh n+1} thì nếu máy không nhận giá trị nào trong các hằng_i , máy
sẽ tự động thực hiện dãy lệnh n+1
Ví dụ: Viết chương trình nhập vào một số có một chữ số, đưa ra màn hình
tên của chữ số đó.
#include
#include
void main(){
clrscr();
char ch;
ch=getchar();
switch (ch){
case '1': {printf("\nmot"); break;}
case '2': {printf("\nhai"); break;}
case '3': {printf("\nba"); break;}
case '4': {printf("\nbon"); break;}
case '5': {printf("\nnam"); break;}
case '6': {printf("\nsau"); break;}
case '7': {printf("\nbay"); break;}
case '8': {printf("\ntam"); break;}
case '9': {printf("\nchin"); break;}
case '0': {printf("\nkhong"); break;}
default: printf("\nkhong phai chu so");
}
getch();
return;
}
2.3.4. Vòng lặp xác định for (biết trước số lần lặp)
Mẫu lệnh for
dạng 1: dạng biểu thức
Dạng chức năng:
for ([biểu thức 1]; [biểu thức 2]; [biểu thức 3] ) câu lệnh;
46
Trong đó:
+ Các phần để trong ngoặc vuông là các phần tuỳ ý.
+ Các dấu “;” và dấu ngoặc đơn bắt buộc phải có.
+ Câu lệnh có thể là lệnh đơn, lệnh ghép hay lệnh có cấu trúc khác,
như vậy ta có thể có các vòng for lồng nhau. nếu câu lệnh là lệnh ghép thì phải đặt
trong cặp dấu “{” và “}”.
+ Câu lệnh có thể không có.
- Hoạt động: khi gặp lệnh này, máy xác định giá trị khởi tạo của biến,
sau đó kiểm tra biểu thức điều kiện, nếu điều kiện cho giá trị khác 0 thì máy
sẽ thực hiện câu lệnh rồi tăng giá trị của biến điều khiển và quay lại chương
trình. nếu điều kiện cho giá trị là 0 thì máy sẽ thoát khỏi vòng lặp.
Ví dụ 1:
Viết chương trình in ra màn hình các số từ 1 đến 24, mỗi số một dòng.
#include
#include
void main(){
clrscr();
int i;
for (i=1;i<=24;i++) printf("\n%d",i);
getch();
return;
công việc
biểu thức
bắt đầu
kết thúc
1
0
for ([khởi tạo]; [điều kiện]; [thay đổi điều kiện] ) câu lệnh;
47
}
Nếu ta sử dụng lệnh for dưới dạng chức năng thì chương trình trên có thể
viết như sau:
#include
#include
void main(){
clrscr();
int i;
i=1;
for (;i<=24;i++) printf("\n%d",i);
getch();
return;
}
Nghĩa là nếu biến điều khiển đã được khởi tạo rồi thì việc khởi tạo không cần
thiết nữa (nhưng dấu chấm phảy nhất thiết phải có)
ví dụ: Viết chương trình nhập vào một kí tự thường, sau đó chuyển sang chữ
hoa và in ra màn hình.
#include
#include
#include
#define eol '\n'
void main(){
clrscr();
char chu[80];
int tong,dem;
for (dem=0;(chu[dem]=getchar())!=eol;++dem);
tong=dem;
for(dem=0;dem<tong;++dem)
putchar(toupper(chu[dem]));
getch();
return;
}
48
Chú ý: Dòng lệnh for (dem=0;(chu[dem]=getchar())!=eol;++dem);
không có câu lệnh, trong trường hợp này dòng lệnh có tác dụng làm bộ đếm (vì kết
thúc lệnh này, ta nhận được giá trị của biến dem)
Ví dụ 3: Viết chương trình nhập vào n số nguyên, sau đó đưa ra màn hình
giá trị trung bình cộng của các số đó.
#include
#include
void main(){
clrscr();
int n,i;
float x,tbc,tong=0.;
printf("cho biet can tinh bao nhieu so: ");
scanf("%d",&n);
for (i=1;i<=n;++i){
printf("x%d=",i);
scanf("%f",&x);
tong+=x;
}
tbc=tong/n;
printf("\ntrung binh cong la: %f",tbc);
getch();
}
Nhận xét:
+ Biểu thức 1 bao giờ cũng chỉ được tính một lần.
+ Biểu thức 2, biểu thức 3 và công việc được thực hiện lặp đi lặp lại nhiều
lần trong chương trình.
Chú ý:
+ Khi biểu thức 2 vắng mặt thì nó luôn được được xem là đúng. trong trường
hợp này, muốn thoát khỏi vòng lặp thì cần phải có lệnh break, goto hoặc return.
+ Trong phần ngoặc tròn sau từ khoá for gồm 3 phần phân cách nhau bởi dấu
“;”. Có thể viết thiếu một biểu thức nhưng cũng có quyền viết một dãy biểu thức
phân cách nhau bởi dấu phảy trong mỗi biểu thức, khi đó các biểu thức trong mỗi
49
phần được xác định từ trái sang phải. tính đúng sai của dãy biểu thức trong phần thứ
hai được hiểu là tính đúng sai của biểu thức cuối cùng trong dãy.
Ví dụ: đảo ngược một dãy số cho trước
#include
#include
float x[]={63.2,-45.6,70.1,3.6,14.5};
int n=sizeof(x)/sizeof(float);
main(){
clrscr();
int i,j;
float c;
for (i=0,j=n-1;i<j;i++,j--){
c=x[i];
x[i]=x[j];
x[j]=c;
}
printf("\nday ket qua\n");
for (i=0;i<n;i++)
printf("%8.2f",x[i]);
getch();
return 0;
}
2.3.5. Vòng lặp không xác định do ... while ..
Mẫu lệnh :
Trong đó
+ Công việc là một hay nhiều lệnh, nếu có nhiều lệnh thì các lệnh
phải đặt trong cặp dấu “{” và “}”.
+ Dấu ngoặc đơn trong biểu thức là bắt buộc.
+ Biểu thức là một biểu thức logic hay biểu thức nguyên.
do
while (biểu thức);
50
Hoạt động: khi gặp lệnh này, máy sẽ thực hiện công việc, sau đó kiểm tra
biểu thức, nếu biểu thức cho giá trị khác 0 thì máy còn lặp lại công việc. nếu biểu
thức cho giá trị bằng 0 thì máy sẽ thoát khỏi vòng lặp.
Ví dụ : nhập vào các kí tự cho đến khi gặp kí tự ‘*’
#include
#include
void main()
{
char c;
clrscr();
do c=getchar(); while (c!='*');
getch();
}
Dòng lệnh do c=getchar(); while (c!='*'); còn có thể thay bởi dòng lệnh:
do while ((c=getchar()) !=’*’)
Lưu đồ minh hoạ lệnh do while (biểu thức)
Vòng lặp vô tận: do while (1);
Để thoát khỏi vòng lặp mà không cần điều kiện, dùng lệnh break
bắt đầu
công việc
biểu thức
kết thúc
đúng
sai
51
Ví dụ: viết chương trình tính ex theo công thức xấp xỉ taylor
ex= 1 + t(1) + t(2) + ... + t(n).
Trong đó số hạng thứ n của chuỗi t(n) = xn/n!
Nhận xét: ta thấy số hạng thứ k của chuỗi được xác định bởi công thức truy hồi
t(t) = t(k-1)*x/k
Chương trình:
#include
#include
void main(){
float e_mu,epsilon,x,t;
int n;
clrscr();
printf("nhap gia tri cua x= ");
scanf("%f",&x);
printf("nhap gia tri sai so epsilon= ");
scanf("%f",&epsilon);
e_mu=1;
n=1;
t=x;
do{
e_mu+=t;
n++;
t=t*x/n;
}while (t>epsilon);
printf("e mu %5.3f=%f ",x,e_mu);
getch();
}
2.3.6. Vòng lặp không xác định while ...
Mẫu lệnh:
while (biểu thức) ;
52
Trong đó:
+ Biểu thức là một biểu thức logic hay biểu thức nguyên
+ Công việc: có thể là một lệnh đơn giản hay một lệnh có cấu trúc
khác. nếu công việc gồm nhiều lệnh thì các lệnh phải để trong cặp dấu { ... },
khi này không có dấu “;” kết thúc. Để kết thúc công việc phải dùng dấu “;”.
Công việc có thể rỗng.
Hoạt động: khi gặp lệnh này, máy sẽ tính giá trị của biểu thức, nếu biểu
thức cho giá trị khác 0 thì máy sẽ thực hiện công việc, ngược lại thì sẽ thoát khỏi
vòng lặp chuyển sang câu lệnh sau thân lặp.
Chú ý:
+ Biểu thức phải được đặt trong cặp ().
+ Biểu thức luôn được tính toán đầu tiên nên cần phải có giá trị xác
định cho biểu thức đó.
Lưu đồ minh hoạ lệnh while (biểu thức) ;
Ví dụ 1:
Ta sử dụng lại ví dụ “ viết chương trình tính ex theo công thức xấp xỉ
taylor”. Đoạn code của chương trình như sau:
#include
#include
void main(){
sai
bắt đầu
biểu thức
công việc kết thúc
đúng
53
float e_mu,epsilon,x,t;
int n;
clrscr();
printf("nhap gia tri cua x= ");
scanf("%f",&x);
printf("nhap gia tri sai so epsilon= ");
scanf("%f",&epsilon);
e_mu=1;
n=1;
t=x;
while (t<epsilon){
e_mu+=t;
n++;
t=t*x/n;
}
printf("e mu %5.3f=%f ",x,e_mu);
getch();
}
Nhận xét:
+ Các biểu thức trong ngoặc tròn sau các lệnh while hay do ... while chẳng
những có thể đặt một biểu thức mà còn có thể đặt một dãy biểu thức phân cách nhau
bởi dấu phảy, tính đúng sai của dãy biểu thức được hiểu là tính đúng sai của biểu
thức cuối cùng.
+ Bên trong thân của một toán tử while hay do ... while ... Lại có thể sử
dụng các toán tử lặp khác, bằng cách đó ta có thể có các vòng lặp lồng nhau.
+ Phân biệt giữa lệnh while ... và do ... while ...
Trong lệnh do ... while ... công việc bao giờ cũng được thực hiện ít nhất là
một lần, còn trong lệnh while, công việc có thể không được thực hiện lần nào.
2.3.7. Các lệnh rẽ nhánh vô điều kiện
a. Lệnh break:
Dùng để kết thúc câu lệnh điều khiển đang thực hiện. nghĩa là khi gặp lệnh
này, máy sẽ dừng lặp để sang câu lệnh tiếp theo.
54
Khi gặp lệnh break trong thân các vòng lặp lồng nhau, máy sẽ thoát khỏi
vòng lặp sâu nhất chứa lệnh này.
b. Lệnh continue:
Cho phép chuyển sang vòng lặp tiếp theo mà không cần thực hiện phần còn
lại của vòng lặp đang thực hiện.
ví dụ:
#include
main(){
int i;
for (i=1;i<10;i++){
printf(“so thu %d”,i);
if (i<5) continue;
printf(“hay doi day!\n”);
}
getch();
}
c. Lệnh goto:
Lệnh nhảy goto chuyển điều khiển chương trình tới một nơi nào đó được gán
một nhãn label để đánh dấu.
Trong thân các vòng lặp có thể sử dụng các toán tử goto để nhảy ra khỏi
vòng lặp đến một vị trí bất kỳ mong muốn.
ví dụ:
#include
#include
main(){
clrscr();
int i;
for (i=1;i<=10;i++){
printf("bat dau vong %d\n",i);
printf("chao ban\n");
if (i==3) goto ra;
printf("ket thuc vong %d\n",i);
55
}
ra: printf("ket thuc vong lap!");
getch();
return 0;
}
Ghi nhớ
Khai báo biến bắt đầu bằng tên kiểu dữ liệu của biến, tiếp theo là tên biến;
nếu có thiếu biến, tên các biến được cách nhau bởi các dấu phẩy. Câu lệnh khai báo
được kết thúc bằng dấu chấm phẩy.
Định nghĩa hằng bằng toán tử #define.
Câu lệnh lựa chọn if chỉ thực hiện câu lệnh đi kèm khi điều kiện đưa mô tả
trong nó là đúng.
Câu if else có thể kiểm tra để thực hiện nhiều lựa chọn khác nhau. nếu có
nhiều điều kiện đúng, chỉ có câu lệnh đi sau điều kiện thỏa mãn lần đầu tiên được
thực hiện.
Một câu lệnh ghép có thể đặt ở bất cứ đâu, tại đó một câu lệnh để có thể có
mặt. một câu lệnh rỗng không làm gì. Biểu thức câu lệnh rỗng bằng cách đặt dấu
chấm phẩy thay thế cho cả câu lệnh.
Một câu lệnh lặp mô tả rằng một hành động được lặp lặp lại chừng nào biểu
thức vẫn còn đúng.
Thông thường một vài thao tác bên trong phần thân câu lệnh lặp có xu hướng
làm cho điều kiện của câu lệnh lặp trở lên bị sau.
Một giá trị có chứa phần không nguyên được xem là một số thực dấu phẩy
động được biểu thị bằng kiểu dữ liệu float.
Các lỗi thường gặp khi lập trình
Quên một hoặc cả hai dấu { và } để bắt đầu và kết thúc một câu lệnh ghép.
Đặt một dấu chấm phẩy sau điều kiện trong câu lệnh điều kiện if , điều đó
dẫn tới một lỗi logic.
Trong phần thân của câu lệnh while không có các câu lệnh nhằm làm cho
điều kiện trong while trở nên sai. thông thường, cấu trúc lặp như vậy sẽ không bao
giờ kết thúc. Chúng ta gọi đây là lỗi lặp vô hạn.
Viết các từ khoá với chữ hoa, ví dụ: while thay vì while.
Chia một số cho 0 - lỗi nặng.
56
Sử dụng phép toán (toán tử) tăng hoặc giảm số học đối với các hằng hoặc
biểu thức ví dụ ++ ( i+1 ) - lỗi cú pháp.
Một số thói quen lập trình tốt cần học tập
Tập thói quen viết chương trình có căn chỉnh lề để tăng tính dễ đọc.
Nếu có nhiều mức căn lề, mỗi mức phải được căn lề với cùng số khoảng
trống một cách rõ ràng.
Trước khi viết chương trình, nên viết sơ đồ khối mô tả thuật toán.
Một số lập trình viên thích viết trước các dấu { và } bắt đầu và kết thúc của
một câu lệnh ghép trước khi viết các câu lệnh thành phần bên trong câu lệnh ghép.
Khi thực hiện phép chia cho một biểu thức mà giá trị của biểu thức có thể
bằng 0. trong trường hợp đó phải kiểm tra trước khi chia để tránh gây lỗi cho
chương trình (fatal error).
Các toán tử một ngôi phải được đặt bên cạnh toán hạng của chúng không nên
đặt thêm các dấu trắng vào giữa.
Không nên so sánh bằng nhau các giá trị số thực.
2.4. Cấu trúc mảng
2.4.1. Khái niệm
Mảng (array) là một dãy liên tiếp các phần tử, mỗi phần tử chứa (hay có thể
chứa) một dữ liệu cùng một kiểu. một mảng các số nguyên gồm các phần tử là các
số nguyên. một mảng các con trỏ số nguyên bao gồm các thành phần, mỗi thành
phần là địa chỉ của một số nguyên.
Kích thước của mảng là số các phần tử. Kích thước này phải được khai báo
tường minh trong phần khai báo mảng, vì nó xác định vị trí và kích thước của vùng
nhớ được cấp phát cho mảng.
Mảng có thể có một hay nhiều chiều. Chúng ta có thể khai báo mảng với số
chiều là một, hai hay tùy ý. Ngôn ngữ C không giới hạn số chiều của mảng (nếu
như khả năng của máy cho phép).
Khai báo mảng
Một mảng cần khai báo để định rõ
+ loại mảng (int, float, double, ... )
+ tên mảng
+ số chiều và số phần tử của mỗi chiều
- Khai báo mảng một chiều
kiểu_phần_tử tên_mảng[số phần tử của mảng];
57
ví dụ:
int x[100]
khai báo mảng hai chiều
ví dụ: float y[3][5];
Là một mảng có 15 phần tử là số thực có số dòng là 3 và số cột là 5.
Các phần tử của mảng được đánh số theo sơ đồ sau
y[0,0] y[0,1] y[0,2] y[0,3] y[0,4]
y[1,0] y[1,1] y[1,2] y[1,3] y[1,4]
y[2,0] y[2,1] y[2,2] y[2,3] y[2,4]
Khi khai báo mảng, có thể khởi tạo ngay giá trị cho mảng
Ví dụ: int x[3]={4, 2, 6}. Nghĩa là x[0]=4; x[1]=2; x[2]=6;
float y[2][3]={{0.1, 0.5, 9.8}, {4.6, 3.6, 2.7}}
hay float y[2][3]={0.1, 0.5, 9.8, 4.6, 3.6, 2.7}
2.4.2. Truy nhập đến các phần tử của mảng
Các phần tử của mảng được cấp phát các khoảng nhớ liên tiếp nhau trong bộ
nhớ, điều đó có nghĩa là các phần tử của mảng có địa chỉ liên tiếp nhau. mỗi phần tử
của mảng được truy nhập trực tiếp thông qua tên mảng cùng chỉ dẫn truy nhập được
để trong cặp ngoặc vuông [].
Các phần tử của mảng luôn được đánh số từ 0 đến số phần tử của mảng - 1
Với khai báo int x[100], x là tên một mảng gồm 100 số nguyên, các phần tử
được xếp như sau:
x
[0]
x
[1]
x
[2]
x
[3]
.
..
.
..
.
..
.
..
x
[98] [99]
số phần tử của mảng là 100
tên mảng là x
kiểu_phần_tử là int
kiểu_phần_tử tên_mảng[số phần tửdòng][số phần tử cột];
58
Chỉ số của mảng bắt buộc phải có kiểu int và không vượt quá kích thước của
chiều tương ứng. Tuy nhiên biểu thức dùng làm chỉ số có thể là thực, khi đó giá trị
chỉ số là phần nguyên của biểu thức đó.
Khi chỉ số vượt ra ngoài kích thước của mảng máy sẽ không báo lỗi, nhưng
sẽ truy nhập đến một vùng nhớ ngoài vùng nhớ của mảng, điều đó có thể làm rối
chương trình.
ví dụ: Đọc các giá trị cho mảng x từ bàn phím
#include
#include
#define kichthuoc 5
void main(){
clrscr();
int x[kichthuoc];
int i;
for (i=0;i<kichthuoc;i++){
printf("x[%d]=",i);
scanf("%d",&x[i]);
}
printf("\ndoc lai mang vua nhap");
for (i=0;i<kichthuoc;i++)
printf("\nx[%d]=%d",i,x[i]);
getch();
return;
}
Để truy nhập vào mảng hai chiều, ngoài cách truy nhập thông qua chỉ số
hàng, chỉ số cột ra ta còn có thể truy nhập thông qua mảng một chiều.
Giả sử ta có khai báo: int a[3][2] là mảng hai chiều với số dòng là 3 và số
cột là 2 thì a[0] chứa địa chỉ hàng đầu, a[1] chứa địa chỉ hàng thứ hai, a[2] chứa địa
chỉ hàng thứ 3 và a chứa địa chỉ của a[0]. Như vậy mảng hai chiều là mảng của
mảng một chiều.
ví dụ: truy nhập mảng hai chiều
#include
59
#include
main(){
clrscr();
int tab[3][2],i,j;
for (i=0;i<3;i++)
for (j=0;j<2;j++) tab[i][j]=i*2+j+1;
for (i=0;i<3;i++)
printf("%d %d\n",tab[i][0],tab[i][1]);
getch();
return 0;
}
2.4.3. Xâu kí tự và mảng
Xâu kí tự trong C được định nghĩa như là một mảng các kí tự và có độ
dài của xâu kết thúc bằng kí tự “\0” hay còn gọi là kí tự null.
Khai báo xâu kí tự
char tên_xâu[số kí tự tối đa];
ví dụ:
char line[80]; thì line có thể chứa tối đa là 80 kí tự. Nếu ta dùng lệnh
gets(line) rồi ta nhập vào một xâu “chao cac ban” thì các kí tự của xâu được bố trí
như sau:
0 1 .. .. .. .. .. .. 8 9
0
Độ dài thực của xâu là 12, dãy trên được đánh số theo chỉ số của mảng, nghĩa
là bắt đầu từ 0.
Độ dài thực của xâu bằng số các kí tự trong xâu +1.
Khi khai báo xâu kí tự có thể khởi tạo cho xâu luôn và không có khai báo
kích thước cụ thể, khi đó chương trình dịch tự động bố trí đủ một mảng ô nhớ để
chứa dãy kí tự trên và kí tự kết thúc ‘\0’
60
ví dụ:
char xau[]=”cong hoa xa hoi chu nghia viet nam”;
Ta cũng có thể khai báo như sau:
char xau[40]=”cong hoa xa hoi chu nghia viet nam”;
Đây là cách khai báo có khởi tạo và dự trữ 40 byte ô nhớ, tuy nhiên hiện tại
máy không sử dụng hết số ô nhớ đó, nhưng với cách này ta có thể thay đổi nội dung
của xâu kí tự với tối đa là 39 kí tự.
Xác định độ dài xâu kí tự
Có thể xác định độ dài xâu kí tự bằng cách đếm, song C cung cấp cho ta hàm
strlen( xâu) dùng để xác định độ dài của xâu, hàm này được đặt trong file string.h.
ví dụ: nhập vào một xâu kí tự, cho biết độ dài của xâu
#include
#include
#include
void main(){
clrscr();
char str1[40]=”khoa cong nghe thong tin “;
printf(“do dai xau str1 la %d ki tu”,strlen(str1));
getch();
return;
}
Truy nhập vào các phần tử của xâu kí tự
Ta có thể truy nhập vào các phần tử của xâu thông qua tên biến và chỉ dẫn
truy nhập được đặt trong cặp [] như khi truy nhập vào các phần tử của mảng, chỉ
cần lưu ý rằng chỉ dẫn này bắt đầu từ 0.
Nếu chỉ dẫn nằm ngoài độ dài thực của xâu kí tự thì phần tử đó không xác
định. Vì vậy khi truy nhập vào phần tử của xâu ta cần kiểm tra xem vị trí đó có nằm
trong khoảng độ dài thực của xâu hay không.
Một số hàm cơ bản xử lý xâu ký tự
Ngôn ngữ lập trình C xây dựng lớp các hàm mẫu để xử lý xâu ký tự, các hàm
này được đặt trong file tiêu đề string.h
61
#include mô tả tóm tắt chức năng của hàm
strcpy(char dest[], char source[] ) sao chép nội dung xâu source vào xâu dest
strncpy(char dest[], char source[]) tương tự như strcpy(), nhưng ngừng sao chép
sau n ký tự. Trong trường hợp không có đủ số
ký tự trong source thì hàm sẽ điền thêm các ký
tự trắng vào xâu dest.
strcat(char ch1[], char ch2[]
nối xâu ch2 vào cuối xâu ch1. sau lời gọi hàm
này độ dài xâu ch1 bằng tổng độ dài của cả hai
xâu ch1 và ch2 trước lời gọi hàm.
strncat(char ch1[], char ch2[],int
n)
tương tự như strcat nhưng chỉ giới hạn với n
ký tự đầu tiên của ch2
int strcmp(char ch1[], char ch2[]) so sánh hai xâu ch1 và ch2. Nguyên tắc so
sánh theo kiểu từ điển. Giá trị trả về:
0 nếu xâu ch1 bằng xâu ch2
>0 nếu xâu lớn hơn xâu ch2
<0 nếu xâu ch1 nhỏ hơn xâu ch2
int strncmp(char ch1[], char
ch2[]), int n)
tương tự như strncmp(), nhưng chỉ giới hạn
việc so sánh với n ký tự đầu tiên của 2 xâu
int stricmp(char ch1[], char
ch2[]), int n)
tương tự như strcmp(), nhưng không phân biệt
chữ in và chữ thường
int strincmp(char ch1[], char
ch2[]), int n)
tương tự như stricmp(), nhưng việc so sánh chỉ
giới hạn ở n ký tự đầu tiên của mỗi xâu.
char *strchr(char s[], char c) tìm lần xuất hiện đầu tiên của ký tự C trong
xâu s, trả về địa chỉ của ký tự này
char *strrchar(char s[], char c) tương tự như hàm strchr(), nhưng việc tìm
kiếm bắt đầu từ cuối xâu
Tuy nhiên ta hoàn toàn có thể xây dựng các hàm để xử lý xâu ký tự. sau đây
là một vài ví dụ xây dựng các hàm :
Phép ghép xâu
ví dụ 1: có hai xâu str1, str2, ta ghép xâu str2 vào sau xâu str1
#include
62
#include
void main(){
clrscr();
char str1[40]=”xau thu nhat”;
char str2[40]=” xau thu hai”;
int dem1=0,dem2=0;
while (str1[dem1]!='\0') dem1++;
while (str2[dem2]!='\0') dem2++;
if
((sizeof(str1)/sizeof(str1[0]))<(dem1+dem2+1))
printf("khong the ghep vi thieu bo nho!");
else {
dem2=0;
while (str2[dem2] !='\0')
str1[dem1++]=str2[dem2++];
str1[dem1]='\0';
printf("\n%s",str1);
}
getch();
}
Copy xâu kí tự
Vì xâu kí tự là một mảng nên không thể gán một xâu cho một biến, vì vậy
muốn thực hiện việc này thì phải viết một vòng lặp để copy từng kí tự một. Tuy
nhiên C cung cấp cho chúng ta một hàm strcpy(xâu1,xâu2) để copy xâu 2 lên
xâu1. Tuy nhiên hàm này không kiểm tra tính đúng đắn về kích thước ô nhớ của
xâu1 có đủ chứa xâu2 hay không, vì vậy khi sử dụng bạn phải kiểm tra vấn đề này.
So sánh xâu kí tự
Khi so sánh hai xâu kí tự, các kí tự của hai xâu được so sánh theo từng cặp
một từ trái qua phải theo giá trị của bảng mã ASCII.
Nếu hai xâu có độ dài khác nhau song số kí tự giống nhau đến độ dài xâu
ngắn hơn thì xâu có độ dài ngắn hơn được coi là bé hơn.
Hai xâu kí tự bằng nhau nếu cả về nội dung và độ dài của chúng là giống
nhau.
63
Nếu hai xâu không bằng nhau thì hàm cho giá trị là hiệu số của mã ASCII
của hai kí tự đầu tiên khác nhau.
Ví dụ: nhập vào hai từ, sau đó đưa ra màn hình xem từ nào đứng trước
#include
#include
#include
void main(){
clrscr();
char tu1[20],tu2[20];
printf("\nhay go vao hai tu:\n 1:");
scanf("%s",&tu1);
printf("2:");
scanf("%s",&tu2);
if (strcmp(tu1,tu2)==0)
printf("hai tu bang nhau hoan toan");
else
printf("%s di truoc %s"
,(strcmp(tu1,tu2)<0)
?tu1:tu2,(strcmp(tu1,tu2)<0)?tu2:tu1);
getch();
}
Mảng các xâu kí tự
Ví dụ dưới đây cho thấy cách kết hợp giữa mảng và xâu kí tự.
#include
#include
void thucdon(char *tieude,char *lua[],int
kichthuoc);
main()
{
clrscr();
static char *chon[]={
"a>dd an address",
64
"e>dit an address",
"d>isplay an address"
};
static char tieude[40]="main menu\n\n";
thucdon(tieude,chon,3);
getch();
return 0;
}
void thucdon(char *tieude,char *lua[],int
kichthuoc)
{
int i;
printf(tieude);
for (i=0;i<kichthuoc;i++)
printf("%s\n",*(lua +i));
}
2.5. Con trỏ
2.5.1. Khái niệm con trỏ
Con trỏ là một biến chứa địa chỉ của một biến.
Vì có nhiều loại địa chỉ nên cũng có nhiều kiểu con trỏ tương ứng. Con trỏ
int chứa địa chỉ của các biến kiểu int, con trỏ kiểu float, kiểu double,... Cũng tương
tự như vậy.
Trong C, con trỏ thường được sử dụng vì với con trỏ thì chương trình có thể
được viết ngắn gọn hơn và hiệu quả hơn những cấu trúc khác.
2.5.2. Khai báo con trỏ
Cũng như các biến khác, một con trỏ phải được khai báo trước khi sử dụng.
Người lập trình phải chỉ ra kiểu của biến được trỏ tới.
Mẫu khai báo
kiểu_của_biến_được_trỏ *tên_biến_trỏ;
Các file đính kèm theo tài liệu này:
- bgcosolaptrinh_p1_4445.pdf