Giáo trình Tin học đại cương - Phần III: Lập trình C

pdf 86 trang phuongnguyen 7490
Bạn đang xem 20 trang mẫu của tài liệu "Giáo trình Tin học đại cương - Phần III: Lập trình C", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên

Tài liệu đính kèm:

  • pdfgiao_trinh_tin_hoc_dai_cuong_phan_iii_lap_trinh_c.pdf

Nội dung text: Giáo trình Tin học đại cương - Phần III: Lập trình C

  1. Phn III. L p trình C Chng 1. Các thành phn c bn œ chng trình 1.1 Gii thi u Ngôn ng C ra Č i t nm 1972 bi Dennis Ritchie và Ken Thompson. Nm 1983, Vi)n chu+n hoá qu.c gia M0 (ANSI - American National Standards Institute) ti9n hành chu+n hoá. Nm 1989, T: ch;c chu+n hoá qu.c t9 (ISO - International Standards Organisation) ti9p túc chu+n hoá và Č9n nm 1990 thì vi)c chu+n hoá Č@Ac hoàn thành và Č@Ac gBi là —C chu+n“. MBi ngôn ng C tr@Ec Čó Č@Ac gBi là C K&R. C là mHt ngôn ng Č@Ac sI dJng rHng rãi nhLt hi)n nay. T —C chu+n“, các hãng phNn mOm phát triPn thành các ngôn ng C riêng nh@: Microsoft C, Quick C, Borland C, W@Ac sI dJng nhiOu là Turbo C (Borland C). Nm 1993, vEi sX phát triPn cYa công ngh) phNn mOm t —lZp trình cLu trúc“ sang —lZp trình h@Eng Č.i t@Ang“ thì C Č@Ac phát triPn thành C++. Giáo trình này trình bày ngôn ng lZp trình C và sI dJng Borland C. Borland C Čã qua nhiOu phiên b]n (version), giáo trình này ch^ trình bày ngôn ng C trong Borland C++ 3.1. 1.2 Các t p chính ca Borland C 3.1 (BC) Borland C g_m có các t)p tin chính sau: • BC.EXE: t)p kh] thi ČiOu khiPn toàn bH hoct ČHng trong môi tr@ ng tích hAp (IDE: Integrated Development Environment) , nghda là có ČNy ČY các ch;c nng socn th]o ch@eng trình, dfch ch@eng trình, gg r.i ch@eng trình, • Các t)p *.H (còn Č@Ac gBi là các t)p header - t)p tiêu ČO): ch;a các nguyên mku hàm, các kiPu, các bi9n, Các t)p này th@ ng nlm trong th@ mJc \BC\INCLUDE. • Các t)p *.LIB: là các t)p th@ vi)n, các t)p này Č@Ac gBi Č9n khi biên dfch và liên k9t ch@eng trình. • Các t)p *.OBJ: là các t)p Č.i t@Ang, Č@Ac dùng Č9n khi liên k9t ch@eng trình ČP tco ra các t)p *.EXE t@eng ;ng cYa ch@eng trình ngu_n. 1.3 Môi trng BC 1.3.1 Vào môi trng BC Có nhiPu cách khi ČHng Borland C. Trong phNn này, ch^ hcn ch9 giEi thi)u cách khi ČHng Borland C t : Čda c;ng. Vi)c khi ČHng môi tr@ ng Borland C Č@Ac thXc hi)n blng cách gBi chcy t)p BC.EXE. 44
  2. N9u t)p BC.EXE có Č@ ng dkn ČNy ČY C:\>BC\BIN\BC.EXE, cách gBi chung nhLt trong mBi tr@ ng hAp mà không ph]i chuyPn : Čda, th@ mJc hi)n hành blng cách gõ Č@ ng dkn Č9n t)p BC.EXE kP t th@ mJc g.c. Ví dJ, n9u Čang  : Čda C:\>_, ta gõ l)nh: C:\>\BC\BIN\BC.EXE Trong cách gõ Č@ ng dkn trên, \ chính là th@ mJc g.c. Sau khi khi ČHng môi tr@ ng Borland C, chúng ta su nhZn Č@Ac cYa s: nOn xanh cùng h) th.ng các menu ch;c nng phJc vJ vi)c socn th]o, biên dfch và chcy ch@eng trình. 1.3.2 Thoát khi BC Có hai cách ce b]n ČP thoát khwi BC, dùng Alt+X (Ln t: hAp phím Alt và phím X, Ln giu phím Alt tr@Ec, sau Čó Ln phím X, tLt nhiên không Ln dLu +), hoxc ta dùng t: hAp phím Alt+F, sau Čó dùng phím myi tên di Č9n mJc Quit và Ln Enter. 1.3.3 Cách g)i menu Các menu Č@Ac hiPn thf  hàng trên cùng cYa môi tr@ ng BC. Trong tên cYa các menu luôn t_n tci mHt kí tX có màu khác Čw, chúng ta dùng phím Alt+kí t+ có m-u Č ČP gBi nhanh menu Čó, hoxc dùng F10 ČP gBi Č9n Menu, sau Čó dùng các phím myi tên Č9 di chuyPn Č9n các menu t@eng ;ng. D@Ei Čây mô t] mHt s. menu chính. menu File: ch;a các mJc ch;c nng làm vi)c vEi t)p nh@ m t)p, l@u t)p, menu Edit: ch;a các mJc ch;c nng phJc vJ socn th]o ch@eng trình nh@ sao chép, xoá, dfch, menu Run: ch;a các mJc ch;c nng phJc vJ vi)c chcy ch@eng trình menu Compile: ch;a các mJc ch;c nng phJc vJ gg r.i, kiPm tra l|i. 1.4 So#n th$o ch%ng trình 1.4.1 Phím di chuy7n con tr Phím Chc nng ←↑↓→ Di chuyPn con trw sang trái, lên, xu.ng, sang ph]i Home W@a con trw vO ČNu dòng End W@a con trw vO cu.i dòng PgUp W@a con trw vO ČNu mHt trang màn hình PgDw W@a con trw vO cu.i mHt trang màn hình Ctrl + → Dfch con trw sang ph]i mHt ch Ctrl + ← Dfch con trw sang trái mHt ch 1.4.2 Phím ch8 hoa Các trình biên dfch C phân bi)t ch hoa và ch th@ ng. Vì th9 chúng ta cNn ph]i l@u ð cách gõ ch hoa và ch th@ ng. Có hai phím trA giúp cho vi)c gõ kð tX hoa và th@ ng: Capslock và Shift. 45
  3. Khi chúng ta nhLn phím Capslock, Čèn Capslock trên bàn phím su có hai trcng thái bZt hoxc tƒt, n9u Čèn Capslock bZt thì chúng ta có thP gõ kí tX hoa, n9u tƒt thì chúng ta gõ kí tX th@ ng. MHt cách khác ČP gõ kí tX hoa hoxc th@ ng là chúng ta nhLn Č_ng th i phím Shift và kí tX cNn gõ, n9u Čèn Capslock bZt thì chúng ta su nhZn Č@Ac kí tX th@ ng, n9u tƒt thì chúng ta nhZn Č@Ac kí tX hoa. 1.4.3 Phím chèn xóa Phím Chc nng Enter Xu.ng dòng Insert ChuyPn Č:i ch9 ČH chèn/Čè Delete Xóa kí tX ngay sau vf trí con trw Back space Xóa kí tX ngay tr@Ec vf trí con trw Ctrl + Y Xóa dòng kí tX ch;a con trw Ctrl + Q + Y Xóa các kí tX t vf trí con trw Č9n cu.i dòng 1.4.4 Phím v= kh>i Kh.i là mHt kh.i kí tX Č@Ac Čánh dLu vf trí ČNu blng vi)c Č@a con trw vO vf trí cNn Čánh dLu và nhLn Ctrl + K + B sau Čó dfch chuyPn con trw vO vf trí cNn Čánh dLu cu.i kh.i và nhLn Ctrl + K + K. Kh.i Č@Ac Čánh dLu su chuyPn màu, hoxc thay Č:i ČH sáng. MHt s. phím dùng thao tác vEi kh.i Č@Ac Čánh dLu: Phím Chc nng Ctrl + K + C Chép kh.i tEi vf trí mEi cYa con trw Ctrl + K + V ChuyPn kh.i tEi vf trí mEi cYa con trw Ctrl + K + Y Xóa c] kh.i Ctrl + K + W Ghi mHt kh.i vào mHt t)p trên Čda Ctrl + K + R WBc mHt kh.i t mHt t)p trên Čda Ctrl + Q + B Dfch chuyPn con trw vO ČNu kh.i Ctrl + Q + K Dfch chuyPn con trw vO cu.i kh.i 1.4.5 Phím tìm kiAm Phím Chc nng Ctrl + Q + F Tìm ki9m mHt cJm t Ctrl + Q + A Tìm ki9m mHt cJm t và sau Čó thay th9 blng mHt cJm t khác Ctrl + Q + L Lxp lci công vi)c Ctrl + Q + F hoxc Ctrl + Q + A cu.i cùng 1.5 Các khái ni m 1.5.1 TB khóa T khóa (keyword) là các t dành riêng cYa ngôn ng C. T khóa ph]i Č@Ac sI dJng Čúng cú pháp và không Č@Ac Čfnh nghda lci. D@Ei Čây là mHt s. t khóa thông dJng: auto break case char continue default 46
  4. do double else extern float for goto if int long register return short sizeof static struct switch typedef union unsigned void volatile while 1.5.2 Tên Tên (identifier) dùng ČP ČP Čfnh danh hay Čxt cho mHt thành phNn cYa ch@eng trình, nh@ tên bi9n, tên hlng, tên hàm, Tên là mHt dãy các kí tX g_m các ch cái [a-z, A-Z, 0-9] và gcch n.i —_“. Các l@u ð khi Čxt tên: • tên không ČuAc ch;a kí tX tr.ng, • tên không Č@Ac bƒt ČNu blng mHt ch s., • tên không Č@Ac trùng vEi t khóa. Ví dJ các tên hAp l): so_sanh, chuong_trinh, batdau. Ví dJ các tên không hAp l): trung binh, 1_bien, char, abc$ten. Nên Čxt các tên gAi nhE, có ð nghda. 1.5.3 Tên chuDn MHt s. tên chu+n Čã có s•n cYa trình biên dfch, có thP Čfnh nghda lci tuy nhiên không nên, nh@: sin, cos, tan, 1.5.4 HFng, biAn, bi7u thIc HFng là Čci l@Ang có giá trf không thay Č:i Č@Ac trong ch@eng trình. Ví dJ: 100 hlng là mHt s., ”a‘ hlng là mHt kí tX, —bai toan“ hlng là mHt chu:i kí tX. WP Čfnh nghda hlng, ta sI dJng t khóa (define. Ví dJ: #define PI 3.1415 BiAn là Čci l@Ang có thP thay Č:i Č@Ac giá trf trong ch@eng trình. Bi7u thIc là mHt công th;c tính toán ČP có mHt giá trf theo mHt qui tƒc toán hBc nào Čó. MHt biPu th;c bao g_m các toán tI và các toán hcng. Khi tính toán thì @u tiên cho các biPu th;c con trong ngoxc Čen. Ví dJ: (x + y) / z a > b 1.5.5 DJu ngKn cách câu lMnh DLu —;“ dùng ČP ngn cách các câu l)nh, nghda là m|i mHt câu l)nh ČOu ph]i k9t thúc bi mHt dLu —;“. 47
  5. 1.5.6 Cách chú thích Khi vi9t ch@eng trình nên sI dJng các l i chú thích ČP làm cho ch@eng trình d‘ hiPu. Trong ch@eng trình, các l i chú thích Č@Ac dxt gia hai dLu —/*“ và —*/“. Ví dJ: /* Day la ham so sanh 2 so */ 1.6 Ki,u d- li u chu.n KiPu d li)u là mHt tZp hAp các giá trf và mHt tZp hAp các phép toán thao tác trên các giá trf Čó. 1.6.1 Ki7u kí t+ - char MHt giá trf kiPu char chi9m mHt byte và biPu di‘n mHt kí tX trong b]ng mã ASCII. Ví dJ: Kí tX Mã ASCII ”0‘ 048 ”a‘ 065 ”A‘ 097 Có hai kiPu char: signed char và unsinged char. KiPu kí tX Kích th@Ec MiOn giá trf char (signed 1 byte -128 -> 127 char) unsigned char 1 byte 0 -> 255 Các hàm xI lí kí tX: KI“U GIÊ TR• NH–N H M TÊC D™NG W—˜C chuyPn c thành mã toascii(c) int ASCII chuyPn thành ch tolower(c) int th@ ng toupper(c) int chuyPn thành ch hoa 1.6.2 Ki7u s> nguyên KiPu s. nguyên Kích th@Ec MiOn giá trf int, short 2 byte -32768 -> 32767 unsigned int, unsigned 2 byte 0 -> 65535 sort long 4 byte -2147483648 -> 2147483647 unsigned long 4 byte 0 -> 4294967295 L@u ð: các kiPu kí tX cyng Č@Ac xem là mHt dcng cYa kiPu s. nguyên. Các s. trong h) 16 Č@Ac vi9t bi 10 ch s. và 6 ch cái sau: 0, 1, 9, A, B, C, D, E, F Cách viAt s> nguyên S hM 16: thêm kí tX 0x hoxc 0X vào tr@Ec s. nguyên  h) 16. Ví dJ: 0x41 (65) 48
  6. 0XF (15) Cách bi7u diTn s> nguyên S dUng s> hM 8: thêm kí tX 0 (s. 0) vào tr@Ec s. nguyên  h) 8. Ví dJ: 017 (15) 0101 (65) (Cách biPu di‘n s. nguyên  h) 16 và  h) 8 thuZn lAi cho cho vi)c lZp trình h) th.ng.) 1.6.3 Ki7u s> th+c KiPu s. thXc Kích th@Ec MiOn giá trf float 4 byte 3.4E-38 -> 3.4E+38 double 8 byte 1.7E-308 -> 1.7E+308 long double 10 byte 3.4E-4932 -> 1.1E+4932 Có 2 cách biPu di‘n s. thXc: • Dcng thZp phân: dùng dLu chLm ČP ngn cách phNn nguyên và phNn thZp phân. Ví dJ: -12.345672 1203.8375 • Dcng khoa hBc: g_m phNn Čfnh trf và phNn my cYa ce s. 10. Hai phNn cách nhau bi ch E hoxc e. Ví dJ: -6.123E+02 0.9827462E-03 1.6.4 Ép ki7u Khác vEi nhiOu ngôn ng lZp trình, C cho phép ta ép kiPu rõ ràng ČP Č@Ac k9t qu] mong mu.n. Cú pháp: (ki.u_m0i)bi.u_thc Ví dJ: int i; i = (int)2.5; /* i =2 */ int m = 1, n = 3; float x; x = (float)m/n; /* x = 1.0/3 = 0.3333 */ 1.7 Các phép toán 1.7.1 Các phép toán trên s> nguyên Các phép toán trên s. nguyên bao g_m: Phép toán Kí hi)u Ví dJ CHng + Tr - Nhân * 49
  7. Chia lLy phNn / 5 / 2 = 2 nguyên Chia lLy phNn d@ % 5 % 2 = 1 1.7.2 Các phép toán trên s> th+c Các phép toán trên s. thXc bao g_m: cHng (+), tr (-), nhân (*), chia (/). 1.7.3 Các phép toán quan hM MHt biPu th;c ch;a các toán hcng 22,32,4, =, So sánh lEn hen = So sánh lEn hen hoxc blng > Dfch ph]i (chia 2) Ví dJ: phép Č]o bit cYa s. nguyên 3 3 = 0000 0000 0000 0011 ~ 3 = 1111 1111 1111 1100 50
  8. Qui tƒc thXc hi)n phép AND tng bit là: 0 & 0 = 0 0 & 1 = 0 1 & 0 = 0 1 & 1 = 1 Ví dJ: 3 & 5 0000 0000 0000 0011 3 8 0000 0000 0000 0101 5 k9t qu]: 0000 0000 0000 0001 1 Qui tƒc thXc hi)n phép OR tng bit là: 0 | 0 = 0 0 | 1 = 1 1 | 0 = 1 1 | 1 = 1 Qui tƒc thXc hi)n phép XOR tng bit là: 0 ^ 0 = 0 0 ^ 1 = 1 1 ^ 0 = 1 1 ^ 1 = 0 Các phép dfch chuyPn: a > n = a/(2n) 1.8 C2u trúc ch%ng trình và các khai báo 1.8.1 Khái niMm hàm Hàm là mHt Čocn ch@eng trình Č@Ac vi9t ra mHt lNn song có thP sI dJng nhiOu lNn, m|i lNn sI dJng ch^ cNn gBi tên hàm và cung cLp các tham s. t@eng ;ng. Khai báo, Čfnh nghda và sI dJng hàm su Č@Ac trình bày cJ thP trong các phNn sau. 1.8.2 CJu trúc ch[ng trình MHt ch@eng trình C th@ ng có cLu trúc: #include /* G•i các t•p tiêu •• trong ch••ng trình */ #define /* Khai báo h•ng s• */ typedef /* ••nh ngh•a ki•u d• li•u */ /* Nguyên m•u các hàm: khai báo tên h•m và các tham s• */ /* Khai báo các bi•n toàn c•c */ 51
  9. main() { /* Khai báo bi•n */ /* Các câu l•nh */ } /* ••nh ngh•a các hàm */ Nh@ th9, trong mHt ch@eng trình C, có thP nhiOu phNn khác nhau: khai báo, Čfnh nghda, TLt c] các phNn này ČOu là tùy chBn (có thP có hoxc không), tr Čfnh nghda hàm main. Hàm main là hàm chính trong mHt ch@eng trình C, Čfnh nghda hàm main là bƒt buHc. Ví dJ: ch@eng trình Čen gi]n nhLt. main() { } Ch@eng trình này không làm gì c], nh@ng cyng không báo l|i, bi vì nó không ch;a mHt câu l)nh nào. 1.8.3 Các khai báo Trong cLu trúc chung cYa mHt ch@eng trình C, có nhiOu loci khai báo khác nhau, trong phNn này ch^ giEi thi)u mHt vài khai báo Čen gi]n, còn các khai báo kiPu và hàm su Č@Ac trình bày sau. 7include dùng ČP gBi các t)p tiêu ČO vào ch@eng trình, các t)p tiêu ČO này ch;a các hàm chu+n hoxc các hàm do ng@ i sI dJng Čfnh nghda. Ví dJ: gBi têp tiêu ČO stdio.h ČP sI dJng các hàm nhZp / xuLt chu+n. #define dùng ČP Čfnh nghda các hlng s. và các macro. Ví dJ: Čfnh nghda hlng s. MAX = 1000. #define MAX 1000 Khai báo bi:n Mu.n sI dJng mHt bi9n, bƒt buHc ph]i khai báo tr@Ec. Cú pháp: kiPu_d_li)u danh_sách _bi9n; Ví dJ: int a,b; /* khai báo 2 bi9n nguyên */ float so_thuc; /* khai báo bi9n kiPu s. thXc */ L@u ð, khi khai báo bi9n chúng ta chúng ta co thP khi tco giá trf cho nó nh@ sau: int a, b = 100; Khai báo h;ng Có hai cách ČP khai báo hlng, hoxc sI dJng #define hoxc sI dJng t khóa const nh@ sau: #define tên_hlng giá_trf_hlng 52
  10. const kiPu_d_li)u tên_hlng = giá_trf_hlng Ví dJ: #define PI 3.14 const float PI = 3.14 1.9 Quy t?c vi:t ch%ng trình • Các l)nh cùng nhóm nên Č@Ac nhóm th£ng cHt dBc. • Wxt tên cho các Čci l@Ang nên có tính ð nghda, gAi nhE. • Nên vi9t thêm các l i gi]i thích n9u cNn. 1.10 Phép gán MHt bi9n nhZn giá trf qua phép gán vEi dLu —=“. Ví dJ: a = 1; /* bi9n a nhZn giá trf 1 */ b = a + 1; /* bi9n b nhZn giá trf biPu th;c a + 1 t;c là giá tri 2 */ Cú pháp phép gán là: tên_bi9n = biPu_th;c; 5hép gán kép a = b = c = 1; /* gán giá trf 1 cho c] 3 bi9n a, b, c */ x = a + (y = 3); /* y nhZn giá trf 3, sau Čó x nhZn giá trf cYa biPu th;c a + y, nghda là 4 */ Các phép tKng 1, gi\m 1 W.i vEi phép tng hay gi]m giá trf 1, C vi9t gBn lai nh@ sau: i = i + 1; Č@Ac vi9t gBn thành i++; hoxc ++i; i = i œ 1; Č@Ac vi9t gBn thành i ; hoxc i; SX khác nhau gia ++i và i++ hoxc gia i và i là trong phép gán: tên_bi9n = biPu_th;c. N9u biPu th;c ch;a ++i ( i) thì i su Č@Ac tng (gi]m) tr@Ec khi gán, n9u biPu th;c ch;a i++ (i ) thì i su Č@Ac gán tr@Ec khi tng (gi]m). Ví dJ: x = 5; y = x++; /* gán x blng 5, gán y blng x (giá trf 5), sau Čó tng x lên 1 */ x = 5; y = ++x; /* gán x blng 5, tng x lên 1, sau Čó gán y blng x (giá trf 6) */ Xét phép gán sau: a = 3; b = a + a; 53
  11. Nh@ vZy, a ph]i Č@Ac thXc hi)n tr@Ec, sau Čó thXc hi)n b = 2 + 2 = 4. Câu l)nh này t@eng Č@eng vEi câu l)nh: a; b = a + a; 1.11 Cách ch#y ch%ng trình Sau khi socn ch@ng trình xong, là b@Ec d]ch (compile) ch@eng trình va socn th]o (gBi là ch@eng trình ngu_n) thành ch@eng trình có thP thXc hi)n Č@Ac (executable) œ blng cách nhLn phím 9:. Ti9p theo Čó là chUy ch@eng trình (run) ČP thI. Hai b@Ec này có thP Č@Ac thXc hi)n cùng nhau blng cách nhanh nhLt, gBn nhLt là nhLn Ctrl_F9 (nlm trong b]ng chBn l)nh Run), là l)nh thXc hi)n dfch và cho chcy ch@eng trình. Khi chcy, k9t qu] cYa ch@eng trình Č@Ac thP hi)n trong mHt màn hình gBi là User screen. Chúng ta nhLn Alt_F5 ČP chuyPn Č:i gia màn hình socn th]o sang màn hình k9t qu] ch@eng trình ČP theo dõi k9t qu]. N9u không  cu.i ch@eng trình chúng ta cNn Čxt l)nh getch(); ČP cho ch@eng trình dng lci, giúp ta xem k9t qu]. 1.12 MBt sD t p tiêu ČG chu.n Trong C có rLt nhiOu t)p tiêu ČO, Čây là nei ch;a các khai báo và Čfnh nghda cho các hàm Čã Č@Ac xây dXng s•n. Các hàm này Č@Ac gHp lci theo ch;c nng vào các t)p tiêu ČO khác nhau. Cách sI dJng các t)p này rLt Čen gi]n. Chúng ta Čã làm quen vEi mHt s. ch@eng trình ví dJ và các ch@ng trình này có sI dJng hai hàm vào ra ce b]n Čó là scanf và printf. Hai hàm này Č@Ac Čfnh nghda trong t)p stdio.h. Chính vì th9 nên trong ch@eng trình, ta sI dJng Č9n câu l)nh #include ČP ch^ dkn ch@eng trình Č9n các t)p này. MHt s. t)p tiêu ČO hay sI dJng: stdio.h t)p tiêu ČO ch;a các hàm vào ra chu+n math.h t)p tiêu ČO ch;a các hàm toán hBc conio.h t)p tiêu ČO ch;a các l)nh vào ra liên quan Č9n màn hình 54
  12. Chng 2. L?nh nh p / xuBt 2.1 L nh hi,n thI printf L)nh printf cho phép hiPn thf nHi dung ra màn hình. Ví dJ, mHt ch@eng trình Čen gi]n sI dJng l)nh printf. #include main() { printf(“Chao ban.\n”); } Cú pháp: printf(const char chu:i_ČiOu_khiPn [, danh_sách_các_tham_s.]); Ví dJ: printf(—Nghiem cua phuong trinh bac 2 la: x1 = %f, x2 = %f\n“, x1, x2); Trong Čó —%f “ là kí tX mã Čfnh dcng cho phép in ra giá trf cYa mHt s. thXc, —\n“ là kí tX ČiOu khiPn sang dòng mEi. Chu_i Či=u khi7n bao g`m 3 loUi kí t+: + Các kí tX ČiOu khiPn \n sang dòng mEi \f sang trang mEi \b xóa kí tX bên trái \t dLu tab + Các kí tX Čfnh dcng và khuôn in + Các kí tX ČP Č@a ra màn hình Các kí t+ Č]nh dUng Các kí tX Čfnh dcng theo sau kí tX —%“. D@Ei dây là mHt s. các kí tX Čfnh dcng th@ ng sI dJng: Kí tX Čfnh Ð nghda dcng c In ra mHt kí tX kiPu char d In ra s. nguyên kiPu int u In ra s. nguyên không dLu kiPu unsigned int ld In ra s. nguyên kiPu long lu In ra s. nguyên kiPu unsigned long 55
  13. f In ra s. thXc dcng m m.n n vEi phNn thZp phân có 6 ch s., áp dJng cho kiPu float, double s In ra xâu kí tX x In ra s. nguyên d@Ei dcng ce s. 16 (hexa) o In ra s. nguyên d@Ei dcng ce s. 8 e, E In ra s. thXc dcng khoa hBc m m.E[+ hoxc -]xx, áp dJng cho kiPu float, double g, G Dùng %e hoxc %f tùy thuHc loci nào ngƒn hen Ví dJ: In kí tX và s. nguyên %c và %d: printf(—%c va %c co ma ASCII tuong ung la %d va %d\n“, ”a‘, ”A‘, ”a‘, ”A‘); K9t qu] trên màn hình là: a và A co ma ASCII tuong ung la 97 va 65 L@u ð: kiPu kí tX char có thP Č@Ac nh@ kiPu s. nguyên tùy vào ČiOu ki)n cJ thP do biPu th;c, do qui cách vi9t ra. In s. nguyên d@Ei dcng biPu di‘n ce s. 16 và ce s. 8: printf(—S. %d có dcng ce s. 16 la %x hoxc %X và dcng ce s. 8 là %o\n“, 90, 90, 90); K9t qu] in ra màn hình là: S. 90 có dcng ce s. 16 la 5a hoxc 5A và dcng ce s. 8 là 132 In ra s. thXc: printf(—%f“, x); n9u x = 12.345 k9t qu] in ra là: 12.345000 vEi phNn thZp phân ngNm Čfnh là 6 ch s n9u x = 12.3456789 k9t qu] in ra là: 12.345679 vEi phNn thZp phân bf làm tròn In ra kí tX xóa trái và sang dòng mEi: printf(—Vi \ndu \nxoa\b\n trai\b\n“); cho k9t qu] là: Vi du xo tra Phuôn in Khái ni)m khuôn in là qui Čfnh cách th;c in ra d li)u và ch^ rw s. ch: d li)u su chi9m, canh lO trái hay lO ph]i. WP d‘ Č9m các kí tX, chúng ta su sI dJng kí tX ^ ČP ch^ ra vf trí tr.ng trong khuôn in. Khuôn in có dcng: %m và %m.n 56
  14. W.i vEi s. nguyên: mku ghi su là Emd trong Čó m là s. nguyên d@eng nlm ngay sau dLu % ch^ ra s. ch: t.i thiPu mà d li)u in ra su chi9m, d là kí tX Čfnh dcng ČP in ra s. nguyên. N9u s. in ra có s. ch s. ít hen m, thì máy su tX ČHng thêm vào các kí tX tr.ng. N9u s. in ra có s. ch s. ít hen m, thì máy tX ČHng thêm vào cho ČY ČP in ra h9t s W.i vEi kiPu s. thXc: mku ghi su là %m.nf trong Čó m t:ng s. ch s. vi9t ra, n s. ch s. sau dLu chLm (ngNm Čfnh s. ch s. thZp phân Č@Ac in ra là 6), f là kí tX Čfnh dcng in s. thXc. Ví dJ: printf(—%4d“, x); n9u x = 11 k9t qu] in ra ^^11 n9u x = 123456 k9t qu] in ra 123456 In các kí t+ Čbc biMt Cách vi9t Ð nghda \‘ In ra dLu ‘ \“ In ra dLu “ \\ In ra dLu \ 2.2 L nh nhJp d- li u scanf L)nh scanf cho phép nhZp d li)u vào t bàn phím. Ví dJ sI dJng l)nh scanf. #include main() { float r, dien_tich; printf(“Nh•p vào bán kính: ”); scanf(“%f”, &r); dien_tich = 3.14 * r * r; printf(“Di•n tích là: %f\n”, dien_tich); return; } L)nh scanf có cách sI dJng gNn gi.ng vEi l)nh printf tuy nhiên l)nh printf dùng ČP hi)n thf còn l)nh scanf thì dùng ČP nhZp d li)u vào. Cú pháp cYa l)nh scanf nh@ sau: scanf(const char chu:i_ČiOu_khiPn [, danh_sách_các_tham_s.]); Chu:i ČiOu khiPn cho phép Čfnh dcng d li)u nhZp vào. Còn danh sách các tham s. là Čfa ch^ các bi9n cNn nhZp. Trong C, ČP lLy Čfa ch^ cYa mHt bi9n thì ta dùng toán tI —&“. D@Ei Čây là li)t kê các kí tX Čfnh dcng cho scanf: Kí tX Čfnh Ð nghda dcng c NhZp vào mHt kí tX kiPu char d NhZp vào s. nguyên kiPu int u NhZp vào s. nguyên không dLu kiPu unsigned int 57
  15. ld NhZp vào s. nguyên kiPu long lu NhZp vào s. nguyên kiPu unsigned long f NhZp vào s. thXc dcng m m.n n vEi phNn thZp phân có 6 ch s., áp dJng cho kiPu float, double s NhZp vào xâu kí tX, không ch;a dLu cách (space) x NhZp vào s. nguyên d@Ei dcng ce s. 16 (hexa) o NhZp vào nguyên d@Ei dcng ce s. 8 Ví dJ: nhZp vào 2 s. nguyên và tính t:ng cYa nó. #include main() { int a, b, tong; printf(“Nh•p vào 2 s•: ”); scanf(“%d%d”, &a, &b); tong = a + b; printf(“T•ng c•a 2 s• là: %d\n”, tong); return; } 2.3 Dòng vào stdin và các hàm gets, getchar stdin là dòng vào chu+n (standard input). Các hàm scanf, gets, getchar ČOu nhZn d li)u t stdin. CNn phân bi)t hai tr@ ng hAp sau: • N9u trên stdin có ČY d li)u, thì các hàm trên su nhZn mHt phNn d li)u mà chúng yêu cNu. PhNn còn lci (ch@a Č@Ac nhZn) vkn còn  trên stdin. • Khi trên stdtin ch@a có ČY d li)u theo yêu cNu thì máy su tcm dng ČP ng@ i dùng nhZp thêm d li)u t bàn phím vào (cho Č9n khi bLm phím Enter). Hàm gets(str): nhZn mHt chu|i kí tX t bàn phím cho Č9n khi gxp kí tX ”\n‘ và tr] vO Čfa ch^ cYa chu|i nhZn Č@Ac. Chu|i str (str là bi9n con trw) nhZn Č@Ac su b: sung thêm kí tX k9t thúc ”\0‘. Cú pháp: char *gets(char*str); Hàm getchar(): nhZn mHt kí tX t bàn phím và tr] vO kí tX nhZn Č@Ac. Cú pháp: int getchar(void); Chú ð: Ví dJ: int ch; ch = getchar(); n9u ta gõ vào: a ↵ (enter) thì ch = a và kí tX \n vkn còn nlm lci stdin, và nó su làm trôi hàm getchar hoxc gets sau Čó. Còn n9u ta gõ 58
  16. ↵ thì ch = ”\n‘ và ”\n‘ bf loci khwi stdin - Hàm scanf cyng ČP lci stdin kí tX ”\n‘. Kí tX này su làm trôi hàm getchar hoxc gets sau Čó. WP các hàm này hoct ČHng Čúng thì ta ph]i khI kí tX ”\n‘ còn lci cYa hàm scanf blng cách thêm Čxc t] %*c vào cu.i chu|i ČiOu khiPn hoxc dùng hàm fflush(): Ví dJ : Thêm %*c vào cu.i chu|i ČiOu khiPn main() { char ht[25]; int t; pritnf("\Tuoi:"); scanf("%d%*c", &t); // khu '\n' trong dong vao printf(" Ho ten: ",); gets(ht); } - Làm scch stdin Ta có thP xoá scch stdin blng hàm fflush(): Cú pháp: fflush(stdin); Dùng hàm này su tránh Č@Ac mBi hZu qu] cYa các thao tác nhZp s. li)u tr@Ec Čó. F dG 2: main() { char ht[25]; int t; pritnf("\Tuoi:"); scanf("%d", &t); // khu '\n' trong dong vao printf(" Ho ten: ",); fflush(stdin); gets(ht); } 2.4 Các hàm xu2t kí tQ puts, putchar (stdio.h) Các hàm printf, puts và putchar ČOu có tác dJng Č@a d li)u lên dòng ra chu+n stdout (màn hình). a. Hàm puts Cú pháp: int puts(str) // str là bi9n con trw kiPu char. Tác dJng: Č@a chu|i str và Č@a thêm kí tX ”\n‘ lên stdout. Khi thành công, hàm tr] vO kí tX cu.i cùng Č@Ac xuLt (chính là ”\n‘ có mã ASCII là 10). Khi có l|i, hàm tr] vO EOF. Ví dG:puts(—\nABCD“); // printf(—\nABCD\n“); 59
  17. b. Hàm putchar Cú pháp: int putchar(int ch);// ch ch;a mã cYa kí tX cNn xuLt. Tác dJng: W@a kí tX ch lên stdout. Khi thành công, hàm tr] vO kí tX Č@Ac xuLt, khi có l|i, hàm tr] vO EOF. Ví dG:putchar(”A‘); su Č@a lên màn hình tci vf trí con trw kí tX A. 2.5 Các hàm nhJp/xu2t khác Trong mJc này, ta su xét các hàm getch, getche, putch, kbhit, clrscr, gotoxy (trong th@ vi)n conio.h) a. Hàm getch() Cú pháp: int getch(void); Tác dJng: nhZn mHt kí tX t bàn phím (console), không cho hiPn thf lên màn hình. Hàm tr] vO kí tX nhZn Č@Ac. b. Hàm getche() Cú pháp: int getche(void); Tác dJng: Gi.ng nh@ hàm getch, ch^ khác là cho hiPn thf kí tX nhZn Č@Ac lên màn hình. c. Hàm putch() Cú pháp: int putch( int ch); // ch ch;a mã kí tX hiPn thf Tác dJng: W@a kí tX ch lên cIa s: màn hình vn b]n. Kí tX su Č@Ac hiPn thf theo màu xác Čfnh bi hàm textcolor. Khác vEi hàm putchar là kí tX luôn Č@Ac hiPn thf vEi màu trƒng. Hàm tr] vO kí Č@Ac hiPn thf. d. Hàm kbhit() Cú pháp: int kbhit(void); Tác dJng: kiPm tra bH Č)m bàn phím (keystrokes), n9u bH Č)m r|ng su cho giá trf 0, và ng@Ac lci, n9u bH Č)m không r.ng, su cho giá trf khác 0. e. Hàm clrscr() Cú pháp: void clrscr(): Tác dJng: Xoá màn hình f. Hàm gotoxy() Cú pháp: void gotoxy(int x, int y) Tác dJng: di chuyPn con trw màn hình Č9n vf trí cHt x (180), và dòng y (125) 60
  18. Chng 3. L?nh ČiLu ki?n 3.1 L nh và khDi l nh 3.1.1 LMnh MHt tác vJ, mHt biPu th;c, mHt câu l)nh gán, Č@Ac k9t thúc bi dLu —;“ ČOu Č@Ac gBi là mHt câu l)nh. Ví dJ: int i, j = 20 ; clrscr( ) ; printf ("nhap 1 so :") ; scanf ("%d", &i) ; MHt cLu trúc ČiOu khiPn cyng Č@Ac xem là mHt l)nh, gBi là l)nh ČiOu khiPn. Có các loci l)nh ČiOu khiPn sau: • L)nh ru nhánh có ČiOu ki)n: if else, switch case. • L)nh ru nhánh không ČiOu ki)n: break, continue, goto. • L)nh lxp: for, while, do while. 3.1.2 Kh>i lMnh Kh.i l)nh là mHt dãy các l)nh (có thP là l)nh Čen hoxc l)nh có cLu trúc) và chúng nlm gia hai dLu móc nhBn —{— và —}“. Ta dùng kh.i l)nh khi ta mu.n mHt tZp các l)nh Č@Ac thXc hi)n ;ng vEi mHt ČiOu ki)n, mHt giá trf nào Čó. Trong ví dJ: if (n1 < n2) { min = n1; max = n2; } else { min = n2; max = n1; } Thì kh.i l)nh ch;a hai l)nh min = n1; và max = n2; Č@Ac thXc hi)n khi n1 < n2, ng@Ac lci thì kh.i l)nh sau Č@Ac thXc hi)n. Trong tr@ ng hAp này, kh.i l)nh g_m nhiOu l)nh Čen. Kh.i l)nh cyng có thP ch;a l)nh cLu trúc, ch£ng hcn nh@ câu l)nh if else 61
  19. 3.2 L nh if L)nh if là mHt câu l)nh ČiOu ki)n ce b]n nhLt, chúng ta có thP tìm thLy trong tLt c] các ngôn ng lZp trình. L)nh if cho phép lXa chBn vi)c thXc thi kh.i l)nh cYa mHt trong hai nhánh tu§ thuHc vào giá trf Čúng hay sai cYa biPu th;c ČiOu ki)n. Nó có hai dcng vi9t: dcng ČNy ČY l)nh if else và dcng ch^ l)nh if. Cú pháp if (ČiOu ki)n) (dUng 1) kh.I l)nh 1; else kh.i l)nh 2; hoxc if (ČiOu ki)n) (dUng 2) kh.i l)nh 1; Ð nghfa cga câu lMnh Dcng 1: n9u ČiOu ki)n là Čúng (có giá trf khác không), kh.i l)nh 1 su Č@Ac thXc hi)n; n9u ČiOu ki)n là sai (có giá trf blng không) thì kh.i l)nh 2 su Č@Ac thXc hi)n. Dcng 2: n9u ČiOu ki)n là Čúng (có giá trf khác không), kh.i l)nh 1 su Č@Ac thXc hi)n; n9u ČiOu ki)n là sai (có giá trf blng không) thì thXc hi)n câu l)nh Č;ng sau kh.i l)nh 1. S[ Č` kh>i bi7u diTn câu lMnh Sai Sai Wieu kien Wieu kien Wúng Wúng Khoi lenh 1 Khoi lenh 2 Khoi lenh 1 Dang 1 Dang 2 Ví di Ví dJ 1: Tính giá trf lEn nhLt cYa hai s. nguyên a và b. /* Chuong trinh tinh gia tri max cua hai so nguyen a va b */ #include main() { int a, b, max; 62
  20. printf(“Nhap vao hai so nguyen a va b.\n”); printf(“a = ”); scanf(“%d”, &a); printf(“b = ”); scanf(“%d”, &b); if (a > b) max = a; else max = b; printf(“max = %d\n”, max); } Ví dJ 2: KiPm tra mHt giá trf nhZp vào là blng không hay không. #include main() { int a; printf(“Nhap a vao:”); scanf(“%d”, &a); if (a == 0) printf(“Gia tri nhap vao la bang 0.\n”); printf(“Ket thuc chuong trinh\n”); } Chú ð: Č.i vEi l)nh so sánh sX blng nhau ph]i sI dJng toán tI —==“. N9u sI dJng toán tI —=“, máy su không báo l|i nh@ng cho k9t qu] không nh@ mong mu.n vì nó xem nh@ là phép gán. Ví dJ 3: Câu l)nh sau cho phép tính giá trf max và min cYa hai bi9n a và b. if (a > b) { max = a; min = b; } else { max = b; min = a; } MHt vài l@u ð khi sI dJng câu l)nh if • BiPu th;c ČiOu ki)n cNn ph]i Čxt trong dLu ngoxc. • BiPu th;c ČiOu ki)n là Čúng n9u nó có giá trf khác không, và là sai n9u nó cógiá trf blng không. • WiOu ki)n có thP là s. nguyên hoxc thXc. 63
  21. • Có thP sI dJng nhiOu ČiOu ki)n blng cách sI dJng các toán tI && và ||. Ví dJ, câu l)nh sau kiPm tra n9u c] hai ČiOu ki)n ČOu Čúng: if ((ČiOu ki)n 1) && (ČiOu ki)n 2)) Nh@ th9, vi)c k9t hAp các toán tI —&&“ và —||“ su cho phép chúng ta xây dXng nhng biPu th;c ČiOu ki)n ph;c tcp hen. Ví dJ: vi9t câu l)nh kiPm tra ba s. thXc a, b, và c là ba ccnh cYa tam giác. if ((a > 0) && (b >0) && (c >0) && (a main() { float a, b, x; printf(“Nhap vao a va b:”); scanf(“%f%f”, &a, &b); if (a == 0){ if (b == 0) printf(“Phuong trinh co vo so nghiem\n”); else printf(“Phuong trinh vo nghiem\n”); } else{ x = -b/a; printf(“Phuong trinh co nghiem x = %f\n”, x); } } Chú ð rlng, n9u sI dJng các l)nh if l_ng nhau, t.t nhLt chúng ta nên sI dJng các dLu Čóng mE ngoxc —{}“ ČP tránh gây ra sX hiPu nhNm if nào t@eng ;ng vEi else nào. Khi không sI dJng các dLu Čóng mE ngoxc —{}“ thì: n9u s. t khoá if blng s. t khoá else ta d‘ dàng xác Čfnh Č@Ac tng cxp if và else t@eng ;ng; tuy nhiên n9u s. t khoá else ít hen s. t khoá if, thì else su Č@Ac gƒn vEi if không có else gNn nhLt tr@Ec Čó. Ch£ng hcn, Čocn ch@eng trình: if (a != 0) if (a > b) y = b/a; 64
  22. else y = -b/a; thì else su Či vEi if bên d@Ei. WP tránh nhNm lkn, ta nên sI dJng dLu Čóng mE ngoxc —{}“, khi Čó Čocn ch@eng trên Č@Ac vi9t lci nh@ sau: if (a != 0) { if (a > b) y = b/a; else y = -b/a; } hj ding else if Khi mu.n sI dJng mHt trong n quy9t Čfnh, ta có thP sI dJng l)nh if d@Ei dcng sau: if (ČiOu ki)n 1) kh.i l)nh 1; else if (ČiOu ki)n 2) khNi l?nh 2; else if (biPu th;c n-1) khNi l?nh n-1; else kh.i l)nh n; W.i vEi câu l)nh này thì: • Ch^ mHt trong n kh.i l)nh trên Č@Ac thXc hi)n; • N9u ČiOu ki)n th; i là ČiOu ki)n ČNu tiên Čúng (t;c là có giá trf khác 0), thì kh.i l)nh i su Č@Ac thXc hi)n; • N9u c] n-1 ČiOu ki)n ČNu tiên ČOu sai (có giá trf blng 0), thì kh.i l)nh n su Č@Ac thXc hi)n. Ví dJ: Ch@eng trình x9p loci k9t qu] hBc tZp cYa mHt sinh viên. #include main() { float diem; printf(—Nhap diem vao“); scanf(“%f”, &diem); if (diem < 5) printf(“Xep loai: kem”); else if (diem < 7) 65
  23. printf(“Xep loai: trung binh”); else if (diem b) ? max = a : max = b; Chú ð rlng, khi thXc thi, cLu trúc —?:“ su tr] vO giá trf k9t qu] cYa câu l)nh Č@Ac thXc thi. Nh@ th9, ví dJ trên có thP Č@Ac vi9t lci nh@ sau: max = (a > b) ? a : b; và cách vi9t này thì th@ ng Č@Ac sI dJng hen. 3.4 L nh switch case L)nh if nói trên ch^ thI ČiOu ki)n ČP chBn mHt trong hai ph@eng án. NhiOu lúc chúng ta ph]i chBn mHt trong nhiOu ph@eng án khác nhau. C cung cLp câu l)nh switch h| trA công vi)c này. Cú pháp switch (biPu th;c nguyên) { case n1: Các câu l)nh case n2: Các câu l)nh case nk: Các câu l)nh [default: 66
  24. Các câu l)nh] } Trong Čó, ni ph]i là các s. nguyên, hlng kí tX. Các ni cNn có giá trf khác nhau. Pefault là thành phNn không bƒt buHc. e nghfa cga câu lMnh Câu l)nh hoct ČHng phJ thuHc vào giá trf cYa biPu th;c vi9t trong các dLu ngoxc tròn. Khi giá trf này blng ni thì máy su nh]y Č9n th;c hi)n các câu l)nh có nhãn case ni. Khi giá trf biPu th;c khác tLt c] các ni thì n9u có phNn default thì máy su nh]y Č9n th@c hi)n các l)nh cYa nhãn này, n9u không thì máy su thoát ra khwi câu l)nh switch và thXc hi)n các l)nh k9 ti9p cYa ch@eng trình. Máy su ra khwi toán tI switch khi nó gxp câu l)nh break, return hoxc nó gxp dLu —}“ cYa câu l)nh switch. Chú ð rlng mHt khi máy nh]y tEi mHt nhãn ni nào Čó thì n9u k9t thúc cYa dãy l)nh t@eng ;ng vEi nhãn này không có l)nh break thì nó su ti9p tJc thXc hi)n các câu l)nh nhãn ni+1 cho Č9n khi gxp l)nh break hoxc return. Nh@ th9 n9u m|i dãy các câu l)nh t@eng ;ng vEi các nhãn k9t thúc bi câu l)nh break thì ch^ mHt trong các dãy l)nh này Č@Ac th@c hi)n. Ví dJ: #include main() { int n; printf(" Nh•p vào m•t s• nguyên t• 0 ••n 2: "); scanf("%d", &n); switch(n) { case 0: printf("S• không\n"); break; case 1: printf("S• m•t\n"); break; case 2: printf("S• hai\n"); break; default: printf(“Không •úng\n”); } printf(“K•t thúc\n”); } N9u n=0 máy su in ra: S. không. K9t thúc. N9u n=1 máy su in ra: 67
  25. S. mHt. K9t thúc. N9u n=2 máy su in ra: S. hai. K9t thúc. N9u n=4 máy su in ra: Không Čúng. K9t thúc. WP thLy rõ tác dJng l)nh break, ta hãy sIa Č:i sang ví dJ trên. Ví dJ: thi9u l)nh break #include main() { int n; printf(" Nh•p vào m•t s• nguyên t• 0 ••n 1: "); scanf("%d", &n); switch(n) { case 0: printf("S• không\n"); case 1: printf("S• m•t\n"); case 2: printf("S• hai\n"); } printf(“K•t thúc\n”); } N9u n=0 máy su in ra: S. không. S. mHt. S. hai. K9t thúc. N9u n=1 máy su in ra: S. mHt. S. hai. K9t thúc. N9u n=2 máy su in ra: S. hai. K9t thúc. 68
  26. Chng 4. L?nh vòng lTp 4.1 Vòng lZp for Trong khi lZp trình, ta gxp tr@ ng hAp mHt s. câu l)nh lxp Či lxp lci vEi s. lNn lxp hu hcn. N9u vi9t lxp Či lxp lci các câu l)nh này thì ch@eng trình su rLt dài. CJ thP, gi] sI ta mu.n in các s. t 1 Č9n 24 lên màn hình, m|i s. trên mHt dòng màn hình. Trong tr@ ng hAp này, ta có thP vi9t 24 câu l)nh printf ČP hiPn thf 24 giá trf này (hoxc 1 câu l)nh), nh@ng rõ ràng cách làm này hoàn toàn không khoa hBc tí nào! Xem cách vi9t mHt câu l)nh: printf("%d\n%d\n %d\n%d\n ", 1, 2, 3, 4, 5, ,24 ); WP gi]i quy9t cho vLn ČO này, C cung cLp câu l)nh for cho phép ta lZp trình thXc hi)n lxp Či lxp lci mHt s. câu l)nh, cú pháp nh@ sau: for ( [biPu th;c 1]; [biPu th;c 2]; [biPu th;c 3]) kh.i l)nh; /* thân for */ • Các phNn ČP trong ngoxc vuông là tu§ ð, có cyng Č@Ac mà không cyng Č@Ac. • Các dLu chLm ph+y và dLu ngoxc Čen là bƒt buHc ph]i có. DLu chLm ph+y ph]i có ngay c] khi không có biPu th;c. e nghfa câu lMnh L)nh for hoct ČHng nh@ sau: 1. Tính biPu th;c 1. 2. Tính biPu th;c 2. N9u biPu th;c 2 có giá trf 0 (sai), máy su ra khwi for và chuyPn tEi câu l)nh sau thân for. N9u biPu th;c 2 có giá trf khác 0 (Čúng), máy thXc hi)n các câu l)nh trong thân for, sau Čó chuyPn tEi b@Ec 3. 3. Tính biPu th;c 3, sau Čó quay tr lci b@Ec 2 ČP bƒt ČNu các b@Ec lxp mEi. Ta hãy xem l)nh for vi9t cho ví dJ nêu trên. #include main() { int i; for (i=1; i <=24; i++) printf("%d\n", i); getch(); } Ti9n trình thXc hi)n ch@eng trình này nh@ sau: a. WNu tiên i nhZn giá trf blng 1, b. Sau Čó kiPm tra xem i có nhw hen hoxc blng 24 thì Či thXc hi)n l)nh printf. N9u không (t;c v@At quá 24) thì thoát ra khwi l)nh for, t;c nh+y tEi mJc e. 70
  27. c. Ti9p theo tng giá trf i lên 1 d. Quay lci chu trình t b. e. K9t thúc. Cùng ví dJ trên ta có thP vi9t: i=1; for ( ; i main() { int n, dem; float x, tbc, tong=0; /* Kh•i t•o và ••c n */ printf(" Bao nhiêu s• c•n ••c vào n = "); scanf("%d", &n); /* ••c các s• */ for (dem=1; dem <= n; ++dem) { printf(" x%d = ",dem); /* in ra x1, x2, x3 */ scanf("%f", &x); tong += x; /* C•ng tích lu• */ } /* Tính Trung bình c•ng */ tbc = tong/n; printf("\n Trung binh cong = %f", tbc); } Nhkn xét 1. BiPu th;c 1 bao gi cyng ch^ Č@Ac tính mHt lNn. 2. BiPu th;c 2, biPu th;c 3 và thân for có thP Č@Ac thXc hi)n lxp Či lxp lci nhiOu lNn. 71
  28. Lu ð • Khi biPu th;c 2 vƒng mxt thì nó luôn Č@Ac xem là Čúng. Trong tr@ ng hAp này ČP ra khwi vòng lxp thì cNn ph]i sI dJng mHt trong các câu l)nh break hoxc return. Ví dJ: for(; ;) {} /* Câu l)nh lxp không dng*/ • Ta có thP sI dJng các l)nh for l_ng nhau. Bài tkp: 1. Tính t:ng: 1 + 22 + 32 + + n2. 2. In ra các s. trên màn hình t 0 Čên 99 trên 10 dòng. 3. In ra n lNn các s. t 1 Č9n m. 4.2 Vòng lZp while Cú pháp: while (biPu th;c) kh.i l)nh; Ð nghfa cga câu lMnh: Trong khi bi7u thIc có giá trf Čúng, t;c khác 0, thì còn phi thXc hi)n kh.i l)nh. Thông th@ ng kh.i l)nh là mHt dãy các câu l)nh, trong Čó có câu l)nh thay Č:i giá trf cYa bi7u thIc ČP thoát vòng lxp. Tuy nhiên, kh.i l)nh cyng có thP ch^ là mHt l)nh Čen. Vòng lxp while là vòng lxp kiPm tra biPu th;c tr@Ec khi thXc hi)n kh.i l)nh, do Čó n9u biPu th;c có giá trf sai (blng 0) thì là vòng lxp r|ng. S[ Č` kh>i bi7u diTn vòng lbp while Begin Bieu thuc Sai, =0 Wúng , !=0 Khoi lenh End Ví dJ 1: Tính t:ng 1 + 2 + 3 + + n. #include main() { int n, i, s; printf(" n = "); 72
  29. scanf("%d", &n); i = 1; s = 0; while (i main() { float e_mu, epsilon, x, t; int n; printf(" x = "); scanf("%f", &x); printf(" 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); } L@u ð: • BiPu th;c luôn Č@Ac Čxt trong dLu ngoxc Čen (). • BiPu th;c su Č@Ac tính toán ČNu tiên nên cNn ph]i có giá trf xác Čfnh. Bài tZp: • Vi9t lci các bài tZp cho vòng lxp for sI dJng while. 73
  30. • ChuyPn vòng lxp for thành vòng lxp while. • Vi9t ch@eng trình tính sin(x) triPn khai theo chu|i sau: sin(x) = x/1! œ x3/3! + + (-1)n.x2n+1/(2n+1)! s. phNn tI Č@Ac chBn cho tEi khi Čct ČH chính xác: |x2n+1/(2n+1)!| i bi7u diTn vòng lbp do while Begin Khoi lenh Wúng, Bieu thuc =0 Sai , !=0 End Ví dJ: hãy ČBc mHt s. cho Č9n khi s. Čó là s. d@eng. #include main() { int n; do { printf(" Hãy cho m•t s• > 0 :"); scanf("%d", &n); printf(" B•n •ã ••c m•t s• %d\n", n); }while (n<=0); printf(" •úng s• d••ng r•i."); 74
  31. } Thí dJ trên có nghda là: Hãy thXc hi)n l)nh do { } trong khi (while) biPu th;c (n main() { int i; for (i=1; i <=5; i++) 75
  32. { printf("B•t ••u vòng %d\n", i); printf("Chào b•n\n"); if (i==3) break; printf("K•t thúc vòng %d\n", i); } printf("H•t vòng l•p."); } K9t qu] cYa ch@eng trình trên nh@ sau: B•t ••u vòng 1 Chào b•n K•t thúc vòng 1 B•t ••u vòng 2 Chào b•n K•t thúc vòng 2 B•t ••u vòng 3 Chào b•n H•t vòng l•p. Bài tZp: Hãy vu se Č_ kh.i mô t] ch@eng trình trên. 4.4.2 LMnh continue Trái vEi l)nh break, l)nh continue dùng ČP quay lci t ČNu ČP thXc vòng lxp mEi mà không cNn thXc hi)n phNn còn lci. Ví dJ vEi vòng lxp for: #include main() { int i; for (i=1; i <= 5; i++) {printf(" B•t ••u %d\n", i); if (i<4) continue; printf(" Chào b•n\n"); } } Ch@eng trình su cho k9t qu] nh@ sau: B•t ••u 1 B•t ••u 2 B•t ••u 3 B•t ••u 4 Chào b•n B•t ••u 5 Chào b•n Nghda là chng nào i < 4 thì l)nh continue su chuyPn sang làm vòng lxp ti9p theo, không cNn thXc hi)n phNn còn lci cYa vòng for. 76
  33. Bài tZp: Hãy vu se Č_ kh.i mô t] ch@eng trình trên. Ví dJ: nhZp vào s. nguyên d@eng và tính bình ph@eng cYa nó. #include main() { int n; do {printf(" Hãy cho m•t s• > 0 :"); scanf("%d", &n); if (n 0\n"); continue; } printf(" Bình ph••ng c•a nó là : %d\n", n*n); } while(n); } VEi k9t qu] hi)n lên màn hình là: Hãy cho m•t s• > 0 : 4 Bình ph••ng c•a nó là : 16 Hãy cho m•t s• > 0 : -5 Xin m•i cho s• > 0 Hãy cho m•t s• > 0 : 2 Bình ph••ng c•a nó là : 4 Hãy cho m•t s• > 0 : 0 Bình ph••ng c•a nó là : 0 Trong tr@ ng hAp các vòng l_ng nhau, l)nh continue su liên quan Č9n vòng bên trong nhLt. Bài tZp: Hãy cho bi9t Čocn ch@eng trình sau làm gì ? for (i = 1; i <= 4; i++) for (j = 1; i <= 10; j++){ printf(“%d”, j); if (j != 10) continue; printf(“\n”); } 77
  34. Chng 5. Hàm MHt ch@eng trình vi9t blng ngôn ng C là mHt dãy các hàm, trong Čó có mHt hàm chính (hàm main). Hàm main chúng ta Čã gxp trong phNn tr@Ec khi nói vO cLu trúc cYa mHt ch@eng trình C.Th; tX cYa các hàm trong ch@eng trình là bLt kì, nh@ng ch@eng trình bao gi cyng thXc hi)n t hàm main. Tr@Ec khi Či vào trình bày các chi ti9t vO hàm, chúng ta xem xét mHt ví dJ sI dJng hàm. Bài toán Čxt ra là rLt Čen gi]n: xây dXng hàm tìm giá trf lEn nhLt cYa hai s #include float max2so(float a, float b); /* Nguyên m•u c•a hàm */ main() /* b•t ••u hàm chính */ { float x, y; printf(“Nh•p vào 2 s•: ”); scanf(“%f%f”, &x, &y); printf(“Giá tr• l•n nh•t c•a %f và %f là ”, x, y, max2so(x, y)); } /* k•t thúc hàm main */ /* ••nh ngh•a hàm max2so */ float max2so(float a, float b) { float max; /* khai báo bi•n c•c b• */ max = a > b ? a : b; return max; } Liên quan Č9n hàm bao gi cyng có các khái ni)m sau: • Tên hàm • KiPu giá trf tr] vO cYa hàm • W.i hay tham s. hình th;c • Thân hàm • Khai báo hàm (nguyên mku hàm) • L i gBi hàm • Tham s. thXc W.i vEi mHt hàm bao gi cyng có 2 giai Čocn khác nhau là: xây dXng hàm và sI dJng hàm. 5.1 [Inh ngh\a hàm Có 2 vf trí khác nhau so vEi hàm main ČP Čfnh nghda hàm: 78
  35. • Wfnh nghda hàm sau hàm main, • Wfnh nghda hàm tr@Ec hàm main. Cú pháp chung ČP Čfnh nghda mHt hàm là nh@ sau: kiPu_d_li)u_tr]_vO_cYa_hàm tên_hàm ([khai_báo_các_tham_s.]) { các khai báo dùng riêng bên trong hàm n9u có; các l)nh bên trong hàm; [return giá_trf_tr]_vO;] } Trong khai báo trên: • KiPu d li)u tr] vO cYa hàm, kiPu d li)u cYa tham s. có thP là các kiPu d li)u ce b]n hoxc các kiPu d li)u do ng@ i dùng Čfnh nghda. • Tên hàm và tên tham s. Č@Ac Čxt tên theo Čúng qui tƒc Čxt tên áp dJng cho tên bi9n. • Câu l)nh return là tùy chBn, có thP có hoxc không. N9u hàm không tr] vO giá trf, thì câu l)nh return là không bƒt buHc. • N9u hàm không tr] vO giá trf, thì kiPu d li)u tr] vO cYa hàm Č@Ac khai báo vEi t khóa void. • N9u hàm không có các tham s. hình th;c, ta có thP sI blng t khóa void ČP ch^ ra hàm không có tham s. hình th;c, hoxc không khai báo gì c]. Ví dJ: vi9t hàm tính f(x) = x2 + bx +c float ham_f(float x, int b, int c) { float gia_tri; /* Khai báo bi•n c•c b• */ gia_tri = x * x + b * x + c; return gia_tri; } Wfnh nghda trên cYa hàm có thP Čxt tr@Ec hoxc sau hàm main. Tuy nhiên, trong tr@ ng hAp Čxt sau hàm main thì ph]i có thêm phNn khai báo nguyên mku hàm Čxt tr@Ec hàm main (th@ ng là ČNu ch@eng trình) nh@ sau: kiPu_d_li)u_tr]_vO_cYa_hàm tên_hàm ([khai_báo_các_tham_s.]); Nh@ vZy trong tr@ ng hAp này, ta thLy khai báo hàm (gBi là nguyên mku hàm) Č@Ac Čxt tr@Ec hàm main (ch^ khác là có thêm dLu chLm ph+y) và cú pháp khai báo hàm lci lxp lci trong phNn Čfnh nghda hàm (sau hàm main). Hai vf trí Čxt Čfnh nghda hàm là t@eng Č@eng nhau. Tuy nhiên, vEi cách khai báo và Čfnh nghda tr@Ec hàm main thì chúng ta d‘ hình dung hen. Cách khai báo nguyên mku hàm và Čfnh nghda hàm tách r i sau hàm main thì có @u ČiPm trong tr@ ng hAp ch@eng trình nhiOu hàm, t: ch;c su rw ràng hen. Ví dJ: hàm không tr] vO giá trf (t@eng Č@eng vEi khái ni)m thY tJc trong Pascal) void bao_ket_qua(int kq) { 79
  36. printf(“K•t qu• là: %d \n”, kq); [return;] } Trong tr@ ng hAp này, kiPu tr] vO là R id và câu l)nh return có thP có hoxc không, không bƒt buHc. Lu ð: • KiPu cYa giá trf d li)u tr] vO (bi câu l)nh return) ph]i phù hAp vEi kiPu d li)u tr] vO cYa hàm Čã khai báo, • Không cho phép xây dXng mHt hàm bên trong hàm khác, • M|i hàm có các bi9n riêng cYa nó, t;c là khai báo bên trong hàm Čó và ch^ Č@Ac sI dJng bên trong hàm Čó (gBi là bi9n cJc bH). 5.2 Li g]i hàm Hàm Č@Ac sI dJng thông qua l i gBi hàm. Cách vi9t mHt l i gBi hàm là nh@ sau: tên_hàm ([danh sách các tham s. thXc]); Chúng ta cNn phân bi)t: tham s. xuLt hi)n trong phNn khai báo Č@Ac gBi là tham s. hình th;c, tham s. xuLt hi)n trong phNn gBi hàm Č@Ac gBi là tham s. thXc. CNn l@u ð  Čây: • S. tham s. thXc ph]i blng s. tham s. hình th;c, • KiPu cYa tham s. thXc ph]i phù hAp vEi kiPu cYa tham s. hình th;c. Ví dJ: vi9t hàm tính giai tha n! = 1.2 n. #include long int giai_thua(int n); /* nguyên m•u hàm */ main() { int n; long gt; /* ••c s• n */ printf("\nn = "); scanf("%d", &n); /* g•i hàm tính giai th•a */ gt = giai_thua(n); /* In ra giai th•a */ printf("\n n! = %ld\n", gt); } long giai_thua(int n) 80
  37. { int i; long gt = 1; if (n > 1) /* N•u không có câu l•nh này ???*/ for (i=2; i int i; /* Bi•n toàn c•c */ void vi_du(void); main() { for (i=1; i <=5; i++) vi_du(); } void vi_du(void) { int m = 3; /* Bi•n c•c b• */ m++; printf(" %d %d\n", i, m); } Trong ví dJ trên, có bi9n i là bi9n toàn cJc vì nó Č@Ac khai báo bên ngoài các hàm, bên ngoài c] hàm chính main. Còn bi9n m là bi9n cJc bH, vì nó Č@Ac khai báo trong hàm vi_du, nh@ th9 bi9n m ch^ Č@Ac sI dJng  bên trong hàm vi_du. Ngoài ra, chúng ta nhZn thLy rlng hàm vi_du sI dJng giá trf cYa bi9n i mà không thay Č:i gì nó. Tuy nhiên chúng ta hoàn toàn có thP thay Č:i giá trf cYa i trong hàm vi_du. Ch£ng hcn: printf(" %d %d\n", i++, m); 81
  38. Tuy nhiên, ČiOu này cho thLy vi)c thay Č:i tùy ti)n giá trf cYa bi9n toàn cJc su làm mLt Či tính kiPm soát, nhLt là trong các ch@eng trình lEn. Vì vZy, viMc sj ding biAn toàn cic là nên hUn chA. 5.3.2 PhUm vi hoUt Čpng cga biAn Phcm vi hoct ČHng cYa bi9n toàn cJc kP t vf trí nó Č@Ac khai báo cho Č9n cu.i t)p ch@eng trình. Phcm vi hoct ČHng cYa bi9n cJc bH là ch^ trong hàm mà bi9n Čó Č@Ac khai báo. Vì vZy trong ví dJ sau: main() { } int a; float b; ham1( ) { int x; } ham2( ) { int y; } thì các bi9n a và b có tác dJng Č.i vEi hai hàm ham1 và ham2 song không có tác dJng Č.i vEi hàm chính main, còn bi9n x thì ch^ có tác dJng Č@Ac trong hàm ham1 và còn bi9n y thì ch^ có tác dJng Č@Ac trong hàm ham2. VO nguyên tƒc, ng@ i ta có thP khai báo các bi9n toàn cJc  nhiOu ch| song vì tính sáng sYa, d‘ nhìn, d‘ tìm ki9m cYa ch@eng trình, nên khai báo tLt c] các bi9n toàn cJc n9u có sI dJng  ngay ČNu ch@eng trình. W.i vEi các bi9n cJc bH Č@Ac khai báo trong mHt hàm thì chúng không có sX liên h) nào vEi các bi9n cJc bH Č@Ac khai báo trong hàm khác và vEi bLt k§ bi9n toàn cJc nào có cùng tên và cùng kiPu. Ví dJ sau ch^ rw ČiOu này: #include int a = 5; /* Bi•n toàn c•c */ void ham_vi_du() { int cuc_bo = 1; /* Bi•n c•c b• */ int a = 10; /* Bi•n c•c b• */ printf(“Bi•n c•c b• trong hàm ví d•:\n cuc_bo = %d\n a = %d\n”, cuc_bo, a); } 82
  39. main() { int cuc_bo = 100; /* Bi•n c•c b• */ ham_vi_du(); /* G•i hàm ví d• */ printf(“Bi•n c•c b• trong hàm main:\n cuc_bo = %d\n”, cuc_bo); printf(“Bi•n toàn c•c:\n a = %d\n”, a); } Ch@eng trình này su cho k9t qu] nh@ sau: Bi•n c•c b• trong hàm ví d•: cuc_bo = 1 a = 10 Bi•n c•c b• trong hàm main: cuc_bo = 100 Bi•n toàn c•c: a = 5 Nh@ th9, chúng ta nhZn thLy trong hàm ham_vi_du bi9n cuc_bo không liên quan gì Č9n bi9n cuc_bo trong hàm main, và bi9n a cyng không liên quan gì Č9n bi9n toàn cJc a. Bi9n cJc bH Č@Ac chia làm hai loci: bi9n cJc bH tX ČHng và bi9n cJc bH tdnh. 5.3.3 BiAn cic bp t+ Čpng Cách cLp phát bH nhE cho các bi9n cJc bH cYa hàm Č@Ac gBi là cLp phát tX ČHng, cNn Č9n Čâu cLp phát Č9n Čó, m|i lNn gBi hàm là mHt lNn cLp phát. Giá trf cYa các bi9n cJc bH này không Č@Ac l@u gi lci mHt khi hàm k9t thúc hoct ČHng. Vì vZy có mHt nguyên tƒc nh@ sau: Các biAn cic bp không lu gi8 kAt qu\ cho các l-n sau. L-n nào biAt l-n Jy, các biAn Č]a ph[ng Čqc sinh ra r`i chAt luôn khi ra khi hàm. Các tham s. cho hàm cyng là bi9n cJc bH. Nghda là cyng ch^ hoct ČHng khi hàm Čó Č@Ac gBi. 5.3.4 BiAn cic bp tfnh Chúng ta hoàn toàn có thP yêu cNu ch@eng trình cLp phát bH nhE cho các bi9n cJc bH theo ph@eng châm các bH nhE này Č@Ac thuê bao, Č@Ac cLp phát  mHt vf trí c. Čfnh, tdnh tci, luôn luôn Č@Ac dùng cho hàm. Vì vZy giá trf cYa các bi9n cJc bH tdnh này có thP t_n tci ngay c khi hàm Čã k9t thúc hoct ČHng. Wó là khai báo vEi t khoá static. Hãy xem ví dJ sau. #include void vi_du(void); main() { int n; for (n=1; n<=5; n++) vi_du(); } void vi_du(void) 83
  40. { static int i; i++; printf(" Goi lan thu %d\n", i) } K9t qu] cYa ch@eng trình này là nh@ sau: Goi lan thu 1 Goi lan thu 2 Goi lan thu 3 Goi lan thu 4 Goi lan thu 5 Bi9n cJc bH i  Čây Č@Ac khai báo là bi9n tdnh static. Chúng ta thLy k9t qu] cYa vi)c gBi hàm vi_du cho chúng ta thLy i c; tng dNn. WiOu Čó có nghda là i gi giá trf cYa nó trong su.t th i gian s.ng cYa ch@ng trình, ngay c] khi hàm Čã k9t thúc. Chúng ta cyng nhZn thLy rlng lNn gBi ČNu tiên, bi9n tdnh có giá trf blng 0. Do vZy có nguyên tƒc là: Các biAn cic bp tfnh Čqc khSi tUo có giá tr] = 0 khi dùng l-n Č-u. * L@u ð rlng biAn cic bp tfnh và biAn toàn cic Č=u t`n tUi trong su>t thi gian s>ng cga ch[ng trình, tuy nhiên biAn cic bp tfnh vtn chu Čqc dùng trong phUm vi hoUt Čpng cga n[i nó Čqc khai báo, nghda là trong phcm vi hàm ch;a khai báo bi9n cJc bH tdnh. Trong ví dJ trên, bi9n tdnh i ch^ có thP Č@Ac sI dJng trong hàm vi_du mà thôi. 5.4 Tham sD là con tr_ Tr@Ec khi trình bày vO cách sI dJng tham s. cYa mHt hàm là con trw, chúng ta su xem khái ni)m Č]a chu và con tr. 5.4.1 n]a chu và con tr Liên quan Č9n mHt bi9n ta có các khai niêm sau: tên bi9n, kiPu bi9n, giá trf bi9n. Ví dJ câu l)nh: float a = 1.5; xác Čfnh mHt bi9n tên là a có kiPu là float và có giá trf là 1.5. VEi khai báo trên thì máy su cLp mHt kho]ng nhE g_m 4 byte liên ti9p ČP l@u tr bi9n này. n]a chu cYa bi9n là s. th; tX cYa byte ČNu tiên trong dãy các byte liên ti9p mà máy dành ČP l@u tr bi9n (các byte Č@Ac Čánh t s. 0). Phép toán: —&“ dùng ČP lLy Čfa ch^ mHt bi9n. Ví dJ: &a cho ta Čfa ch^ cYa bi9n a. L@u ð là máy phân bi)t các kiPu Čfa ch^: Čfa ch^ kiPu int, Čfa ch^ kiPu float, Čfa ch^ kiPu double, Con tr là mHt bi9n dùng ČP ch;a Čfa ch^. Vì có nhiOu loci Čfa ch^, nên cyng có nhiOu kiPu con trw t@eng ;ng: con trw kiPu int dùng ČP ch;a Čfa ch^ các bi9n kiPu int, Cyng nh@ bi9n con trw cNn Č@Ac khai báo tr@Ec khi sI dJng. Khai báo con trw Č@Ac thXc hi)n theo mku sau: kiPu *tên_con_trw; Ví dJ: 84
  41. int a, b, *px, *py; khai báo 2 s. nguyên a, b và 2 con trw kiPu int là px và py. Khi Čã có các khai báo này thì các câu l)nh sau: px = &a; py = &b; là hoàn toàn xác Čfnh. Nh@ vZy, con trw px ch;a Čfa ch^ cYa bi9n a, con trw py ch;a Čfa ch^ cYa bi9n b. Bây gi ta chú ð Č9n các cách vi9t: *px và *py WiOu này Č@Ac phát biPu nh@ sau: n9u con trw px là trw tEi bi9n x thì các cánh vi9t x và *px là t@eng Č@eng nhau. Ví dJ: int x, y, *px, *py; px = &x; py = &y; x = 3; /* t••ng •••ng v•i *px = 3 */ y = 5; /* t••ng •••ng v•i *py = 5 */ /* Các câu l•nh d••i •ây là t••ng •••ng: */ x = 10 * y; *px = 10 * y; x = 10 * (*py); *px = 10 * (*py); 5.4.2 Hàm có tham s> là con tr Chúng ta xét ví dJ sau. #include void hoan_vi(int a, int b); /* nguyên m•u hàm, prototype */ main() { int n=10, p=20; printf(" Tr••c khi g•i hàm : %d %d\n", n, p); hoan_vi(n, p); printf(" Sau khi g•i hàm : %d %d\n", n, p); } void hoan_vi(int a, int b) { int t; printf(" Tr••c khi hoán v• : %d %d\n", a, b); t=a; a=b; b=t; printf(" Sau khi hoán v• : %d %d\n", a, b); 85
  42. } Ch@eng trình này cho k9t qu] sau: Tr••c khi g•i hàm : 10 20 Tr••c khi hoán v• : 10 20 Sau khi hoán v• : 20 10 Sau khi g•i hàm : 10 20 Nh@ th9 chúng ta nhZn thLy, k9t qu] tr@Ec và sau khi gBi hàm không có sX thay Č:i. Phân tích: Hàm hoán_v] nhZn 2 giá trf tham s. t@eng ;ng vEi 2 tham s. hình th;c là a và b. Nó su thXc hi)n vi)c hoán Č:i giá trf cYa 2 tham s. này. Song chúng ta thLy khi quay tr vO ch@eng trình chính, chúng ta không thLy dLu v9t gì cYa sX hoán vf này Č.i vEi 2 tham s. thXc sX là n và p. ThXc vZy khi gBi hàm, 2 bi9n n và p su Č@Ac sao chép giá trf ČP dùng cho hàm hoán_v]. Nh@ vZy hàm su sao ra mHt b]n khác ČP dùng nên b]n g.c không bao gi bf thay Č:i. Hi)n t@Ang sao m@An giá trf này Č@Ac gBi là sao m@An dùng cJc bH trong hàm  vf trí 2 tham s. hình th;c a và b. Wó chính là lí do vì sao k9t qu] tr@Ec và sau khi gBi hàm ČOu nh@ nhau. Nh@ th9 hàm hoán_v] không gi]i quy9t Č@Ac yêu cNu Čxt ra. WP gi]i quy9t Č@Ac vLn ČO này chúng ta su sI dJng tham s. là con trw. Vi)c thay Č:i giá trf cYa nhiOu tham s. thông qua các hàm có thP Č@Ac thXc hi)n thông qua vi)c truyOn giá trf Čfa ch^ cYa tham s. Čó cho hàm, Čfa ch^ cYa tham s. ch; không ph]i giá trf cYa tham s Khi Čó chúng ta có thP thay Č:i Č@Ac giá trf cYa tham s. Čó. Chúng ta vi9t lci hàm hoán vf hai bi9n sI dJng truyOn Čfa ch^ cho hàm: #include void hoan_vi(int *a, int *b); main() { int n = 10, p = 20; printf(" Tr••c khi g•i hàm : %d %d\n", n, p); hoan_vi(&n, &p); printf(" Sau khi g•i hàm : %d %d\n", n, p); } void hoan_vi(int *a, int *b) // a và b bây gi• là 2 ••a ch• { int t; printf(" Tr••c khi hoán v• : %d %d\n", *a, *b); t = *a; /* t nh•n giá tr• ch•a trong ••a ch• a */ *a = *b; *b = t; printf(" Sau khi hoán v• : %d %d\n", *a, *b); } K9t qu] nhZn Č@Ac nh@ mong mu.n: Tr••c khi g•i hàm : 10 20 Tr••c khi hoán v• : 10 20 86
  43. Sau khi hoán v• : 20 10 Sau khi g•i hàm : 20 10 Chúng ta hãy chú ð 2 kí hi)u: w9 ČBc là giá trf tci Čfa ch^ a, là kí hi)u giá trf Č@Ac l@u tr trong bH nhE có Čfa ch^ là a. &a ČBc là Čfa ch^ cYa a, là kí hi)u Čfa ch^ bH nhE ch;a giá trf a. Câu hwi Čxt ra là: khi nào thì dùng tham s. là con trw? ThXc ra, trong s. các tham s. cYa mHt hàm, ta chia ra làm 2 loci. Loci th; nhLt là các tham s. các giá trf cNn truyOn vào cho hàm, gBi là tham s. vào. Loci th; hai là các tham s. dùng ČP ch;a các k9t qu] mEi nhZn Č@Ac, gBi là tham s. ra. Ví dJ, cNn lZp mHt hàm ČP gi]i ph@eng trình bZc 2 (ax2 + bx + c = 0), thì các tham s. vào su là a, b, c; còn các tham s. ra su là các nghiêm x1 và x2. Nh@ th9, các tham s. x1 và x2 ph]i sI dJng kiPu con trw ČP nhZn giá trf. Bài tZp: o Tci sao l)nh scanf sI dJng Čfa ch^ cho các tham s. thXc ? o Vi9t hàm gi]i ph@eng trình bâc hai: ax2 + bx + c = 0. 5.5 [ qui Ngôn ng C cho phép t trong thân mHt hàm có l i gBi tEi chính hàm Čó. Hàm nh@ th9 Č@Ac gBi là hàm Č) qui. Ví dJ tính giai tha qua Čfnh nghda: n! = 1.2.3 (n-1).n hoxc Čfnh nghda: 1 khi n = 0 n ! = (n-1)!.n khi n >= 1 Khi Čó hàm giai_thua có thP Č@Ac Čfnh nghda nh@ sau: int giai_thua(int n) { if (n == 0) return (1); else return (n * giai_thua (n-1)); } và ch@eng trình hoàn ch^nh #include long giai_thua (int n); /* khai báo hàm*/ main() { 87
  44. int n; /* ••c s• n */ printf(" n= "); scanf("%d", &n); /* In ra giai th•a */ printf(" n! = %ld\n", giai_thua (n) ); return(0); } long giai_thua (int n) { if (n==0) return(1); else return (n * giai_thua(n-1)); } Vi)c sI dJng Č) qui cNn sI dJng bH nhE x9p ch_ng kiPu LIFO (Last In, First Out stack) ČP ch;a các k9t qu] trung gian và do Čó cNn h9t s;c thZn trBng l@ ng tr@Ec vi)c k9t thúc cYa quá trình Č) qui này. Trong thí dJ trên, l)nh gán: k = giai_thua (-1); su khi ČHng mHt quá trình Č) qui rLt dài vO mxt lð thuy9t vì tham s. âm bf xI lð sai. Khƒc phJc vLn ČO trên blng cách thêm vào câu l)nh: if (n <0) return(-1); Ngn x9p n = 3; giai_thua(3); 3*giai_thua(2) 2* giai_thua(1) 1* giai_thua(0) 1 1 2 Gi]i thích hoct ČHng cYa hàm Č) quy giai_thua khi hoct ČHng: Ví dJ tính giai tha  trên vO ph@eng di)n ví dJ nó rLt Čen gi]n và d‘ hiPu. Song vO ph@eng di)n k0 thuZt lZp trình thì ng@ i ta có thP tính giai tha mHt cách ti9t ki)m hen blng ch@eng trình sau sI dJng l)nh lxp while: long giai_thua (int n); { int i, k; 88
  45. i = 0; k = 1; /*Ph•i dùng bi•n c•c b• k •• ch•a k•t qu• trung gian */ while (i y thì usc(x, y) = usc(x-y, y) • n9u x y) return usc(x-y, y); else return usc(x, y-x); } Bài tkp: 1. Vi9t lci hàm usc dùng vòng lxp. 2. Hãy vi9t ch@eng trình sI dJng hàm Č) qui ČP tco dãy s. Fibonacci 89
  46. Dãy s. Fibonacci là dãy s. F1, F2, F3, Fn Č@Ac tco ra vEi công th;c: Fn = Fn-1 + Fn-2 VEi F1=1, F2=1 Thí dJ: 1, 1, 2, 3, 5, 8, 13, 21, 3. Vi9t hàm Č) quy tính t:ng: 12 + 22 + + n2. 4. Vi9t các hàm cHng, tr, nhân, chia phân s. (sI dJng hàm @Ec s. chung lEn nhLt). 5.6 MBt sD hàm chu.n Hàm chu+n là mHt s. hàm Čã Č@Ac khai báo và Čfnh nghda s•n bi ngôn ng C mà chúng ta có thP sI dJng. WP sI dJng các hàm chu+n thông th@ ng chúng ta ph]i sI dJng (include ČP ch^ cho ch@eng trình bi9t các hàm chu+n Čó Č@Ac ch;a trong t)p tiêu ČO nào. 5.6.1 TMp tiêu Č= stdio.h printf() và scanf() thì chúng ta Čã Č@Ac giEi thi)u tr@Ec. int getchar(void): ČBc vào mHt kí tX. 5.6.2 TMp tiêu Č= conio.h void clrscr(void): xóa màn hình. int getch(void): lLy mHt phím vào, trên màn hình không hi)n. int getche(void): lLy mHt phím vào, trên màn hình có hi)n. 5.6.3 TMp tiêu Č= stdlib.h int rand(void): tr] vO mHt s. ngku nhiên trong kho]ng t 0 (RANMAX-1); RANMAX = 32767 int randomize(void): hàm khi ČHng bi9n ngku nhiên, Č@Ac sI dJng cùng vEi hàm rand(). 5.6.4 TMp tiêu Č= math.h int abs(int x): tr] vO giá trf tuy)t Č.i cYa mHt s. nguyên. double fabs(double x): tr] vO giá trf tuy)t Č.i cYa mHt s. thXc. double sqrt(double x): tính cn bZc 2 mHt s double sin(double x), double cos(double x), double tan(double x), double pow(double x, double y): tính xy. double log(double x): tính ln(x). double log10(double x): tính log10(x). 90
  47. Chng 6. Ki.u mng 6.1 M$ng mBt chiGu N.1.1 Khai báo m\ng M]ng là mHt dãy các phNn tI cùng mHt kiPu d li)u nào Čó Č@Ac sƒp x9p theo mHt trình tX nhLt Čfnh. Cú pháp khai báo mHt m]ng là nh@ sau: kiPu_d_li)u tên_m]ng[s._phNn_tI_cYa_m]ng]; Ví dJ mHt s. khai báo m]ng sau: int m[10]; float a[100]; static char message[25]; S. phNn tI cYa m]ng Č@Ac xác Čfnh ngay t khi khai báo m]ng. M|i phNn tI cYa m]ng Č@Ac truy nhZp trXc ti9p thông qua tên m]ng cùng vEi ch^ s. (vf trí cYa phNn tI trong m]ng) Č@Ac ČP gia hai ngoxc vuông [ ]. VEi mHt m]ng có n phNn tI thì ch^ s. cYa các phNn tI Č@Ac Čánh s. t 0 Č9n n-1. Vi)c truy cZp Č9n phNn tI có ch^ s. n là bLt hAp lí. Ch£ng hcn vEi khai báo m]ng ČNu tiên trong ví dJ trên thì su có các phNn tI sau: m[0], m[1], m[2], m[3], , m[9] Ví di: ČBc các giá trf cho m]ng x t bàn phím. #include #define kich_thuoc 5 /* 5 •• th• cho d• */ main() { int x[kich_thuoc]; int i; for (i=0; i <= kich_thuoc-1; i++) { printf(" x[%d]= ", i); scanf("%d", &x[i]); } /* Vi•t l•i các giá tr• c•a m•ng lên màn hình */ printf(" \nM•ng x g•m có các ph•n t•"); for (i=0; i < kich_thuoc; i++) printf("\n x[%d]= %d", i, x[i]); } Ví dJ chcy ch@eng trình nhZp li)u cho các phNn tI cYa m]ng x nh@ sau: x[0]=12↵ 91
  48. x[1]=34↵ x[2]=56↵ M]ng x g_m có các phNn tI x[0]=12 x[1]=34 x[2]=56 6.1.2 PhSi tUo m\ng M]ng có thP khi tco giá trf ngay khi khai báo. Cú pháp là: kiPu_d_li)u tên_m]ng[s._phNn_tI_cYa_m]ng] = {danh_sách_các_giá_trf_khi_tco}; Ngoài ra, khi khai báo m]ng có khi tco giá trf cho các phNn tI thì có thP không cNn khai báo s. phNn tI cYa m]ng. Ví dJ: int x[3] = {7, 4, 5}; hoxc: int x[] = {7, 4, 5}; Nghda là ngay khi khai báo, ta Čã gán các giá trf cho m]ng: x[0] = 7; x[1] = 4; x[2] = 5; L@u ð là n9u s. các phNn tI trong danh sách các giá trf khi tco ít hen s. các phNn tI cYa m]ng thì vi)c khi tco ČuaBac thXc hi)n t phNn tI ČNu tiên (ch^ s. 0), các phNn tI không có giá trf khi tco t@eng ;ng Č@Ac gán giá trf ngNm Čfnh là 0. Ví di: cHng hai m]ng mHt chiOu C = A + B. #include #define kich_thuoc 5 /* 5 •• th• cho d• */ main() { int a[kich_thuoc] = {1, 2, 3, 4, 5}; int b[kich_thuoc] = {5, 4, 3, 2, 1}; int c[kich_thuoc]; int i; /* Làm phép c•ng m•ng */ for (i=0; i < kich_thuoc; i++) c[i] = a[i] + b[i]; /* In ra giá tr• m•ng C */ printf(" \nM•ng c g•m có các ph•n t•"); for (i=0; i < kich_thuoc; i++) printf("\n c[%d]= %d", i, c[i]); } 92
  49. Bài tkp: • NhZp vào 2 vector, sau Čó tính tích vô h@Eng cYa 2 vector Čó. • NhZp vào mHt m]ng, sau Čó tính t:ng các phNn tI cYa m]ng. 6.2 Ta khóa typedef T khóa typedef dùng ČP Čxt tên cho mHt kiPu d li)u. Tên kiPu này su Č@Ac dùng ČP khai báo d li)u sau này. Nên chBn tên ngƒn gBn và gAi nhE. Ví dJ câu l)nh Čxt tên kiPu int là nguyen: typedef int nguyen; Sau Čó có thP dùng nguyen (cyng nh@ int) ČP khai báo các bi9n, m]ng nguyên nh@ sau: nguyen x, a[10]; T@eng tX ta có ví dJ khác: typedef float mangthuc10[10]; Sau Čó ta có thP dùng khai báo: mangthuc10 x, y; /* khai báo 2 m•ng th•c m•t chi•u 50 ph•n t• */ 6.3 S?p x:p m$ng Sƒp x9p các phNn tI cYa m]ng theo mHt trZt tX tng hoxc gi]m là mHt vLn ČO th@ ng hay gxp trong lZp trình. Có rLt nhiOu cách sƒp x9p các phNn tI cYa m]ng. Chúng ta se xem xét mHt vài cách sƒp x9p Čen gi]n. 6.3.1 Szp xAp l+a ch)n Gi] sI ta có mHt dãy phNn tI Č@Ac ch;a trong mHt m]ng. Các phNn tI m]ng có thP là các s. nguyên hoxc s. thXc hoxc xâu kí tX. Cách sƒp x9p là nh@ sau: • WNu tiên Čem phNn tI th; nhLt lNn l@At so sánh vEi các phNn tI ti9p theo, n9u nó lEn hen thì Čem Č:i ch| giá trf cYa phNn tI ČNu tiên vEi phNn tI Čang so sánh. K9t qu] sau l@At ČNu, phNn tI ČNu tiên su gi giá trf nhw nhLt. • Ti9p tJc l@At hai, Čem phNn tI th; hai so sánh vEi các phNn tI ti9p theo, n9u nó lEn hen thì Čem Č:i ch| giá trf cYa phNn tI th; hai vEi phNn tI Čang so sánh. • Vi)c này Č@Ac ti9n hành cho Č9n khi ta gxp phNn tI cu.i cùng. Ví dJ: sƒp x9p m]ng. #include #define kich_thuoc 5 main() { int x[kich_thuoc]; int i, j, tam; /* ••c các giá tr• m•ng */ 93
  50. for (i=0; i x[j]) { tam=x[i]; /* Hoán ••i giá tr• 2 bi•n */ x[i]=x[j]; x[j]=tam; } } /* Vi•t l•i các giá tr• c•a m•ng lên màn hình */ printf(" \nM•ng x g•m có các ph•n t•"); for (i=0; i x[j]) m = j; } if (m != i) { tam=x[m]; x[m]=x[i]; x[i]=tam; } } 94
  51. N.3.2 Szp xAp n_i b)t Nguyên tƒc cYa ph@eng pháp là duy)t các phNn tI cYa m]ng t Čáy lên Č9n Č^nh (hay t cu.i m]ng Č9n ČNu m]ng). DBc Č@ ng n9u gxp hai phNn tI k9 cZn ng@Ac th; tX thì Č:i ch: chúng cho nhau. Nh@ vZy, trong l@At ČNu gái trf nhw nhLt su cguyPn lên Č9n Č^nh (ČNu m]ng). W9n l@At th; hai, phNn tI nhw th; hai Č@Ac chuyPn lên vf trí th; hai, N9u hình dung, m]ng Č@Ac Čxt th£ng Č;ng thì sau t;ng l@At sƒp x9p các phNn tI có giá trf nhw su n:i dNn lên nh@ bBt n@Ec trong n_i Čang sôi. Vì vZy ph@eng pháp này Č@Ac gBi là: sƒp x9p n:i bBt. ThuZt toán cho ph@eng pháp này nh@ sau: /* S•p x•p n•i b•t */ for (i = 0; i i + 1; j ) { if (x[j] chot) j ; 95
  52. if (i a[g]) t = g + 1; 96
  53. else return(g); } return(n); /* tr••ng h•p không tìm th•y x */ } Bài tâp: Hãy so sánh ph@eng pháp tìm ki9m nhf phân và ph@eng pháp tìm ki9m tuNn tX. 6.5 M$ng là tham sD ca hàm Nhƒc lci rlng phép toán lLy Čfa ch^ mHt bi9n là &, nó cyng Č@Ac áp dJng cho các phNn tI cYa m]ng. W.i vEi m]ng mHt chiOu, các phNn tI Č@Ac b. trí liên ti9p nhau trong bH nhE. Nghda là, n9u bi9t Č@Ac Čci ch^ cYa phNn tI th; i ta su tính Č@Ac Čfa ch^ cYa phNn tI th; i+1. WiOu Čó cyng có nghda là Čfa ch^ cYa phNn tI ČNu tiên là Čfa ch^ cYa m]ng. Trong ngôn ng C, tên m]ng là hlng Čfa ch^, nghda tên cYa mHt m]ng mang Čfa ch^ cYa m]ng Čó. Ví dJ ta có khai báo: int a[10]; Thì ta có cách vi9t t@eng Č@eng nh@ sau: a ⇔ &a[0] a + i ⇔ &a[i] *(a + i) ⇔ a[i] Tham s. cYa mHt hàm cyng có thP là mHt m]ng. Ví dJ, vi9t lci ch@eng trình sƒp x9p m]ng blng cách sI dJng hàm. #include #define kich_thuoc 5 void sap_xep(int n, int x[]); main() { int x[kich_thuoc]; int i; /* ••c các giá tr• m•ng */ for (i=0; i <= kich_thuoc-1; i++) { printf(" x[%d]= ", i); scanf("%d", &x[i]); } sap_xep(kich_thuoc, x); /* Vi•t l•i các giá tr• c•a m•ng lên màn hình */ printf(" \nM•ng x g•m có các ph•n t•"); for (i=0; i < kich_thuoc; i++) printf("%7d", x[i]); } 97
  54. void sap_xep(int n, int x[]) { int tam, i, j; /* S•p x•p m•ng */ for (i=0; i x[j]) { tam=x[i]; x[i]=x[j]; x[j]=tam; } } } T ví dJ trên ta nhZn thLy, khi khai báo hàm có tham s. là m]ng, ta ch^ cNn khai báo m]ng vEi hai dLu ngoxc vuông tr.ng ČP truyOn cho hàm Čfa ch^ cYa m]ng. void sap_xep(int n, int x[]); Ngoài ra ta cyng có thP khai báo kiPu con trw nh@ sau: void sap_xep(int n, int *x); Hai cách khai báo này là t@eng Č@eng. Còn khi gBi hàm, ta ch^ cNn truyOn cho hàm tên m]ng là ČY. Vì tên m]ng chính là Čfa ch^ biPu di‘n Čfa ch^ ČNu cYa m]ng. sap_xep(kich_thuoc, x); Hoxc cách t@eng Č@eng nh@ sau: sap_xep(kich_thuoc, &x[0]); Bài tZp: vi9t hàm tính t:ng các phNn tI cYa mHt m]ng kiPu double. 6.6 M$ng nhiGu chiGu M]ng d li)u có thP có nhiOu chiOu. Ví dJ chúng ta khái báo m]ng 2 chiOu sau: int x[3][5]; là m]ng ch;a các s. nguyên, có 3 hàng, 5 cHt. Các phNn tI m]ng Č@Ac Čánh s. nh@ se Č_ d@Ei Čây: 0 1 2 3 4 0 x[0, 0] X[0, 1] x[0, 2] x[0, 3] x[0, 4] 1 x[1, 0] X[1, 1] x[1, 2] x[1, 3] x[1, 4] 2 x[2, 0] X[2, 1] x[2, 2] x[2, 3] x[2, 4] Ví dJ vO truy cZp các phNn tI cYa m]ng là nh@ sau: x[0,3]; x[i, j], Ví dJ khai báo các m]ng khác: float x[2][2]; 98
  55. char x[4][5]; L@u ð khi tính toán ch^ s. ma trZn: có thP x+y ra hi)n t@Ang tràn ch^ s., t;c là giá trf t^ s. nlm ra ngoài phcm vi Čã khai báo. Ví dJ m]ng 3 chiOu Č@Ac khai báo nh@ sau: int m[3][5][8]; Kh]i t^o giá trW mng nhiLu chiLu M]ng nhiOu chiOu có thP Č@Ac khi tco vEi các giá trf ban ČNu. Ví dJ: int x[3, 2]= { { 1, 2}, { 3, 4}, {5, 6} }; int x[3, 2]= { 1, 2, 3, 4, 5, 6}; Hai cách khi gán này là t@eng Č@eng. Các ví dG Ví dJ vO cHng hai ma trZn C = A + B nghda là công tng phNn tI t@eng ;ng cYa hai ma trZn: C[i][j] = A[i][j] + B[i][j] Ch@eng trình su thXc hi)n các công vi)c sau: • WBc giá trf kích th@Ec m]ng vEi gi] thi9t Čây là 2 ma trZn cùng kích th@Ec. S. hàng không quá 20, s. cHt không quá 30. • WBc giá trf các phNn tI cYa m]ng. • HiPn thf k9t qu] trên màn hình. Ch@eng trình Č@Ac thP hi)n d@Ei dcng hàm. #include #define Max_Hang 20 #define Max_Cot 30 void nhap_ma_tran (int a[][Max_Cot], int so_hang, int so_cot); void tinh_tong (int a[][Max_Cot], int b[][Max_Cot], int c[][Max_Cot], int so_hang, int so_cot); void in_ma_tran (int c[][Max_Cot], int so_hang, int so_cot); main() { int so_hang, so_cot; /* Khai báo các m•ng */ int a[Max_Hang][Max_Cot], b[Max_Hang][Max_Cot], c[Max_Hang][Max_Cot]; printf(" Bao nhieu hang : "); scanf("%d", &so_hang); printf(" Bao nhieu cot : "); scanf("%d", &so_cot); printf("\n\nMang thu nhat:\n"); nhap_ma_tran (a, so_hang, so_cot); 99
  56. printf("\n\nMang thu hai:\n"); nhap_ma_tran(b, so_hang, so_cot); tinh_tong(a, b, c, so_hang, so_cot); printf("\n\nTong cua 2 mang la:\n\n"); in_ma_tran(c, so_hang, so_cot); } /* Hàm nh•p m•ng các s• nguyên */ void nhap_ma_tran(int a[][Max_Cot], int m, int n) { int i, j; int x; for (i=0; i < m; i++) { printf("\n Hay cho so lieu cua hang thu %2d\n", i+1); for (j=0; j < n; ++j){ scanf("%d", &x); a[i][j] = x; } } return; } /* Tính t•ng 2 m•ng các s• nguyên */ void tinh_tong(int a[][Max_Cot], int b[][Max_Cot], int c[][Max_Cot], int m, int n); { int i, j; for (i=0; i < m; i++) for (j=0; j < n; ++j) c[i][j]= a[i][j] + b[i][j]; return; } /* Hi•n th• k•t qu• */ void in_ma_tran (int a[][Max_Cot], int m, int n); { int i, j; for (i=0; i < m; i++) { for (j=0; j < n; ++j) printf("%4d", a[i][j]); printf("\n"); } 10 0
  57. return; } Trong ch@eng trình trên, khai báo hàm vEi tham s. là m]ng Č@Ac vi9t theo mku sau: void nhap_ma_tran(int a[][Max_Cot], int m, int n) Wó là m]ng a vEi 2 ngoxc cxp ngoxc vuông. Cxp ngoxc vuông th; nhLt t@eng ;ng vEi s. hàng và là r|ng. Trong khi Čó cxp ngoxc vuông th; hai lci ch;a s. cHt mHt cách rõ ràng. Cách vi9t này cho ta Čfa ch^ cYa m]ng. Bài tZp: 1. Vi9t ch@eng trình nhân 2 m]ng sI dJng hàm. 2. Vi9t ch@eng trình Č]o các phNn tI cYa 2 cHt hoxc 2 hàng 3. Vi9t ch@eng trình sƒp x9p tLt c] các phNn tI cYa các cHt (hàng) theo chiOu gi]m dNn 4. Vi9t ch@eng trình tìm phNn tI có giá trf lEn nhLt trong Č@ ng chéo cYa m]ng 5. Vi9t ch@eng trình tìm phNn tI có giá trf lEn nhLt trong m]ng 6. Cho bi9t hàm sau làm gì ? void in_ma_tran (int a[][Max_Cot], int m, int n); { int i, j; for (i=0; i < m; i++) for (j=0; j < n; ++j) printf("%4d%c", a[i][j], j == n-1 ? ‘\n’ : ‘ ‘); } 7. KiPm tra ma trZn có Č.i x;ng qua Č@ ng chéo chính (phJ). 8. Xóa tLt c] các phNn tI x trong m]ng mHt chiOu. 9. Xóa tLt c] các phNn tI có giá trf lEn nhLt trong m]ng mHt chiOu. 10. W9m s. phNn tI có giá trf lEn nhLt trong m]ng môt hoxc hai chiOu. 11. Xóa phNn tI th; k cYa m]ng mHt chiOu. 12. Xóa cHt (hàng) th; k cYa m]ng hai chiOu chiOu. 10 1
  58. Chng 7. Xâu kí ta 7.1 Khai báo và khdi gán Xâu kí tX Č@Ac xây dXng và l@u trong bH nhE nh@ mHt m]ng mHt chiOu kiPu char, và Č@Ac k9t thúc blng kí tX ”\0‘ hay NULL. 7.1.1 Khai báo Có 2 cách khai báo xâu kí tX: Cách 1: Khai báo kiPu m]ng kí tX: char ten_mang[kich_thuoc]; Ví dG: char ten[32]; khai báo xâu ten có thP ch;a t.i Ča 32 kí tX (kP c] kí tX NULL cu.i cùng ). N9u ta dùng hàm gets(ten) ČP ČBc các kí tX và ta nhZp: Lap trinh C? thì xâu này Č@Ac l@u trong m]ng nh@ sau: L a p T r I n h C ”\0‘ 0 1 2 2 4 5 6 7 8 9 1 1 0 1 Cách 2: Khai báo con trw kiPu kí tX Tên xâu kí tX cyng chính là Čfa ch^ cYa m]ng nên ta có thP khai báo: char *tên_con_trw; Ví dG: char *line; 7.1.2 KhSi gán Ta có thP dùng các cách khi gán thông qua ví dJ sau: • char line[12 ]= {'L', 'a', 'p', ' ', 't', 'r', 'i', 'n', 'h', 'C', ' ', '\0'}; // (a) • char line[12 ]= "Lap trinh C"; // (b) • char line[ ]= "Lap trinh C"; // (c) • char *line = "Lap trinh C"; // (d) Các cách khi gán trên cho k9t qu] nh@ nhau. Tuy nhiên,  (a), (b) và (c), ta khi gán cho m]ng mHt chiOu, tên m]ng là hlng Čfa ch^, còn  (d) con trw line là bi9n. Ví dJ: Khai báo và khi gán cho con trw kiPu kí tX: main() { 10 2
  59. char *message="Hoc TC kho qua"; printf("\n%s", message); getch(); } 7.1.3 Truy nhkp vào ph-n tj cga xâu Gi.ng nh@ m]ng mHt chiOu. Ta dùng: tên_con_trw[ch^_s.]; hoxc tên_m]ng[ch^_s.]; Ví dJ: Xác Čfnh ČH dài cYa xâu kí tX. void main() { char line[20]="Hoc TC kho qua"; char *message="Hoc TC kho qua"; int dem=0; while(line[dem] != '\0') dem++; printf("\nDo dai cua xau line la: %d",dem); dem = 0; while(message[dem]!='\0') dem++; printf("\nDo dai cua xau dem la: %d",dem); getch(); } 7.2 MBt sD hàm xT lð xâu kí tQ (trong string.h) • Hàm xác Čfnh ČH dài xâu: strlen() Cú pháp: int strlen(char *str) Hàm có Č.i là con trw kiPu char, tr] vO s. kí tX cYa chu|i (không kP kí tX ”\0‘) Ví dJ: char *line = "Tin hoc"; thì strlen(line) = 7 Ta cyng có thP xác Čfnh ČH dài cYa xâu blng cách Č9m s. kí tX cYa xâu cho Č9n khi gxp kí tX ”\0‘. (ví dJ 2) Ví dJ: Xác Čfnh ČH dài xâu blng strlen() #include void main(void) { char *string = "Borland International"; printf("%d\n", strlen(string)); getch(); } Ví dJ: Vi9t xâu theo th; tX ng@Ac lci #include 10 3
  60. void inchuoinguoc(char *s); main() { char *string; printf("\nNhap vao mot chuoi:"); gets(string); printf("Chuoi nguoc: "); inchuoinguoc(string); getch(); } void inchuoinguoc(char *s) { int i; for (i = strlen(s);i >= 0; i ) putchar(s[i]); } • Hàm ghép xâu: strcat() Cú pháp: char *strcat(char *dest, char *source) Tác dJng: sao chép toàn bH nHi dung cYa xâu source và n.i vào ti9p sau nHi dung xâu dest. Kí tX NULL cYa xâu dest su bf vi9t Čè bi kí tX cYa source n9u dest không ČY ch|. Do Čó, lZp trình viên ph]i Č]m b]o là m]ng l@u des ph]i ČY ch| ČP l@u dest, source và kí tX NULL. N9u xâu dest không ČY ch| tr.ng thì k9t qu] su sai. Hàm ČOu tr] vO bi9n con trw trw Č9n chu|i dest. Chú ð: Không Č@Ac vi9t dest = dest + source; Ví dJ: In ra xâu Čã ghép t 2 xâu nhZp vào t bàn phím 1- Dùng khai báo m\ng ki7u kí t+ (ph\i Čg ch{ tr>ng Č7 chIa xâu 2) #include #define dodaixau 40 main() { char str1[dodaixau], str2[dodaixau]; printf("\nNhap vao mot str 1:");gets(str1); printf("Nhap vao mot str 2:");gets(str2); printf(" Sau khi strcat str2 vao str1: %s",strcat(str1,str2)); getch(); } Khi chcy ch@eng trình, n9u ta nhZp các xâu cho str1 hoxc str2 mà ČH dài cYa chúng v@At quá kích th@Ec khai báo thì máy su l|i. T@eng tX cho tr@ ng hAp n9u strlen(str1)+strlen(str2) lEn hen kích th@Ec str1 Č@Ac khai báo. 2 - Dùng khai báo m\ng ki7u kí t+ và khzc phic hiMn tqng nAu xâu Čqc ghép vào thiAu ô nh| tr>ng: 10 4
  61. #include #define dodaixau 80 main() { char str1[dodaixau], str2[dodaixau]; printf("\nNhap vao mot str 1:"); gets(str1); printf("Nhap vao mot str 2:"); gets(str2); if (dodaixau > strlen(str1) + strlen(str2)) printf(" Sau khi strcat str2 vao str1: ",strcat(str1, str2)); else printf("Khong du cho trong"); getch(); } 3- Dùng khai báo con tr ki7u kí t+ - không c-n ki7m tra kích th|c xâu str1. #include main() { char *str1, *str2; // không c•n ch• ••nh kích th••c c•a các xâu printf("\nNhap vao mot str 1:"); gets(str1); printf("Nhap vao mot str 2:"); gets(str2); printf(" Sau khi strcat str2 vao str1: %s",strcat(str1, str2)); getch(); } • Hàm sao chép xâu: strcpy() C không cho phép gán mHt xâu cho mHt bi9n. Nh@ng ta có thP sao chép mHt xâu và l@u vào bi9n con trw blng hàm strcpy: Cú pháp: char * strcpy(char *str1, char *str2) Tác dJng: sao chép toàn bH nHi dung xâu str2 (kP c] kí tX NULL), vi9t Čè lên nHi dung cy str1. Hàm tr] vO bi9n con trw trw Č9n Čfa ch^ cYa str1. Ví dJ: char *line; strcpy(line, “Ha Uyen”); Chú ð: Hàm này không kiPm tra kích th@Ec cYa str1, nên n9u str1 Č@Ac khai báo d@Ei dcng m]ng kiPu char thì ta ph]i l@u ð. • Hàm so sánh 2 xâu: strcmp() Các quy tƒc khi so sánh 2 xâu kí tX: • Các kí tX cYa 2 xâu Č@Ac so sánh tng cxp mHt t trái sang ph]i theo giá trf cYa mã ASCII. • N9u 2 xâu có ČH dài khác nhau song s. kí tX gi.ng nhau Č9n ČH dài xâu ngƒn hen, thì xâu có ČH dài nhw hen Č@Ac coi là bé hen. Ví dJ: —Ngoc“ < —NgocA“. • Hai xâu blng nhau n9u blng nhau c] nHi dung và ČH dài. 10 5
  62. Cú pháp: int strcmp(char *str1, char *str2) Hàm tr] vO: 0 n9u hai xâu blng nhau >0 n9u xâu str1 > str2 main() { char *str1, *str2; printf("\nNhap vao mot str 1:");gets(str1); printf("Nhap vao mot str 2:");gets(str2); if(strcmp(str1, str2)==0) printf("Hai xau nay giong nhau"); else if (strcmp(str1, str2) main() { char *str1, *str2; printf("\nNhap vao mot str 1:");gets(str1); 10 6
  63. printf("Nhap vao mot str 2:");gets(str2); if(strstr(str1, str2)==NULL) printf("Khong tim thay %s trong %s", str2, str1); else printf("Xau %s tim thay trong %s" ,str2,str1); getch(); } 7.3 MBt sD hàm chuy,n Čfi gi-a chugi và sD (trong stdlib.h) double atof (const char *nptr): chuyPn Č:i mHt chu|i trw bi con trw nptr thành s. thXc kiPu double. int atoi (const char *nptr): chuyPn Č:i mHt chu|i trw bi con trw nptr thành s. nguyên int. long int atol (const char *nptr): chuyPn Č:i mHt chu|i trw bi con trw nptr thành s. nguyên long. W.i vEi các hàm trên, n9u trf chuyPn Č:i không thP biPu di‘n Č@Ac, ch£ng hcn kí tX ČNu tiên cYa chu|i không ph]i là s., thì hàm su tr] vO trf 0. Ví dJ: Ch@eng trình sI dJng các hàm chuyPn Č:i trên. #include main() { char *pstr; clrscr(); printf("Nhap vao mot chuoi :"); gets(pstr); printf("\nChuyen pstr sang so nguyen int: %d", atoi(pstr)); printf("\nChuyen pstr sang so nguyen dai: %ld", atol(pstr)); printf("\nChuyen pstr sang so thuc: %f", atof(pstr)); getch(); } K9t qu] nh@ sau: • Tr@ ng hAp nhZp chu|i bƒt ČNu blng s.: Nhap vao mot chuoi :123.456 Tin hoc Chuyen pstr sang so nguyen int: 123 Chuyen pstr sang so nguyen dai: 123 Chuyen pstr sang so thuc: 123.456000 • Tr@ ng hAp nhZp chu|i bƒt ČNu blng kí tX: Nhap vao mot chuoi :Tin hoc 123.456 Chuyen pstr sang so nguyen int: 0 Chuyen pstr sang so nguyen dai: 0 Chuyen pstr sang so thuc: 0.000000 10 7
  64. double strtod (const char *nptr, char endptr): chuyPn Č:i mHt chu|i trw bi con trw nptr thành s. thXc kiPu double. Hàm có hai Č.i: mHt chu|i nptr (char *nptr) và mHt con trw trw vO chu|i (char endptr), nptr là chu|i cNn chuyPn Č:i. Con trw endptr su ch^ vO kí tX ČNu tiên sau phNn chu|i Čã Č@Ac chuyPn Č:i, hay nói cách khác là trw vO kí tX ČNu tiên trong phNn chu|i mà không thP chuyPn Č:i Č@Ac. Ví dJ: SI dJng hàm strtod. #include main() { char *str; char *pstr; clrscr(); printf("Nhap vao mot chuoi:");gets(str); printf("\nPhan so kieu double:%.2f", strtod(str,&pstr)); printf("\nPhan chuoi:%s",pstr); getch(); } K9t qu] nh@ sau: • Tr@ ng hAp nhZp chu|i bƒt ČNu blng s.: Nhap vao mot chuoi:123.123Tin hoc Phan so kieu double:123.12 Phan chuoi:Tin hoc • Tr@ ng hAp nhZp chu|i bƒt ČNu blng s.: Nhap vao mot chuoi:Tin hoc123.123 Phan so kieu double:0.00 Phan chuoi:Tin hoc123.123 long int strtol (const char *nptr, char endptr, int radix): chuyPn Č:i mHt chu|i trw bi con trw nptr thành s. nguyên dài. unsigned long int strtoul (const char *nptr, char endptr, int radix): chuyPn Č:i mHt chu|i trw bi con trw nptr thành s. nguyên dài không dLu. Hai hàm này t@eng tX nh@ hàm strtod, Č.i radix cho bi9t trf có thP chuyPn Č:i theo dcng ce s. nào. cJ thP: radix Ð nghda < 0 không hAp l) 0 Kí tX ČNu tiên và kí tX th; hai cYa xâu xác Čfnh ce s. cYa trf Č@Ac chuyPn Č:i: 10 8
  65. Kí tX th; nhLt Kí tX th; nhLt Giá trf chuyPn Č:i 0 1 7 Octal 0 x hoxc X Hexadecimal 1 9 Decimal 1 không hAp l) 2 cho bi9t ce s. cYa trf. Ví dJ, n9u radix =2 thì ce s. cYa trf là 2; néu radix là 20 thì 36 ce s. cYa trf là 20, h) này su bao g_m các ch s. 0 9 và các kí tX A J >36 không hAp l) N9u radix là không hAp l) thì hàm tr] vO 0 và endptr trw Č9n kí tX ČNu tiên cYa chu|i. 7.4 MBt sD hàm ki,m tra kí tQ (trong ctype.h) int isalnum(int c); int islower(int c); int isalpha(int c); int isprint(int c); int isascii(int c); int ispunct(int c); int iscntrl(int c); int isspace(int c); int isdigit(int c); int isupper(int c); int isgraph(int c); int isxdigit(int c); Các hàm trên ČOu tr] vO mHt giá trf khác 0 trong tr@ ng hAp Čúng hoxc blng 0 trong tr@ ng hAp sai. Tr] lci giá trf Čúng n9u: • isalpha: c là kí tX (A Z hoxc a z) • isascii: các kí tX có mã ASCII t 0 Č9n 127 (0x00 0x7F) • iscntrl: c là mã cYa phím delete hoxc cYa các các kí tX ČiOu khiPn khác:0x7F, 0x00, 0x1F) • isdigit: c là kí tX s. (0 9) • isgraph: c là kí tX hiPn thf, gi.ng nh@ hàm isprint, không kP kí tX space • islower: c là kí tX th@ ng (không ph]i hoa): a z • isprint: c là kí tX hiPn thf (0x20 0x7E) • ispunct: c là kí tX tr] lci giá trf Čúng cho hàm iscntrl hoxc isspace. • isspace: c là kí tX space, tab, carriage return, new line, vertical tab, hay formfeed (0x09 to 0x0D, 0x20) • isupper: c là kí tX hoa (A Z) • isxdigit: c là s.  h) 16 (0 9, A F, a f) 10 9
  66. Chúng ta co thP tham kh]o thêm các hàm xI lí chu|i trong các th@ vi)n string.h, stdlib.h, ctype.h. 7.5 M$ng xâu kí tQ M]ng xâu kí tX: là m]ng mà m|i phNn tI m]ng l@u tr mHt xâu kí tX. Nh@ vZy, thXc chLt Čây là m]ng con trw kiPu kí tX. Ví dJ: NhZp và sƒp x9p các xâu kí tX. void sapxep(char mainstr[][10], int row); const rowmax=10; char mainstr[10][10]; main() { int i, j, row; //Nhap so xau printf("Nhap so xau:"); scanf("%d%*c", &row); // Nhap xau printf("Nhap cac xau:\n"); for(i = 0; i 0) { strcpy(strtam, mainstr[i]) ; strcpy(mainstr[i], mainstr[j]); strcpy(mainstr[j], strtam); } } Ví dJ: nhZp vào mHt xâu kí tX và chuyPn thành ch hoa ČP in ra màn hình. #include 11 0
  67. #include #define MAX 80 main() { char xau[MAX]; /* M•ng ch• */ int dem; /* ••c dòng kí t• */ for (dem=0; dem = 0; dem ) putchar(toupper(xau[dem])); } Hàm toupper dùng ČP chuyPn mHt kí tX th@ ng thành kí tX hoa. L@u ð: khi mu.n gán mHt xâu kí ta ph]i sI dJng hàm strcpy. Ví dJ: char ho_ten[30]; strcpy(ho_ten, “Nguyen Van A”); n9u sI dJng: ho_ten = “Nguyen Van A”; là không hAp l). 11 1
  68. Chng 8. Ki.u cBu trúc (struct) và ki.u hcp (union) 1.1 Ki,u c2u trúc (struct) 8.1.1 Khái niMm và Č]nh nghfa ki7u cJu trúc Chúng ta Čã hBc vO kiPu cLu trúc d li)u nh@ m]ng (array). Các kiPu d li)u này ČOu Č@Ac tco ra blng mHt tZp hAp các phNn tI có cùng mHt kiPu. Ví dJ int mang[100]; có 100 phNn tI là các s. nguyên WP tco ra mHt kiPu d li)u mEi vEi các phNn tI d li)u có kiPu khác nhau nh@ng có liên k9t vEi nhau, C có Čfnh nghda kiPu d li)u struct, vi9t tƒt cYa structure, cLu trúc. Ngay trong C, bcn hoàn toàn có thP gBi kiPu struct là record (b]n ghi). Nói mHt cách khác, ČP mô t] cùng mHt Č.i t@Ang blng các phNn tI d li)u có mô t] kiPu khác nhau, chúng ta ph]i dùng cLu trúc kiPu struct. Nh@ vZy struct là mHt trong các ph@ng ti)n linh hoct ČP xây dXng các kiPu d li)u mEi. 8.1.2 Mô t\ và khai báo ki7u cJu trúc Mô t] kiPu cLu trúc Č@Ac vi9t blng ch struct, theo sau là danh sách khai báo các phNn tI d li)u cYa struct mà ta gBi là các tr@ ng. M|i mHt tr@ ng có mHt tên tr@ ng và Č@Ac dùng ČP chBn các phNn tI d li)u cYa struct. Ví dJ, mHt Čfa ch^ bao g_m các d li)u nh@ s. nhà, tên ph., thành ph.; ta mô t] và khai báo Dia_Chi vEi t khoá struct nh@ sau: struct Dia_Chi { int So_Nha; char Pho[20]; char Thanh_Pho[15]; }Ong_A, Ba_B; hoxc không cNn tên cYa struct mà có thP khai báo trXc ti9p các bi9n Ong_A, Ong_B nh@ sau: struct { int So_Nha; char Pho[20]; char Thanh_Pho[15]; }Ong_A, Ba_B; Nh@ vZy chúng ta có 3 tr@ ng là So_Nha, Pho và Thanh_Pho vEi kiPu khác nhau và chúng Č@Ac liên k9t lci vEi nhau ČP mô t] Čfa ch^. Sau Čó chúng ta có khai báo 2 bi9n là Ong_A, Ba_B (Wfa ch^ cYa Óng A, Wfa ch^ cYa Bà B) 11 2
  69. Chúng ta cyng có thP khai báo kiPu và bi9n cLu trúc tách r i nhau. Trong tr@ ng hAp này, bƒt buHc ph]i khai báo tên cYa struct: Wfnh nghda kiPu d li)u (ch@a cLp phát bH nhE): struct Dia_Chi { int So_Nha; char Pho[20]; char Thanh_Pho[15]; }; Khai báo bi9n (có cLp phát bH nhE): struct Dia_Chi Ong_A, Ba_B; Ví dJ, ČP mô t] th i gian Date ta có 3 tr@ ng: Ngày, Tháng và Nm. struct Date { unsigned char ngay; unsigned char thang; unsigned int nam; }date1, date2; hoxc struct Date date1, date2; Trong Čó có tính Č9n vi)c ngày, tháng, nm ch^ dùng các s. d@eng nên ta khai báo vEi t khóa unsigned. Ngoài ra, chúng ta có thP sI dJng t khóa typedef ČP Čfnh nghda cLu trúc nh@ sau: typedef struct { unsigned char ngay; unsigned char thang; unsigned int nam; }Date; Sau Čó, ch^ cNn khai báo mHt cLu trúc kiPu ngày nh@ sau: Date d1, d2; 8.1.3 Khai báo cJu trúc l`ng nhau Chúng ta cyng có thP khai báo cLu trúc bên trong cLu trúc. Ví dJ: WP mô t] nhân sX hay phi9u cán bH cYa phòng t: ch;c, ta ph]i dùng các tr@ ng HB Tên, Ngày Sinh, Ch| , L@eng,  Čây ta lLy ví dJ vEi 5 tr@ ng. Gi] sI ta Čã có mô t] kiPu Date và Dia_Chi nh@  trên. typedef struct { char Ho_Ten[30]; struct Date Ngay_Sinh; unsinged Gioi_Tinh; /* Nu=0, Nam=1 */ struct Dia_chi O_Tai; /* • t•i */ float Luong; /* L•ng */ } Nhan_Su; 11 3
  70. Nhan_su NguoiA, NguoiB; 8.1.4 Truy ckp vào ph-n tj cJu trúc VEi khai báo struct Dia_Chi { int So_Nha; char Pho[20]; char Thanh_Pho[15]; } Ong_A, Ba_B; Chúng ta có thP truy cZp vào các phNn tI cYa struct theo mku sau: tên_cLu_trúc.tên_phNn_tI Ví dJ: Ong_A.So_nha Ong_A.Pho Ong_A.Thanh_Pho hoxc dùng trong các hàm: printf(" Hãy cho tên ph• c•a ông A: "); gets(Ong_A.Pho); và r_i ta có thP can thi)p vào tng phNn tI cYa tên ph. vì tên ph. là mHt m]ng các kí tX. VEi N là s. nguyên và là ČH dài xâu kí tX cNn in. for (i=0; i < N; i++) putchar(Ong_A.Pho[i]); 8.1.5 Gán cJu trúc WP gán 2 cLu trúc, chúng ta có thP thXc hi)n mHt trong các ph@eng pháp sau: • Gán 2 bi9n kiPu cLu trúc cho nhau • Gán các phNn tI t@eng ;ng cYa cLu trúc Ví dJ ČP gán Čfa ch^ cYa ông A cho bà B, ta có thP rhXc hi)n 1 trong 2 cách sau: Ong_A = Ong_B; hoxc Ong_A.So_nha = Ba_B.So_Nha; Ong_A.Pho = Ba_B.Pho; Ong_A.Thanh_Pho = Ba_B.Thanh_Pho; 8.1.6 M\ng cJu trúc Chúng ta cyng có thP sI dJng cLu trúc ČP khai báo m]ng mà các phNn tI có kiPu cLu trúc. Gi] sI ta Čã có cLu trúc Nhan_su khai báo  trên. Bây gi ta khai báo mHt m]ng các nhân công nh@ sau: Nhan_su nhan_cong[100]; 11 4
  71. Wocn ch@eng trình sau su cho phép tính t:ng l@eng cYa 100 nhân công: double s = 0; int i; for (i = 0; i thành_phNn Hoxc: (*Tên_con_trw).thành_phNn Ví dJ, các cách sau là t@eng Č@eng: nc1.Luong ⇔ p1->Luong ⇔ (*p1).Luong 8.1.8 Hàm sj ding cJu trúc Tham s. hình th;c cYa hàm có thP là: • Bi9n cLu trúc, khi Čó tham s. thXc t@eng ;ng là mHt giá trf cLu trúc. • Con trw cLu trúc, khi Čó tham s. thXc t@eng ;ng là Čfa ch^ cYa bi9n cLu trúc. • M]ng cLu trúc hoxc con trw cLu trúc, khi Čó tham s. thXc t@eng ;ng là tên m]ng cLu trúc. Hàm có thP tr] vO: • Giá trf cLu trúc • Con trw cLu trúc Ví dJ: ch@eng trình d@Ei Čây qu]n lð mHt danh sách các nhân công (g_m hai thông tin: hB tên và bZc l@eng). Ch@eng trình thXc hi)n: nhZp d li)u, sƒp x9p theo hB tên, in ra danh sách các nhân công. #include #include #include 11 5
  72. #define N 100 typedef struct { char hoten[30]; float bacluong; } Nhan_Cong; void nhap(Nhan_Cong *nc); void xuat(Nhan_Cong nc); void sapxep(Nhan_Cong *p, int n); void hoanvi(Nhan_Cong *p1, Nhan_Cong *p2); main() { Nhan_Cong ds[N]; int i, n; clrscr(); printf(“Nhap so nhan cong: ”); scanf(“%d”, &n); for(i = 0; i 0) hoanvi(&p[i], &p[j]); 11 6
  73. } 1.2 Ki,u hhp (union) union Č@Ac dùng ČP chia s® cùng mHt s. ô nhE cho nhiOu bi9n khác nhau,  nhng th i ČiPm khác nhau, nhlm mJc Čích ti9t ki)m ô nhE. Vi)c khai báo union t@eng tX nh@ struct. Ví dJ, Čfnh nghda kiPu d li)u: union kieu_union { int i; char ch; }; và khai báo bi9n xyz: union u_type xyz; Nghda là trong bH nhE dành cho bi9n xyz, c] bi9n i và bi9n ch ČOu có thP chi9m gi bH nhE này. Vì vZy tci m|i th i ČiPm ch^ nên dùng mHt th;, sang th i ČiPm khác thì dùng th; khác. TLt nhiên trong ČNu bcn cNn ph]i rLt thZn trBng vì n9u không su là râu ông nB cƒm clm bà kia. Khi khai báo bi9n xyz, ch@eng trình dfch su b. trí kích th@Ec bH nhE lEn nhLt trong tLt c] các phNn tI cYa union. Trong ví dJ trên, máy su b. trí 2 byte cho kiPu kieu_union vì trong 2 thành phNn int và char thì int có kích th@Ec lEn nhLt, là 2 bytes. Vi)c truy nhZp vào các phNn tI cYa union cyng t@ng tX nh@ struct. Ví dJ: xyz.i, xyz.ch. union Č@Ac sI dJng trong nhiOu tr@ ng hAp. Ví dJ khi vi9t ch@eng trình dfch không phJ thuHc vào máy. Máy này thì yêu cNu là int, máy kia yêu cNu là long int. Bcn không ph]i quá lo nghd vO ČiOu này vì union gi dLu v9t kích th@Ec hi)n tci cYa union cho m|i tr@ ng hAp. Ví dJ: union table { int number; long address; char code; }; union table co_address; union table code_string[10]; union table address_no; Bài tkp: Vi9t ch@eng trình qu]n lð ČiPm thi Čci hBc mHt lEp hBc g_m các thông tin: hB tên, ngày sinh, ČiPm toán, ČiPm lð, ČiPm hóa, t:ng ČiPm ba môn. Ch@eng trình có các ch;c nng sau: • NhZp d li)u • Sƒp x9p danh sách sinh viên theo hBc tên • Tính t:ng ČiPm cYa tng sinh viên • Sƒp x9p danh sách sinh viên theo t:ng ČiPm • In danh sách sinh viên theo th; tX hB tên hoxc t:ng ČiPm 11 7
  74. • In ra các sinh viên có ČiPm toán trên 8.0 và t:ng ČiPm lEn hen 22.0 11 8
  75. Chng 9. Làm vi?c v0i t?p 9.1 Gii thi u Ngôn ng C cung cLp cho chúng ta rLt nhiOu các hàm ČP thao tác trên các t)p tin, nh@: m t)p, Čóng t)p, ČBc, ghi, C Čfnh nghda s•n mHt cLu trúc kiPu t)p cho ng@ i sI dJng là FILE và mã k9t thúc t)p là EOF (- 1) trong t)p tiêu ČO . Các t)p tin Č@Ac chia là hai loci: t)p tin vn b]n và t)p tin nhf phân. Trong bìa hBc này chúng ta ch^ tìm hiPu các xI lð Č.i vEi t)p tin vn b]n. 9.2 Dòng ch$y Tr@Ec khi nói Č9n các hàm xI lð t)p tin, chúng ta Č9 cZp Č9n khái ni)m dòng ch]y (stream). MHt dòng ch]y th@ ng là mHt con trw Č9n mHt cLu trúc. Có 3 dòng ch]y Č@Ac m ra bi mBi ch@eng trình C: stdin, stdout, stderr. • stdin (standard input) Č@Ac n.i vEi bàn phím ČP ČBc. • stdout (standard output) và stderr (standard error) Č@Ac n.i vEi màn hình ČP ghi. 9.3 Md t p Khi mu.n truy cZp thông tin mHt t)p, cNn ph]i m t)p tr@Ec. M t)p Č@Ac thXc hi)n bi hàm fopen() vEi cú pháp nh@ sau: FILE * fopen(const char *name, const char *mode) • Tham s. name là chu|i kí tX mang tên t)p cNn m (có thP ph]i ch^ rw c] Č@ ng dkn n9u cNn). • Tham s. mode là chu|i kí tX ch^ ra kiPu m t)p, mode có thP là mHt trong cac chu|i sau: o —r“: m t)p vn b]n ČP ČBc (t)p ph]i t_n tci, n9u không báo l|i) o —w“: m t)p vn b]n ČP ghi (ghi Čè n9u t)p Čã t_n tci, n9u không tco t)p mEi) o —a“: m t)p vn b]n ČP ghi vào  cu.i t)p (ghi n.i Čuôi n9u t)p t_n tci, n9u không tco t)p mEi) o —r+“ hoxc —w+“: m t)p vn b]n ČP ČBc/ghi o —a+“: m t)p vn b]n ČP ČBc/ghi  cu.i t)p • Hàm này tr] vO con trw Č9n t)p n9u m thành công, n9u không tr] vO con trw NULL. Ví dJ: #include FILE *fp; 11 9
  76. if ((fp = fopen("dulieu.txt","r")) == NULL) { fprintf(stderr,"Không th• m• t•p dulieu.txt\n"); exit(1); } 9.4 [óng t p Sau khi không làm vi)c vEi t)p na, chúng ta cNn ph]i Čóng t)p bi hàm fclose() vEi cú pháp nh@ sau: int fclose(FILE *fp) • Tham s. là con trw Č9n t)p cNn Čóng. • Hàm tr] vO 0 n9u thành công, ng@Ac lci tr] vO EOF. Ví dJ: #include FILE *f; fclose(f); 9.5 []c và ghi kí tQ trên t p 9.5.1 n)c kí t+ C cung cLp hai hàm ČBc kí tX vEi cú pháp nh@ sau: int getc(FILE *fp) int fgetc(FILE *fp) Hai hàm này có ch;c nng nh@ nhau, ČOu ČBc mHt kí tX t t)p tin Č@Ac trw bi fp. Hàm tr] vO kí tX ČBc Č@Ac, n9u có l|i x]y ra thì tr] vO EOF. Ví dJ: #include int c; FILE *fi; while ((c = fgetc(fi)) != EOF) { /* s• d•ng kí t• c */ } 9.5.2 Ghi kí t+ C cung cLp hai hàm ghi kí tX vEi cú pháp nh@ sau: int putc(int ch, FILE *fp) int fputc(int ch, FILE *fp) Hai hàm này có ch;c nng nh@ nhau, ČOu ghi mHt kí tX ch vào t)p tin Č@Ac trw bi fp. Hàm tr] vO kí tX ghi Č@Ac, n9u có l|i x]y ra thì tr] vO EOF. Ví dJ: 12 0
  77. #include int c; FILE *fi,*fo; main() { /* fi : con tr• t•p tin m• •• ••c */ if ((fp = fopen("dulieu.txt","r")) == NULL) { fprintf(stderr,"Không th• m• t•p dulieu.txt\n"); exit(1); } /* fo : con tr• t•p tin m• •• ghi */ if ((fp = fopen("tepmoi.txt","w")) == NULL) { fprintf(stderr,"Không th• m• t•p tepmoi.txt\n"); exit(1); } while ((c = fgetc(fi)) != EOF) fputc(c,fo); fclose(fi); fclose(fo); } 9.6 []c ghi tang dòng trên t p 9.6.1 n)c mpt dòng Hàm ČBc mHt dòng fgets có cú pháp nh@ sau: char *fgets(char *s, int n, FILE *fp) Các tham s.: • s là con trw kiPu char trw Č9n vùng nhE ch;a chu|i kí tX ČBc t t)p • n là ČH dài lEn nhLt cYa chu|i Č@Ac ČBc • fp là con trw t)p Č@Ac ČBc Hàm tr] vO dfa ch^ vùng nhE nhZn k9t qu]. N9u có l|i hoxc cu.i t)p thì tr] vO NULL. Vi)c ČBc mHt dòng k9t thúc khi mHt trong các tr@ ng hAp sau x]y ra: • hhoxc Čã ČBc Č@Ac n-1 kí tX • Hoxc gxp dLu xu.ng dòng (cxp mã 13 10). Mã 10 Č@Ac ghi vào xâu k9t qu]. • Hoxc k9t thúc t)p Xâu k9t qu] Č@Ac b: sung thêm kí hi)u ”\0‘. 12 1