Kỹ thuật lập trì nh
7
CHươNG 2 LàM QUEN VớI NGôN NGữ C
* Giới thiệu ngôn ngữ C
Ngôn ngữ C do Dennis Ritchie là người đầu tiên đề xuất, đ thiế t kế và cà i
đặ t C trong môi trường UNIX. Nó có nguồn gốc từ ngôn ngữ BCPL do Martin
Richards đ ưa ra và o nă m 1967 và ngôn ngữ B do Ken Thompson phá t triể n từ
ngôn ngữ BCPL nă m 1970 khi viế t hệ điề u hà nh Unix.
C là ngôn ngữ lậ p trì nh đa dụng, cấ p cao nhưng lạ i có khả nă ng thực hiệ n
cá c thao tá c như của ngôn ngữ Assembly. Vì thế ngôn ngữ C nhanh chóng đ ược
cà i đ ặ t, sử dụ ng trê n má y vi tí nh và đ trở thà nh một công cụ lậ p trì nh khá mạ nh,
hiệ n nay đang có khuynh hướng trở thà nh một ngôn ngữ lậ p trì nh chí nh cho má y
vi tí nh trê n thế giới.
* Đặc điể m ngôn ngữ C
Ngôn ngữ C có những đặ c điể m cơ bả n sau :
- Tí nh cô đọng
(compact) : Ngôn ngữ C chỉ có 32 từ khoá chuẩ n, 40 toán
tử chuẩ n mà hầ u hế t được biể u diể n bởi cá c d y ký tự ngắ n gọn.
- Tí nh cấ u trúc
(structured) : Ngôn ngữ C có một tậ p hợp các phát biể u lậ p
trì nh cấ u trúc như phá t biể u quyế t định hoặ c lặ p. Do đó, nó cho phép chúng ta
viế t chương trì nh có tổ chức và dể hiể u.
- Tí nh tương thí ch
(compactable) : Ngôn ngữ C có bộ lệ nh tiề n xử lý và
cá c thư việ n chuẩ n là m cho cá c chương trì nh viế t bằ ng ngôn ngữ C có thể tương
thí ch khi chuyể n từ má y tí nh nà y sang má y tí nh kiể u hoà n toà n khá c.
- Tí nh linh động
(flexible) : Ngôn ngữ C là một ngôn ngữ rấ t linh động về
ngữ phá p, nó có thể chấ p nhậ n rấ t nhiề u cá ch thể hiệ n mà không có ở ngôn ngữ
khá c như Pascal, nó giúp cho kí ch thước m lệ nh có thể thu gọn lạ i để chương
trì nh thực thi nhanh chóng hơn.
- Biê n dịch
: Ngôn ngữ C đ ược biê n dịch bằ ng nhiề u bước và cho phép
biê n dịch nhiề u tậ p tin chương trì nh riê ng rẽ thà nh cá c tậ p tin đối tượng (object)
và nối cá c đối tượng đó lạ i với nhau (link) thà nh một chương trì nh thực thi thống
nhấ t.
I. CáC KHáI NIệM Cơ BảN
I.1. Cấu trúc cơ bản của một chương trì nh C
[tiề n xử lý]
[Cá c hà m]
main()
Kỹ thuật lập trì nh
8
{ [khai bá o biế n;]
[nhậ p dữ liệ u ;]
[xử lý ;]
[xuấ t ;]
}
Ví dụ
: Chương trì nh hiệ n trê n mà n hì nh câ u Chao cac ban
void main()
{ printf(Chao cac ban\n);
}
Một và i nhậ n xét quan trọng
:
- Chương trì nh C bao giờ cũng có một hay nhiề u hà m, trong đó có một
hà m chí nh bắ t buộc phả i có là hà m main(). Đâ y chí nh là hà m đ ược thực hiệ n
đầ u tiê n trong chương trì nh.
- Cặ p dấ u { } để xá c định một khối lệ nh.
- Hà m printf( Chao cac ban \n) là hà m chuẩ n của C dùng để xuấ t câ u
thông bá o Chao cac ban ra mà n hì nh. Ký tự \n là ký tự đặ c biệ t dùng để
xuống dòng.
- Dấ u ; để chấ m dứt một lệ nh.
- Chương trì nh C có phâ n biệ t chữ thường với chữ hoa. Đa số cá c từ khoá
của C đ ược viế t bằ ng chữ thường, còn một số í t đ ược viế t bằ ng chữ hoa mà ta
phả i tuâ n thủ chặ t chẽ , nế u không thì chương trì nh dịch sẽ không hiể u.
* Một vài ví dụ
Ví dụ 1
: In bả ng lũy thừa 2 của cá c số nguyê n từ 10 đế n 50
/* Chương trì nh in bì nh phương cá c số từ 10 đế n 50*/
#include <stdio.h>
void main()
{int n; /*Khai bá o biế n n kiể u nguyê n */
n=10; /*Gá n n=10 */
while (n<=50) /*Lặ p từ 10 đế n 50 bằ ng while */
{ printf(%3d \t %5d\n,n,n*n); /*in dạ ng 5d là dà nh 5 vị trí để in n và n
2
*/
n++; /* Tă ng n lê n 1 */
} /*Hế t while*/
} /*Hế t main*/
Kỹ thuật lập trì nh
9
Ví dụ 2 : Tương tự như ví dụ 1 nhưng viế t cá ch khá c :
#include <stdio.h>
#define max 50 /*Tiề n xử lý, định nghĩ a max =50*/
void main()
{ int n; /*Khai bá o biế n n kiể u nguyê n*/
for (n=10; n<=max; n++) /*Lặ p từ 10 đế n 50 bằ ng for*/
printf(%3d \t %5d\n,n,n*n); /*in n và n
2
dạ ng 5d là nă m chữ số*/
} /*Hế t main*/
Ví dụ 3
: Chương trì nh in lũy thừa 2, 3, 4, 5; có dùng hà m để tí nh lũy thừa :
#include <stdio.h>
#define max 50 /*Tiề n xử lý, định nghĩ a max =50*/
float luythua(int n, int m) /*Hà m luythua với 2 thông số*/
{ float s=1; /*Khai bá o và khởi tạ o biế n s*/
for ( ;m>0;m--) /*Lặ p giả m dầ n từ m tới 1*/
s=s*n;
return s; /*Trả kế t quả về */
}
void main()
{ int n,n2,n3,n4,n5; /*Khai bá o biế n kiể u nguyê n*/
for (n=10;n<=50;n++) /*Lặ p từ 10 đế n 50 bằ ng for*/
{ n2= luythua(n,2); /*Gọi hà m luythua*/
n3= luythua(n,3);
n4= luythua(n,4);
n5= luythua(n,5);
printf(%3d \t %5.2f \t %5.2f\t %5.2f\t %5.2f\t %5.2f\n,
n,n2,n3,n4,n5); /*in n và n
m
dạ ng 5 chữ số với 2 số lẻ */
}
} /*Hế t main*/
* Hàm xuất chuẩn printf()
Cú pháp
:
printf(chuỗi-địnhdạ ng,thamso1,thamso2,...)
ý nghĩ a
:
Hà m printf() sẽ xem xét chuỗi-địnhdạ ng, lấ y giá trị cá c tham số (nếu cầ n)
để đặ t và o theo yê u cầ u của chuỗi-địnhdạ ng và gởi ra thiế t bị chuẩ n.
Chuỗi-địnhdạ ng là một chuỗi ký tự, trong đó có những ký tự xuấ t ra
nguyê n vẹ n hoặ c xuấ t ở dạ ng đặ c biệ t, và có thể có những chuỗi điề u khiể n
cầ n lấ y giá trị của cá c tham số để thay và o đó khi in ra.
Kỹ thuật lập trì nh
10
- Những ký tự đặc biệ t :
Ký tự Tác dụng Mã ASCII
\n Xuống hà ng mới 10
\t Tab 9
\b Xóa ký tự bê n trá i 8
\r Con trỏ trở về đầ u hà ng 13
\f Sang trang 12
\a Phá t tiế ng còi 7
\\ Xuấ t dấ u chéo ngược 92
\ Xuấ t dấ u nhá y đơn 39
\ Xuấ t dấ u nhá y kép 34
\xdd Xuấ t ký tự có m ASCII dạ ng Hex là dd
\ddd Xuấ t ký tự có m ASCII dạ ng Dec là
ddd
\0 Ký tự NULL 0
- Chuỗi định dạng :
% [ flag][width][.prec][F
N
h
l] type
Type : định kiể u của tham số theo sau chuỗi-địnhdạ ng để lấ y giá trị ra
Type
ý nghĩ a
d,i Số nguyê n cơ số 10
u Số nguyê n cơ số 10 không dấ u
o Số nguyê n cơ số 8
x Số nguyê n cơ số 16, chữ thường(a,b,...,f)
X Số nguyê n cơ số 16, chữ in (A,B,...,F)
f Số thực dạ ng [-]dddd.ddd...
e Số thực dạ ng [-]d.ddd e[+/-]ddd
E Số thực dạ ng [-]d.ddd E[+/-]ddd
g,G Số thực dạ ng e(E) hay f tùy theo độ chí nh xá c
c Ký tự
s Chuỗi ký tự tậ n cùng bằ ng \0
% Dấ u % cầ n in
Kỹ thuật lập trì nh
11
Flag : Dạ ng điề u chỉ nh
Flag
ý nghĩ a
nế u không có in dữ liệ u ra với canh phả i
- in dữ liệ u ra với canh trá i
+ Luôn bắ t đầ u số bằ ng + hay -
# in ra tùy theo type, nế u:
0 : Chè n thê m 0 đứng trước giá trị >0
x,X : Chè n thê m 0x hay 0X đứng trước số nà y
e,E,f : Luôn luôn có dấ u chấ m thậ p phâ n
G,g : Như trê n nhưng không có số 0 đi sau
Width : định kí ch thước in ra
Width
ý nghĩ a
n Dà nh í t nhấ t n ký tự , điề n khoả ng trắ ng các ký tự còn trống
0n Dà nh í t nhấ t n ký tự , điề n số 0 cá c ký tự còn trống
* Số ký tự í t nhấ t cầ n in nằ m ở tham số tương ứng
Prec : định kí ch thước phầ n lẽ in ra
Prec
ý nghĩ a
không có độ chí nh xá c như bì nh thường
0 d,i,o,u,x độ chí nh xá c như cũ
e,E,f Không có dấ u chấ m thậ p phâ n
n nhiề u nhấ t là n ký tự (số)
* Số ký tự í t nhấ t cầ n in nằ m ở tham số tương ứng
Các chữ bổ sung :
F Tham số là con trỏ xa XXXX:YYYY
N Tham số là con trỏ gầ n YYYY
h Tham số là short int
l Tham số là long int (d,i,o,u,x,X)
double (e,E,f,g,G)
Ví dụ 1: char c=A;
char s[]=Blue moon! ;
Kỹ thuật lập trì nh
12
Dạng Thông số
tương ứng
Xuất Nhận xét
%c c A độ rộng 1
%2c c A độ rộng 2, canh phả i
%-3c c A độ rộng 3, canh trá i
%d c 65 M ASCII của A
%s s Blue moon! độ rộng 10
%3s s Blue moon! Nhiề u ký tự hơn cầ n thiế t
%.6s s Blue m Chí nh xá c 6 ký tự
%-11.8s s Blue moo Chí nh xá c 8, canh trá i
Ví dụ 2: int i = 123;
float x = 0.123456789;
Dạng Thông số
tương ứng
Xuất Nhận xét
%d i 123 độ rộng 3
%05d i 00123 Thê m 2 số 0
%7o i 123 Hệ 8, canh phả i
%-9x i 7b Hệ 16, canh trá i
%c i { Ký tự có m ASCII 123
%-#9x i 0x7b Hệ 16, canh trá i
%10.5f x 0.12346 độ rộng 10, có 5 chữ số thậ p
phâ n
%-12.5e x 1.23457e-01 Canh trá i, in ra dưới dạ ng
khoa học
Ví dụ 3: Viế t chương trì nh in hì nh chữ nhậ t kép bằ ng cá c ký tự ASCII
C9 CD BB
C8 CD BC
void main()
{ printf(\n\xC9\xCD\xBB);
printf(\n\xC8\xCD\xBC\n);
}
Kỹ thuật lập trì nh
13
I.2. Kiể u dữ liệ u cơ bản
I.2.1. định nghĩ a:
Kiể u dữ liệ u cơ bả n là kiể u dữ liệ u có giá trị đơn, không phâ n chia được
nữa như số, ký tự
I.2.2. Phân loại:
Tê n kiể u
ý nghĩ a
Kí ch
thước
Phạm vi
char Ký tự 1 byte
-128
127
unsigned char Ký tự không dấ u 1 byte
0
255
unsigned short Số nguyê n ngắ n không dấ u 2 bytes
0
65535
enum Số nguyê n có dấ u 2 bytes
-32768
32767
short int Số nguyê n có dấ u 2 bytes
-32768
32767
int Số nguyê n có dấ u 2 bytes
-32768
32767
unsigned int Số nguyê n không dấ u 2 bytes
0
65535
long Số nguyê n dà i có dấ u 4 bytes
-2147483648
2147483647
unsigned long Số nguyê n dà i không dấ u 4 bytes
0
4294967295
float Số thực độ chí nh xá c đơn 4 bytes
3.4 E-38
3.4 E+38
double Số thực độ chí nh xá c kép 8 bytes
1.7 E-308
1.7
E+308
long double Số thực độ chí nh xá c hơn
double
10 bytes
3.4 E-4932
1.1
E+4932
Chú ý
:
1. Ngôn ngữ C không có kiể u logic (boolean như Pascal) mà quan niệ m
0 là false ; Khá c 0 là true
2. Ngôn ngữ C không có kiể u chuỗi như kiể u string trong Pascal
3. Cá c kiể u đồng nhấ t:
int = short int = short = signed int = signed short int
long int = long
signed long int = long
unsigned int = unsigned = unsigned short = unsigned short int
unsigned long int = unsigned long
Kỹ thuật lập trì nh
14
I.3. Biế n
I.3.1. Tê n biế n : Tê n biế n là một chuỗi ký tự bắ t đầ u bằ ng ký tự chữ, ký tự
kế tiế p là ký tự chữ (dấ u gạ ch dưới _ đ ượ c xem là ký tự chữ ) hoặ c số và khô ng
đ ược trùng với cá c từ khóa của C.
Chú ý
: - Ngôn ngữ C phâ n biệ t chữ thường với chữ hoa nê n biế n chữ
thường với chữ hoa là khá c nhau.
Ví dụ
: Bien_1 _bien2 là hợp lệ
bi&en 2a a b là không hợp lệ
- Ngôn ngữ C chỉ phâ n biệ t hai tê n hợp lệ với nhau bằ ng n ký tự đầ u tiê n
của chúng. Thông thường n=8, nhưng hiệ n nay nhiề u chương trì nh dịch cho phép
n=32, như Turbo C cho phép thay đổi số ký tự phâ n biệ t từ 8-32)
Ví dụ
:Hai biến sau bị xem là cùng tê n
bien_ten_dai_hon_32_ky_tu_dau_tien_1
bien_ten_dai_hon_32_ky_tu_dau_tien_2
I.3.2. Khai báo biế n
Các biến phải được khai bá o trước khi sử dụng nhằ m giúp cho chương
trì nh dịch có thể xử lý chúng.
Khai bá o biế n có dạ ng :
Kiể udữliệ u tê nbiế n1 [,tenbiế n2 ...] ;
Ví dụ: int a,b,c;
float x,y,delta;
char c;
* Khai bá o và khởi tạ o biế n
:
Kiể u dữ liệ u tê nbiế n = giá trị ;
I.3.3. Hàm nhập dữ liệ u chuẩn
a) Hàm scanf()
Cú pháp
: scanf(chuỗi-địnhdạ ng,điạ chỉ thamsố 1, điạ chỉ thamsố2,...)
- Chuỗi-địnhdạ ng của scanf() gồm có ba loạ i ký tự :
+ Chuỗi điề u khiể n
+ Ký tự trắ ng
+ Ký tự khá c trắ ng
! Chuỗi điề u khiể n có dạ ng :
%[width][h/l] type
Kỹ thuật lập trì nh
15
Với type: xá c định kiể u của biế n địa chỉ tham số sẽ nhậ n giá trị nhậ p và o
Type
ý nghĩ a
d,i Số nguyê n cơ số 10 (int)
o Số nguyê n cơ số 8 (int)
u Số nguyê n cơ số 10 không dấ u (unsigned)
x Số nguyê n cơ số 16 (int)
f,e Số thực (float)
c Ký tự (char)
s Chuỗi ký tự
p Con trỏ (pointer)
lf Số thực (double)
Lf Số thực (long double)
Width : xá c định số ký tự tối đa sẽ nhậ n và o cho vùng đó.
Hà m scanf() chỉ nhậ n cho đủ width ký tự hoặ c cho đế n khi gặ p ký tự trắ ng
đầ u tiê n. Nế u chuỗi nhậ p và o nhiề u hơn thì phầ n còn lạ i sẽ dành lạ i cho lầ n gọi
scanf() kế tiế p.
Ví dụ 1
: scanf(%3s,str);
Nế u nhậ p chuỗi ABCDEFG
thì scanf() sẽ nhậ n tối đa 3 ký tự cấ t và o mả ng str, còn DEFG sẽ được lấ y
nế u sau đó có lầ n gọi sanf(%s,str) khá c.
Ví dụ 2
: unsigned long money;
scanf(%lu,&money);
Lưu ý
: Nế u scanf(%ul, &money) thì giá trị nhậ p và o sẽ không được lưu
trữ trong biế n money, nhưng chương trì nh dịch không bá o lỗi.
Ví dụ 3
: Nhậ p và o tê n và bị giới hạ n trong khoả ng [A-Z,a-z]
char name[20];
printf(Name : ) ;
scanf(%[A-Za-z],&name);
Trong trường hợp nà y, nế u ta gõ sai dạ ng thì name =
! Ký tự trắ ng: nế u có trong chuỗi-dạ ng sẽ yê u cầ u scanf() bỏ qua một hay
nhiề u ký tự trắ ng trong chuỗi nhậ p và o. Ký tự trắ ng là ký tự khoả ng trắ ng ( ),
tab (\t), xuố ng hà ng (\n). Một ký tự trắ ng trong chuỗi-địnhdạ ng sẽ được hiể u
là chờ nhậ p đế n ký tự khá c trắ ng tiế p theo.
Kỹ thuật lập trì nh
16
Ví dụ 4: scanf(%d ,&num);
Hà m scanf() cho ta nhậ p một ký tự khá c trắ ng nữa thì mới thoát ra. Ký tự
đó sẽ nằ m trong vùng đệ m và sẽ được lấ y bởi hà m scanf() hoặ c gets() tiế p theo.
! Ký tự khá c trắ ng: nế u có trong chuỗi-địnhdạ ng sẽ khiế n cho scanf() nhậ n
và o đúng ký tự như thế .
Ví dụ 5
: scanf(%d/%d/%d,&d,&m,&y);
Hà m scanf() chờ nhậ n một số nguyê n, cấ t và o d, kế đế n là dấ u /, bỏ dấu
nà y đi và chờ nhậ n số nguyê n kế tiế p để cấ t và o m. Nế u không gặ p dấ u / kế
tiế p số nguyê n thì scanf() chấ m dứt.
Chú ý
: Hà m scanf() đòi hỏi cá c tham số phả i là cá c địa chỉ của cá c biến
hoặ c là một con trỏ.
* Toá n tử địa chỉ &
: Lấ y địa chỉ của một biế n
Ví dụ 6
: int n;
biế n n
&n;
địa chỉ của n
printf(trị = %d, địa chỉ = %d,n,&n);
b) Hàm getch():
Hà m getch() dùng để nhậ n một ký tự do ta nhậ p trê n bà n phí m mà không
cầ n gõ Enter với cú phá p :
ch = getch(); Không hiệ n ký tự nhậ p trê n mà n hì nh
ch = getche(); Hiệ n ký tự nhậ p trê n mà n hì nh
Với ch là biế n kiể u char.
Ví dụ 7
:
void main()
{ char ch;
printf(Go vao ky tu bat ky : );
ch = getche();
printf(\n Ban vua go %c,ch);
getch();
}
Ví dụ 8
: Bạ n nhậ p và o 1 chữ cá i. Nế u chữ cá i nhậ p và o là 'd' thì chương
trì nh sẽ kế t thúc, ngược lạ i chương trì nh sẽ báo lỗi và bắ t nhậ p lạ i.
#include <stdio.h>
#include <conio.h>
void main()
{ char ch;
Kỹ thuật lập trì nh
17
printf("\nBan nhap vao 1 chu cai tu a den e: ");
while ((ch=getche()) != 'd')
{ printf("\nXin loi, %c la sai roi",ch);
printf("\n Thu lai lan nua. \n");
}
}
Lưu ý
: Hà m getch() còn cho phép ta nhậ p và o 1 ký tự mở rộng như cá c
phí m F1, F2,.., cá c phí m di chuyể n cursor. Cá c phí m nà y luôn có 2 bytes: byte
thứ nhấ t bằ ng 0, còn byte 2 là m scancode của phí m đó. Để nhậ n biế t ta đ gõ
phí m ký tự hay phí m mở rộng, ta có chương trì nh sau:
void main()
{
int c;
int extended = 0;
c = getch();
if (!c)
extended = getch();
if (extended)
printf("The character is extended\n");
else
printf("The character isn't extended\n");
}
Phí m Mã scancode
F1 59
F2 60
F3 61
F4 62
F5 63
F6 64
F7 65
F8 66
F9 67
F10 68
Home 71
"
72
#
80
$
75
Kỹ thuật lập trì nh
18
%
77
PgUp 73
PgDn 81
End 79
Ins 82
Del 83
Bả ng m scancode của cá c phí m mở rộng
c. Hàm kbhit
(): Hà m int kbhit() sẽ kiể m tra xem có phí m nà o đ ược gõ
và o hay không. Nế u có, hà m kbhit sẽ trả về một số nguyê n khá c 0, và ngược lạ i.
Ký tự mà ta nhậ p và o qua hà m kbhit() có thể lấ y đ ược qua hà m getch()
hoặ c getche().
Ví dụ
:
void main()
{
printf("Press any key to continue:");
while (!kbhit()) /* do nothing */ ;
char kytu=getch();
printf("\nKy tu vua an : %c",kytu);
}
I.4 Hằng
: Hằ ng là cá c đạ i lượng mà giá trị của nó không thay đổi trong quá
trì nh chương trì nh thực hiệ n.
I.4.1. Phân loại :
a.
Hằng số
: là cá c giá trị số đ xá c định và không đổi.
int unsigned long hệ 8 hệ 16 float/double
Dạ ng nnnn
-nnnn
nnnnU/u
nnnnL/l
-nnnnl/L
0nnnn 0xnnnn nnnn.nnnn
nnnn.nnnE/e
nnn
Ví dụ 4567
-12
123U
12uL
456789L
-1234L
0345 0x1AB 123.654
123.234E-4
Chú ý
:
- Cá c hằ ng số viế t không dấ u hoặ c không số mũ đ ược hiể u là số nguyê n,
ngược lạ i là double.
- Cá c hằ ng số nguyê n lớn hơn int sẽ được lưu trữ theo kiể u long, còn lớn
hơn long thì đ ược lưu trữ theo kiể u double.
- Cá c hằ ng số nguyê n dương lớn hơn long sẽ đ ược lưu trữ theo kiể u double
- Một hằ ng số đ ược lưu trữ theo dạ ng long nế u theo số đó có ký tự l (L),
Kỹ thuật lập trì nh
19
dạ ng unsigned nế u sau đó có chữ u (U), dạ ng thậ p lục phâ n nế u trước số
đó có 0x và dạ ng bá t phâ n nế u trước số đó có 0
Ví dụ
: 50000; 10 L;
Long
5U, 100u
unsigned
0x10
hệ 16 = 16
10
010
hệ 8 = 8
10
b.
Hằng ký tự
: là ký tự riê ng biệ t đ ược viế t trong hai dấ u nhá y đơn : A
Giá trị của hằ ng ký tự là m ASCII của nó.
Ví dụ
: printf(%c có giá trị là %d,A,A);
% A có giá trị là 65
& 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ó thể là cá c ký tự đặ c biệ t dạ ng \c
1
mà ta đ xét ở hà m
printf() như \n,\a,\t ...
c.
Hằng chuỗi
: Là một chuỗi ký tự nằ m trong hai dấ u nhá y kép .
Ví dụ
: Day la mot chuoi
Hang chuoi co ky tu đạ c biệ t như \ \n \248
chuỗi rỗng.
Chú ý
:
- Phân biệt A
A
Hằ ng: Chuỗi Ký tự
Dạ ng lưu trữ :
A \0 A
- Nhậ n xét: ở dạ ng lưu trữ, ta thấ y tậ n cùng của chuỗi có ký tự NULL \0
mà không có ở dạ ng ký tự. Chí nh vì vậ y mà không có ký tự rỗng .
- Một chuỗi có thể đ ược viế t trê n nhiề u hà ng với điề u kiệ n hà ng trê n phả i
có dấ u \.
Ví dụ
:Day la mot chuoi duoc viet tren \
nhieu hang \n
d.
Hằng biể u thức
: Là một biể u thức mà trong đó cá c toá n hạ ng đề u là
cá c hằ ng. Khi đó chương trì nh dịch sẽ tí nh toá n biểu thức trước, và kế t quả đ ược
lưu trữ thẳ ng bằ ng một hằ ng số tương đ ương.
Ví dụ : 8*20-13
kế t quả lưu trữ là 173
Kỹ thuật lập trì nh
20
a -A
là 97-65 = 32
1<8
là 0 (sai)
I.4.2. Khai báo hằng:
Cú pháp
: const tê nhằ ng = biể uthức;
Ví dụ
: const MAX = 50;
const PI = 3.141593;
Chú ý
: - Ta có thể khai bá o hằ ng bằ ng cá ch định nghĩ a 1 macro như sau:
#define tê nhằ ng giá trị
- Lệ nh #define phả i đ ược khai bá o ngoà i hà m và sau nó không có
dấ u ;
I.5. Phép toá n
I.5.1. Phép gán:
Cú pháp
: biế n = biể u thức;
Chú ý
: Phép gá n trong ngôn ngữ C trả về một kế t quả là trị của biể u thức
Ví dụ 1
: c = 10;
a = b = c;
printf(a=%d , b=%d,a,b);
a=10,b=10
Ví dụ 2
: x = b + 2*c;
y= a + (x= b + 2*c)
y = a + x;
Ví dụ 3
: (n+3) = 4+z; (không hợp lệ vì bê n trá i là biể u thức)
= c +o; (không hợp lệ vì bê n trá i là hằ ng)
I.5.2. Các phép toán số học :
a.
Phép toán hai toán hạng
: +, -, *, /, %
Phép toán Kiể u toán hạng Kiể u kế t quả
+, -, * char, int, long, float,
double
Kiể u của toá n hạ ng có kiể u cao nhấ t
/ nguyê n/nguyê n Kiể u nguyê n và là phép chia nguyê n
thực(nguyê n)/thực
(nguyê n)
Kiể u thực và là phép chia thực
% nguyê n/nguyê n Kiểu nguyê n và là phép chia lấ y phầ n dư
Ví dụ :
#include <stdio.h>
void main()
Kỹ thuật lập trì nh
21
{ char cv;
int iv = 121;
float fv1,fv2;
printf( Chuyể n kiể u :\n\n);
cv = iv;
printf(int đ ược gá n cho char : %d
%d (%c)\n\n,iv,cv,cv);
fv1 = iv/50;
printf( int : %d / 50 = %f \n\n,iv,fv1);
fv1 = iv/50.0;
printf( float : %d / 50.0 = %f \n\n,iv,fv1);
fv1 = 1028.75;
fv2 = fv1 +iv ;
printf( %f + %d = %f \n\n,fv1,iv,fv2);
getch();
}
b.
Phép toán một toán hạng
: phép tă ng ++, phép giả m --
a++ hoặ c ++a
a = a+1
a-- hoặ c --a
a = a-1
Chú ý
: Tuy nhiê n a++ sẽ khá c ++a khi chúng đứng trong biể u thức (có
phép gá n).
a++ : Tă ng a sau khi giá trị của nó đ ược sử dụng.
++a : Tă ng a trước khi giá trị của nó đ ược sử dụng.
Ví dụ
:
main()
a b n
{ int a=4 , b=6, n;
n = a + b;
n = a++ + b;
n = ++a + b;
n = --a + b;
n = a-- + b;
n = a+ b;
}
4
4
5
6
5
4
4
6
6
6
6
6
6
6
10
10
12
11
11
10
I.5.3. Phép gán phức hợp:
Cú pháp
: biế n op= <biể uthức>
biế n = biế n op <biể uthức>
Với op là phép toá n.
Kỹ thuật lập trì nh
22
Cá c phép gá n phức hợp : += , -= , *= , /= , %= , <<= , >>=
Ví dụ
:n = n*(10+x)
n *= (10 +x)
n = n % 10
n %= 10
I = I +3
I += 3
<< : là phép dịch chuyể n bit qua trá i .
>> : là phép dịch chuyể n bit qua phả i .
I.5.4. Phép toán quan hệ :
< : nhỏ hơn
> : lớn hơn
>= : lớn hơn hoặ c bằ ng
<= : nhỏ hơn hoặ c bằ ng
!= : khá c
== : bằ ng
Chú ý
:
- Phâ n biệ t toá n tử so sá nh == với phép gá n =
- C không có kiể u dữ liệ u boolean mà qui ước : Giá trị 0 là sai
Giá trị !=0 là đúng
Ví dụ
:
a=10;
b= (a>6)*(a-6)
b = 4
c= (a< 5)*(a-5)
c = 0
Ví dụ
: Tì m số lớn nhấ t trong 3 số nguyê n a, b, c
#include <stdio.h>
#include <conio.h>
void main ()
{ int a, b, c, max;
printf(Chương trì nh tì m số lớn nhấ t trong 3 số);
printf(Nhậ p a, b, c);
scanf(%d %d %d , &a, &b, &c);
max = a;
if (max<b) max = b;
if (max<c) max = c;
printf(Số lớn nhấ t = %d, max);
getch();
}
Kỹ thuật lập trì nh
23
I.5.5.Toán tử logic:
Toán tử
ý nghĩ a
NOT ! Phủ định
AND && Giao, và
OR || Hội
Thứ tự tí nh toá n từ trê n xuống.
Bả ng châ n trị
:
x ! x x y x && y
true false true true true
false true true false false
false true false
false false false
x y x || y
true true true
false true true
false true true
false false false
Ví dụ 1: Xét ký tự c có phả i là ký số hay không?
char c;
if (c >= 0 && c <= 9)
printf (% c là kí tự số , c);
Ví dụ 2
: Xét ký tự ch là chữ cá i hay không?
if ((ch> =a) and (ch< =z)) or ((ch> =A) and (ch< =Z))
printf(%c là chu cai \n,ch);
Ví dụ 3
:
int a=10, b=5, c=0;
a && b
1
a && c
0
a | | c
1
Ví dụ 4
:
int a=10, b=5;
Kỹ thuật lập trì nh
24
int i=2, j=0;
(a>b) && (i<j)
0
(a<b) | | (i>j)
1
Ví dụ 5
:
n=5;
while (n)
{ printf("\nSố n = %d",n);
n--;
}
I.5.6. Toán tử phẩy:
Cú pháp
:
T = (exp1, exp2, exp3 ); // T = kế t quả của exp3
Ví dụ: m= (t=2, t*t+3)
m=7; t=2
c= (a=10,b=5,a+b);
a=10, b=5, c=15
I.5.7. Toán tử điều kiện:
Cú pháp
:
T = <điề u kiệ n> ? <bt1> : <bt2>;
Nế u <điề u kiệ n> là đúng thì T = <bt1> , ngược lạ i T = <bt2>
Ví dụ
: A = i>= MAX ? 1: 0;
printf ( max (a,b) = %d , (a>b) ? a:b);
lower = (c > = A && c< = Z) ? c - A + a :c;
I.5.8. Toán tử trê n bit (bit wise) :
Dạng Ký hiệ u
ý nghĩ a
NOT bit ~ lấ y bù 1
AND bit & giao
OR bit | hội
XOR bit ^ hội loạ i trừ
dịch trá i << nhâ n 2
dịch phả i >> chia 2
Kỹ thuật lập trì nh
25
Bả ng châ n trị:
Bit Bit Bit kế t quả
A B ~ A A & B A | B A ^ B
0 0 1 0 0 0
0 1 1 0 1 1
1 0 0 0 1 1
1 1 0 1 1 0
Ví dụ:
a= 4564 0001 0001 1101 0100
b= 13667 0011 0101 0110 0011
a & b 0001 0001 0100 0000
a | b 0011 0101 1111 0111
a ^ b 0010 0100 1011 0111
ý nghĩ a
:
1. Phép AND bit thường đ ược dùng để kiể m tra một bit cụ thể nà o đó trong
thà nh phầ n dữ liệ u x có trị 0 hay 1. Việ c nà y thực hiệ n bằ ng cách sử dụng một
mặ t nạ (mask) với bit cầ n quan tâ m bằ ng 1 còn cá c bit khá c bằ ng 0. Ta lấ y mask
AND với giá trị x. Nế u kế t quả thu đ ược bằ ng mask thì là bit cầ n quan tâ m là 1,
ngược lạ i là 0.
Ví dụ 1
:
void main()
{ unsigned x1; x2;
printf (\n cho 2 số hex(2 số) );
scanf (%x %x , &x1, &x2);
printf (% 02x & % 02x = % 02x\n, x1, x2, x1& x2);
}
Ví dụ 2
: Ta muốn biế t bit thứ 3 của số hexa ch là 1 hay 0 :
void main()
{ unsigned char ch, kq;
printf ( \n cho 1 số hex 2 số :);
scanf ( %x, &ch);
kq= ch & 0x08;
if (kq== 0x08) printf (bit 3 = 1);
else printf (bit 3 = 0);
}
Kỹ thuật lập trì nh
26
2. Phép OR dùng để bậ t cá c bit cầ n thiế t lê n cũng nhờ và o một mặ t nạ .
Chẳ ng hạ n như ta muốn bậ t bit thứ 7 của biế n ch (unsigned char ch) lê n 1:
ch = ch | 0x80;
Ví dụ 3
:
void main()
{ unsigned char x1,x2;
printf (\n cho 2 số hex (ff hay nhỏ hơn) :);
scanf (%x %x, &x1, &x2);
printf ( %02x | %02x %02x \n, x1, x2, x1| x2);
}
3. Phép XOR dùng để lậ t bit nghĩ a là hoá n chuyể n 0
1
Ví dụ 4
: Để lậ t bit 3 ta có chương trì nh:
void main()
{ unsigned char ch;
printf ( nhậ p 1 số hex < = ff :);
scanf (%x, &ch);
printf (%02x ^ 0x08 = %02x \n , ch, ch ^ 0x08);
}
4. Toá n tử << , >>
<< dịch sang trá i (nhâ n 2)
>> dịch sang phả i (chia 2)
Ví dụ 5
: num = 201 (0x00c9)
num :
0 0 0 0 0 0 0 0 1 1 0 0 1 0 0 1
num << 2 : 0 0 0 0 0 0 1 1 0 0 1 0 0 1 0 0
Kế t quả = 0x0324
804 nghĩ a là 201* 4
Ví dụ 6
:
void main()
{ unsigned char x1, x2 ;
printf ( nhậ p 1 số hex < = ff và số bit : );
scanf ( %x %d , &x1, &x2);
printf ( %02x >> %d = %02x \n, x1, x2, x1>> x2);
}
Chú ý
: Trong phép dịch phả i C là m theo 2 cá ch khá c nhau tùy thuộc và o
Kỹ thuật lập trì nh
27
kiể u dữ liệ u của toá n hạ ng bê n trá i.
- Nế u toá n hạ ng bê n trá i kiể u unsigned thì phép dịch sẽ điề n 0 và o các bit
bê n trá i.
- Nế u toá n hạ ng bê n trá i kiể u signed thì phép dịch sẽ điề n bit dấ u và o cá c
bit bê n trá i
Ví dụ 7
: unsigned int num;
num = 39470; // 9A2E hexa
num =
num >> 2
=
0
1 0 0 1
9867 = 0x268B
0 0 1 0
1 0 1 0
0 1 1 0
0 0 1 0
1 0 0 0
1 1 1 0
1 0 1 1
Ví dụ 8 : int num; // 9A2E hexa
num = -26066
num =
num >> 2
=
1
1 0 0 1
-6517 = 0xE68B
1 1 1 0
1 0 1 0
0 1 1 0
0 0 1 0
1 0 0 0
1 1 1 0
1 0 1 1
Ví dụ 8: Chương trì nh đổi số hex ra số nhị phâ n :
#include <stdio.h>
#include <conio.h>
void main()
{ int num;
unsigned int mask;
clrscr();
printf ("Chuong trinh doi so hexa sang nhi phan\n");
printf ("Nhap vao so hexa :");
scanf("%x",&num);
mask = 0x8000;
printf("\n Dang nhi phan cua so %x la ",num);
for (int j=1; j<=16; j++)
{ printf("%d",mask & num?1:0);
if (j==4 || j==8 || j==12) printf("-");
mask >>=1;
}
getch();
}
Kỹ thuật lập trì nh
28
Ví dụ 9: Chương trì nh má y tí nh bitwise
Đâ y l à c h ương trì nh giả lậ p một má y tí nh thực hiệ n cá c toá n tử bitwise.
#define TRUE 1
main()
{ char op[10];
int x1, x2;
while (TRUE)
{ printf (\n \n Cho biể u thức ( vd ffoo & f11) : );
printf (\n);
switch ( op[0])
{ case &:
pbin (x1); printf (& (and) \n );
pbin (x2);
pline (); pbin (x1 & x2);
break;
case |:
pbin (x1); printf (| \n );
pbin (x2);
pline (); pbin (x1 | x2);
break;
case ^:
pbin (x1); printf (^ \n);
pbin (x2);
pline (); pbin (x1 ^ x2);
break;
case >:
pbin (x1); printf ( >>); printf (%d \n ,x2);
pline (); pbin (x1 >> x2);
break;
case <:
pbin (x1); printf (<<); printf (%d \n, x2);
pline (); pbin (x1 << x2);
break;
case ~:
pbin (x1); printf (~ \n);
pline (); pbin (~ x1);
break;
default : printf (Toá n tử không hợp lệ /n );
}
}
Kỹ thuật lập trì nh
29
}
pbin (num)
int num;
{ unsigned int mask;
int j, bit;
mask = 0x8000;
printf (%04x, num);
for(j=0; j<16; j++)
{ bit = ( mask & num ) ? 1:0;
printf (%d, bit);
if (j= = 7) printf (- -);
mask >> = 1;
}
printf (- -);
mask >> 1;
}
pline ()
{ printf (- - - - - - - - \n);
}
* Sự chuyể n kiể u bắt buộc:
Trong C có 2 trường hợp chuyể n kiể u: chuyể n kiể u tự động và chuyể n
kiể u bắ t buộc.
Chuyể n kiể u bắ t buộc: đ ược á p dụng khi chuyể n kiể u tự động không được.
Cú pháp: (Type) biể u thức
Ví dụ: d = (float) (f - 32)
int a= 100, b=6;
double f;
f =a/b // kế t quả f=16
f= (double) a/ (double)b // kế t quả f= 100.0 / 6.0= 16.666.
* Mức độ ưu tiê n của các phép toán:
Độ ưu tiê n Phép toán Thứ tự kế t hợp
1
() [ ]
2 ! ~ ++ - - (type) * & size of
3 * / %
4 + -
5 << >>
Kỹ thuật lập trì nh
30
6 < <= > >=
7 = = !=
8 &
9 ^
10 |
11 &&
12 | |
13 ?
14 = + = - = ..
Ví dụ 1: 3/4 * 6 # 3*6 /4
0 * 6 18 /4
0 4
Ví dụ 2
: (float) 2 /4 # (float) (2/4)
2.0 /4 (float) 0
0.5 0.0
I.6. Chuỗi
I.6.1. Định nghĩ a :Chuỗi là một mả ng mà cá c phầ n tử của nó có kiể u ký tự.
Khai bá o một chuỗi ký tự chứa tối đa 49 ký tự
char chuỗi[50];
*
Lưu ý
: Tấ t cả cá c chuỗi đề u đ ược kế t thúc bằ ng ký tự NULL (\0). Do đó,
nế u chuỗi dà i 50 thì ta chỉ có thể chứa tối đa 49 ký tự.
I.6.2. Khởi động trị:
char chuỗi[ ] = {A, N, H, \0};
char chuỗi[ ] = "ANH";
I.6.3. Nhập / xuất chuỗi:
a. Nhập chuỗi:
gets (chuỗi)
b. Xuất chuỗi:
puts (chuỗi)
Chú ý
:
- Khi nhậ p chuỗi thì không đ ược dùng hà m scanf vì hà m scanf không chấ p
nhậ n khoả ng trắ ng.
Ví dụ
: scanf(%s, chuỗi);// ta nhậ p và o Nguyễ n Vă n ái thì
Kỹ thuật lập trì nh
31
// chuỗi = Nguyễ n vì hà m scanf cắ t khoả ng trắ ng
- Khi dùng hà m gets trong chương trì nh thì không nê n dùng hà m scanf ở
bấ t kì đâ u dù rằ ng dùng hà m scanf để nhậ p số mà ta nê n dùng hà m gets và hà m
atoi, atof để nhậ p số.
Vì :
scanf(%d, &n); // ta nhậ p số 5
gets (chuỗi); // lúc nà y chuỗi = (chuỗi rỗng)
I.6.4
.
Hàm chuyể n đổi số sang chuỗi và ngược lại
sốint = atoi (chuỗisố) // chuyể n chuỗi số sang số nguyê n
sốf = atof (chuỗisố) // chuyể n chuỗi số sang số thực
* Hai hà m nà y nằ m trong < stdlib .h >
I.6.5. Các hàm về chuỗi:
(# include < string. h> )
- int strlen(S) : trả về chiề u dà i chuỗi S.
- int strcmp(S1, S2): so sá nh chuỗi S1 với S2. Nế u chuỗi S1 giống S2 kế t
quả bằ ng 0. Nế u chuỗi S1< S2 kế t quả là â m, nế u chuỗi S1> S2 kế t quả > 0.
- int stricmp(S1, S2): so sá nh chuỗi S1, S2 không phâ n biệ t chữ thường
hay chữ hoa
- int strncmp(S1, S2, n): chỉ so sá nh n ký tự đầ u của 2 chuỗi S1, S2 với
nhau.
- int strnicmp(S1, S2, n): chỉ so sá nh n ký tự đầ u của 2 chuỗi S1, S2 với
nhau, không phâ n biệ t chữ thường, chữ hoa
- strcpy(dest, source): chép chuỗi từ nguồn source sang đí ch dest
Ví dụ
: char string[10];
char *str1 = "abcdefghi";
strcpy(string, str1);
printf("%s\n", string); // "abcdefghi"
- strncpy(dest, source, n): chép chuỗi từ nguồn sang đí ch với nhiề u nhấ t
là n ký tự.
Ví dụ
:
char string[10];
char *str1 = "abcdefghi";
strncpy(string, str1, 3); // string = "abcx1zwe12"
string[3] = '\0'; // Đặ t ký tự kế t thúc chuỗi và o cuối chuỗi.
printf("%s\n", string); // "abc"
- strcat(dest, src): nối chuỗi src và o sau chuỗi dest. Chiề u dà i của chuỗi
kế t quả bằ ng strlen(dest) + strlen(src)