bai giang tin dc -...

86
2 MC LC PHN 1 ...................................................................................................................................... 4 ĐẠI CƯƠNG VTIN HC ...................................................................................................... 4 CHƯƠNG 1 – NHNG KHÁI NIM CƠ BN VTIN HC............................................ 5 1.1 Đối tượng nghiên cu ca Tin hc ............................................................................... 5 1.2 Thông tin và xlý thông tin ......................................................................................... 5 1.3 Hđếm và biu din thông tin trong máy tính ............................................................. 6 1.4 Nguyên lý ca hxlý thông tin tđộng .................................................................... 8 1.5 Cu trúc máy tính ....................................................................................................... 10 1.6 Mt sng dng ca Tin hc ..................................................................................... 12 CHƯƠNG 2 – HĐIU HÀNH ......................................................................................... 14 2.1 Hđiu hành MS-DOS ............................................................................................... 14 2.2 Hđiu hành Windows .............................................................................................. 16 CHƯƠNG 3 – THUT TOÁN ............................................................................................ 21 3.1 Khái nim ................................................................................................................... 21 3.2 Mt sphương pháp biu din thut toán .................................................................. 21 3.3 Các cu trúc cơ bn ca thut toán ............................................................................. 23 3.4 Mt sthut toán gii mt sbài toán đơn gin ........................................................ 26 PHN 2 .................................................................................................................................... 32 NGÔN NGLP TRÌNH C ................................................................................................... 32 CHƯƠNG 1 - MT SKHÁI NIM MĐẦU ................................................................ 33 1.1 Tp ký t..................................................................................................................... 33 1.2 Tkhóa ....................................................................................................................... 33 1.3 Tên .............................................................................................................................. 34 1.4 Mt skhái nim ........................................................................................................ 34 1.5 Nhp xut dliu ....................................................................................................... 37 1.6 Mt schương trình đơn gin .................................................................................... 40 1.7 Cách thc hin các chương trình trên máy tính .......................................................... 42 BÀI TP CHƯƠNG 1 ..................................................................................................... 42 CHƯƠNG 2 - CÁC KIU DLIU................................................................................... 44 2.1 Các kiu dliu cơ bn .............................................................................................. 44 2.2 Hng ........................................................................................................................... 45 2.3 Biến............................................................................................................................. 47 2.4 Mng ........................................................................................................................... 48 2.5 Các phép toán trên các kiu ........................................................................................ 50 2.6 Mt shàm thường dùng............................................................................................ 54 BÀI TP CHƯƠNG 2 ..................................................................................................... 55 CHƯƠNG 3 - CÁC LNH ĐIU KHIN........................................................................... 56 3.1 Nhc li khái nim vcâu lnh và khi lnh .............................................................. 56 3.2. Lnh if ....................................................................................................................... 56 3.3 Lnh for ...................................................................................................................... 59 3.4 Lnh while .................................................................................................................. 61 3.5 Lnh do - while ........................................................................................................... 63 3.6 Lnh break .................................................................................................................. 64 3.7 Lnh continue ............................................................................................................. 64 BÀI TP CHƯƠNG 3 ..................................................................................................... 65 CHƯƠNG 4 - HÀM VÀ TCHC CHƯƠNG TRÌNH .................................................... 68 4.1 Tchc chương trình thành các hàm ......................................................................... 68 4.2 Tham skiu con tr.................................................................................................. 70 4.3 Đệ quy ........................................................................................................................ 77 BÀI TP CHƯƠNG 4 ..................................................................................................... 80

Upload: others

Post on 31-Aug-2019

5 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

2

MỤC LỤC PHẦN 1 ......................................................................................................................................4 ĐẠI CƯƠNG VỀ TIN HỌC ......................................................................................................4

CHƯƠNG 1 – NHỮNG KHÁI NIỆM CƠ BẢN VỀ TIN HỌC............................................5 1.1 Đối tượng nghiên cứu của Tin học ...............................................................................5 1.2 Thông tin và xử lý thông tin .........................................................................................5 1.3 Hệ đếm và biểu diễn thông tin trong máy tính .............................................................6 1.4 Nguyên lý của hệ xử lý thông tin tự động ....................................................................8 1.5 Cấu trúc máy tính .......................................................................................................10 1.6 Một số ứng dụng của Tin học.....................................................................................12

CHƯƠNG 2 – HỆ ĐIỀU HÀNH .........................................................................................14 2.1 Hệ điều hành MS-DOS...............................................................................................14 2.2 Hệ điều hành Windows ..............................................................................................16

CHƯƠNG 3 – THUẬT TOÁN ............................................................................................21 3.1 Khái niệm ...................................................................................................................21 3.2 Một số phương pháp biểu diễn thuật toán ..................................................................21 3.3 Các cấu trúc cơ bản của thuật toán .............................................................................23 3.4 Một số thuật toán giải một số bài toán đơn giản ........................................................26

PHẦN 2 ....................................................................................................................................32 NGÔN NGỮ LẬP TRÌNH C ...................................................................................................32

CHƯƠNG 1 - MỘT SỐ KHÁI NIỆM MỞ ĐẦU ................................................................33 1.1 Tập ký tự.....................................................................................................................33 1.2 Từ khóa.......................................................................................................................33 1.3 Tên..............................................................................................................................34 1.4 Một số khái niệm ........................................................................................................34 1.5 Nhập xuất dữ liệu .......................................................................................................37 1.6 Một số chương trình đơn giản ....................................................................................40 1.7 Cách thực hiện các chương trình trên máy tính..........................................................42 BÀI TẬP CHƯƠNG 1 .....................................................................................................42

CHƯƠNG 2 - CÁC KIỂU DỮ LIỆU...................................................................................44 2.1 Các kiểu dữ liệu cơ bản ..............................................................................................44 2.2 Hằng ...........................................................................................................................45 2.3 Biến.............................................................................................................................47 2.4 Mảng...........................................................................................................................48 2.5 Các phép toán trên các kiểu........................................................................................50 2.6 Một số hàm thường dùng............................................................................................54 BÀI TẬP CHƯƠNG 2 .....................................................................................................55

CHƯƠNG 3 - CÁC LỆNH ĐIỀU KHIỂN...........................................................................56 3.1 Nhắc lại khái niệm về câu lệnh và khối lệnh..............................................................56 3.2. Lệnh if .......................................................................................................................56 3.3 Lệnh for ......................................................................................................................59 3.4 Lệnh while ..................................................................................................................61 3.5 Lệnh do - while...........................................................................................................63 3.6 Lệnh break ..................................................................................................................64 3.7 Lệnh continue .............................................................................................................64 BÀI TẬP CHƯƠNG 3 .....................................................................................................65

CHƯƠNG 4 - HÀM VÀ TỔ CHỨC CHƯƠNG TRÌNH ....................................................68 4.1 Tổ chức chương trình thành các hàm .........................................................................68 4.2 Tham số kiểu con trỏ ..................................................................................................70 4.3 Đệ quy ........................................................................................................................77 BÀI TẬP CHƯƠNG 4 .....................................................................................................80

Page 2: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

3

CHƯƠNG 5 - CẤU TRÚC ..................................................................................................81 5.1 Định nghĩa cấu trúc và khai báo biến cấu trúc ...........................................................81 5.2 Kết hợp định nghĩa cấu trúc và khai báo biến cấu trúc ..............................................81 5.3 Sử dụng typedef để định nghĩa kiểu dữ liệu cấu trúc .................................................82 5.4 Truy cập các thành phần của cấu trúc.........................................................................83 5.5 Ví dụ minh hoạ ...........................................................................................................83 BÀI TẬP CHƯƠNG 5 .....................................................................................................86

Page 3: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

4

PHẦN 1

ĐẠI CƯƠNG VỀ TIN HỌC

Page 4: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

5

CHƯƠNG 1 – NHỮNG KHÁI NIỆM CƠ BẢN VỀ TIN HỌC

1.1 Đối tượng nghiên cứu của Tin học Tin học là ngành khoa học nghiên cứu về cấu trúc, tính chất và các quá trình xử lý thông

tin một cách tự động dựa trên các phương tiện kỹ thuật. Tin học là một ngành khoa học trẻ, mới hình thành và phát triển trong mấy thập kỷ qua. Đặc biệt từ đầu những năm 80 của thế kỷ trước, cùng với sự phát triển của máy vi tính, mạng máy tính và gần đây là mạng Internet, tin học đã phát triển rất mạnh và trở nên không thể thiếu trong hầu như mọi lĩnh vực của đời sống xã hội.

Tin học được sinh ra trên miền giáp danh của nhiều lĩnh vực khoa học. Hai ngành khoa học trực tiếp làm nền móng cho tin học là toán học và vật lý. Đặc trưng quan trọng của tin học là sự truyền và xử lý thông tin một cách tự động. Việc xử lý thông tin trước đây chưa đặt ra vấn đề tự động hóa và con người luôn gắn liền với mọi thao tác trong quá trình xử lý thông tin. Để đạt được phương thức tự động hóa phải có các phương tiện kỹ thuật, mà quan trọng nhất là máy tính điện tử (MTĐT). Phương tiện kỹ thuật vừa là công cụ vừa là đối tượng nghiên cứu của tin học.

Ngay từ khi ra đời, tin học đã phát triển theo hai bộ phận hợp thành chủ yếu là: bảo đảm toán học, thuật toán, chương trình (gọi là phần mềm) và các thiết bị tính toán, lưu trữ, truyền dẫn thông tin (gọi là phần cứng). Trong bản thân cả phần mềm và phần cứng lại có các lĩnh vực nghiên cứu chuyên sâu hơn về lý thuyết và ứng dụng. Mặc dù rất khó phân định chính xác các lĩnh vực nghiên cứu, ứng dụng của tin học, nhưng khi nói đến tin học, người ta thường đề cập đến:

- Kỹ thuật chế tạo máy tính

- Mạng máy tính

- Kỹ thuật lập trình

- Đảm bảo toán học cho máy tính và các hệ thống tính toán

- Thuật toán và độ phức tạp của thuật toán

- Cơ sở dữ liệu

- Trí tuệ nhân tạo

- . . .

1.2 Thông tin và xử lý thông tin Thông tin theo nghĩa thông thường của đời sống hàng ngày được hiểu như là sự thông

báo, cắt nghĩa, ... Thông tin tồn tại dưới nhiều dạng và được lưu trữ nhờ vật mang tin như tờ báo, quyển sách, băng ghi âm, đĩa từ, ...

Thông tin về một đối tượng là các dữ kiện về đối tượng đó. Thông tin có khả năng làm thay đổi sự hiểu biết của con người, là nguồn gốc của nhận thức. Trước thời điểm nhận thông tin, có một cái gì đó ta chưa biết, chưa xác định (bất định). Chẳng hạn ta biết sinh viên A học ở ĐH Giao thông vận tải nhưng không biết ở khoa nào, lớp nào thì việc tìm đến sinh viên A có một độ bất định nào đó. Bây giờ, giả sử biết thêm sinh viên A học ở khoa Công nghệ thông tin của trường, thì điều này đã làm giảm độ bất định ở trên. Như vậy tính bất định đã thay đổi khi nhận thêm thông tin.

Ta xét một ví dụ khác: Nếu biết A đã thi đạt kỳ thi học kỳ môn Tin học đại cương, nhưng chưa biết được bao nhiêu điểm thì việc xác định điểm của A có một độ bất định nào đó. Nếu

Page 5: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

6

biết thêm A đạt điểm 7 hoặc 8 thì lượng thông tin bổ sung này sẽ làm giảm độ bất định trên. Tính bất định của sự kiện lúc đầu thể hiện ở 1 trong 6 (điểm có thể là 5, 6, 7, 8, 9, 10) và lúc sau là 1 trong 2 (điểm có thể là 7 hoặc 8). Tính bất định gắn liền với khái niệm xác suất, xác suất càng nhỏ thì độ bất định càng lớn, hay nói cách khác, lượng thông tin tỷ lệ nghịch với xác suất của sự kiện.

Thông tin thường được biểu diễn qua các bộ ký hiệu. Ví dụ, ta có tập đối tượng X cần biểu diễn (tập các thí sinh chẳng hạn). Chọn một tập hữu hạn Y các chữ và số làm bảng chữ cái, ta gọi một dãy hữu hạn các chữ cái đó là một từ trên Y (ở đây là số báo danh). Với mỗi phần tử x ∈ X ta gán một từ y ∈Y và gọi là mã của x (Y gọi là bảng mã). Phép tạo mã tương ứng này cần đảm bảo tính chất với x1≠x2 (x1 , x2 ∈X) sẽ có y1≠y2 (y1 , y2 ∈ Y) là mã tương ứng của chúng. Khi biết mã số (số báo danh), bằng phép giải mã ta sẽ tìm được đối tượng tương ứng (thí sinh).

Thông tin đưa vào MTĐT (để lưu trữ, tính toán, ...) thực chất là dãy các tín hiệu nhị phân hay còn gọi là các bit (binary digit), nó tương ứng với các trạng thái của các mạch điện tử bên trong máy tính. Vì vậy, trong xử lý thông tin tự động, dạng mã quan trọng được dùng là mã nhị phân. Thông tin được mã hóa trên bảng chữ cái gồm 2 ký hiệu là chữ số 0 và chữ số 1.

Ví dụ, với bảng mã ASCII, là bộ mã tiêu chuẩn của Mỹ, mỗi ký tự (chữ cái, chữ số, ký tự đặc biệt) tương ứng với một mã 7 bit. Như vậy bảng mã với mỗi bit có 2 trạng thái cho phép mã hóa 27=128 ký tự. Với bảng mã ANSI, hay còn gọi là ASCII mở rộng, mỗi ký tự được mã hóa bằng 8 bit, và như vậy lượng ký tự có thể mã hóa được là 28=256 ký tự. Cuối những năm 80 của thế kỷ trước, bảng mã UNICODE được giới thiệu. Bảng mã này có thể sử dụng 16 bit để mã hóa một ký tự, nên lượng ký tự có thể mã hóa được là 216=65536 ký tự. Hiện nay UNICODE đã trở thành một tiêu chuẩn được chấp nhận rộng rãi vì nó có thể mã hóa được các ký tự của tất cả các ngôn ngữ trên thế giới.

1.3 Hệ đếm và biểu diễn thông tin trong máy tính Hệ đếm được hiểu như tập các ký hiệu và tập các qui tắc xác định dùng để biểu diễn và

tính giá trị các số. Trước hết hãy xét những hệ đếm quen thuộc, đại diện cho hai cách đếm là: hệ đếm La Mã (đếm không theo vị trí) và hệ đếm thập phân (đếm theo vị trí).

Hệ đếm La Mã: Mỗi ký hiệu biểu thị một giá trị (I=1, V=5, X=10, D=500, M=1000). Nó có các qui tắc, chẳng hạn: n ký hiệu đứng cạnh nhau cho biết ký hiệu đó được lặp lại n lần, ví dụ: II=2, III=3, XXX=30; hai ký hiệu trong đó ký hiệu lớn đứng trước biểu thị tổng của hai ký hiệu đó, ví dụ: VI=6, XI=11, ... Như vậy trong hệ đếm La Mã, mỗi ký hiệu chỉ đại diện cho một giá trị, không phụ thuộc vào vị trí của nó trong biểu diễn.

Hệ đếm thập phân: Sử dụng 10 ký hiệu (là các chữ số: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9). Qui tắc tính giá trị: giá trị của mỗi ký hiệu phụ thuộc vào bản thân ký hiệu đó và vị trí của nó trong biểu diễn. Ví dụ: trong số 555, chữ số 5 hàng đơn vị chỉ 5 đơn vị, chữ số 5 hàng chục chỉ 50 đơn vị (5*101), chữ số 5 hàng trăm chỉ 500 đơn vị (5*102). Số lượng các chữ số dùng trong hệ thập phân (10 chữ số) gọi là cơ số của hệ đếm. Số mũ của cơ số 10 xác định giá trị định lượng của mỗi đơn vị.

Hệ đếm thập phân chỉ là một trường hợp riêng khi chọn cơ số là 10. Tổng quát, bất kỳ một số nguyên b > 1 nào cũng đều có thể chọn làm cơ số. Lúc đó các ký hiệu của hệ đếm là 0, 1, 2, ..., b-1.

Trong tin học, các hệ đếm thường được sử dụng là: hệ cơ số 2 (hệ nhị phân) chỉ dùng 2 ký hiệu 0, 1, hệ cơ số 8 dùng các ký hiệu 0, 1, 2, 3, 4, 5, 6, 7 , hệ cơ số 16 dùng các ký hiệu 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F. Khi cần phân biệt số ở hệ đếm nào, ta có thể sử dụng cơ số làm chỉ số, ví dụ: 1012 , 58 , 516 .

Page 6: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

7

MTĐT chỉ có thể tác động trực tiếp với các số nhị phân, trong khi đó con người lại thường làm việc trên hệ thập phân. Vì thế cần phải có thuật toán để chuyển đổi số từ hệ đếm này sang hệ đếm khác. Để chuyển đổi số từ hệ đếm cơ số b1 sang hệ đếm cơ số b2 , người ta thường dùng hệ thập phân làm trung gian: chuyển số từ hệ đếm cơ số b1 sang hệ thập phân, sau đó chuyển tiếp số từ hệ thập phân sang hệ đếm cơ số b2.

1.3.1 Biến đổi số ở hệ đếm bất kỳ sang hệ thập phân: Cho số N= (dn-1dn-2...d1d0d-1d-2...d-m) ở hệ đếm cơ số b. Để tìm biểu diễn của N trong hệ

thập phân, ta tiến hành theo các bước:

- Viết N dưới dạng đa thức:

N = dn-1 bn-1 + dn-2 bn-2 + ... + d1 b1 + d0 b0 + d-1 b-1 + d-2 b-2 + ... + d-mb-m

- Sử dụng phép toán của hệ thập phân để tính giá trị đa thức.

Ví dụ:

1110,12 = 1.23 + 1.22 + 1.21 + 0.20 + 1.2-1 = 14,5

D3F,416 = D.162 + 3.161 + F.160 + 4.16-1

= 13.162 + 3.161 + 15.160 + 4.16-1= 3391,25

1.3.2 Biến đổi số ở hệ thập phân sang hệ đếm cơ số bất kỳ: Trước hết cần tách phần nguyên và phần thập phân (nếu có), rồi tiến hành biến đổi chúng

riêng biệt sang hệ đếm cơ số b. Sau đó bằng cách ghép nối các kết quả ta thu được giá trị cần tìm.

Để biến đổi phần nguyên N, ta chia nguyên nó cho b được thương số là N1 và số dư d1. Sau đó lại lấy N1 chia nguyên cho b, được thương số là N2 vào số dư là d2, ... Lặp lại quá trình đó đến khi thương số Nk=0, ta sẽ có kết quả cần tìm là (dk ... d2d1).

Ví dụ: 5210 = ?2 . Ta thực hiện theo thuật toán như sau:

Phép chia nguyên Thương số Số dư 52 : 2 26 0 26 : 2 13 0 13 : 2 6 1 6 : 2 3 0 3 : 2 1 1 1 : 2 0 1

Như vậy 5210 = 1101002

Ví dụ: 5850610 = ?16 . Ta thực hiện theo thuật toán như sau:

Phép chia nguyên Thương số Số dư 58506 : 16 3656 10 3656 : 16 228 8 228 : 16 14 4 14 : 16 0 14

Như vậy 5850610 = E48A16

Để biến đổi phần thập phân 0,M ta nhân nó với b, được phần nguyên của kết quả là d1, phần thập phân còn lại sau khi lấy kết quả trừ đi d1 là 0,M1. Sau đó lấy 0,M1 nhân với b, được phần nguyên của kết quả là d2, phần thập phân còn lại sau khi lấy kết quả trừ đi d2 là 0,M2, ...

Page 7: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

8

Tiếp tục lặp lại quá trình này, nó có kết thúc hoặc lặp vô hạn, khi đó tùy theo yêu cầu mà quyết định dừng khi nào. Ta sẽ có kết quả cần tìm là (0,d1d2d3 ...)

Ví dụ: 0,687510 = ?2

Phép nhân Kết quả Phần nguyên 0,6875 * 2 1,375 1 0,375 * 2 0,75 0 0,75 * 2 1,5 1 0,5 * 2 1,0 1

Như vậy: 0,687510 = 0,10112

Từ đây suy ra: 52,687510 = 110100,010112

Ví dụ: 0,843510 = ?16

Phép nhân Kết quả Phần nguyên 0,8435 * 16 13,496 13 0,496 * 16 7,936 7 0,936 * 16 14,976 14 0,5 * 16 15,616 15

... ... ...

Như vậy: 0,843510 = 0,D7EF...16

Từ đây suy ra: 58506,843510 = E48A,D7EF...16

1.3.3 Biểu diễn thông tin trong máy tính: MTĐT xử lý cả dữ liệu số và phi số, nhưng cả hai loại dữ liệu này khi đưa vào máy đều

là dãy các tín hiệu nhị phân, thường được thể hiện bằng các chữ số 0, 1 (gọi là các bit). Theo nghĩa đó MTĐT xử lý dữ liệu bằng số, và bit là đơn vị thông tin. Số được biểu diễn dưới dạng nhị phân chính là một dãy các bit liên tiếp. Các số, các ký hiệu, các lệnh máy được biểu diễn trong máy tính thông qua các dãy nhị phân với độ dài xác định, gọi là từ máy. Độ dài từ máy là đặc trưng của từng họ máy. Các độ dài từ máy thông dụng là 8, 16, 32, ... bit. Độ dài từ máy là xác định, do vậy dải số có thể biểu diễn được bên trong máy tính là hữu hạn.

1.4 Nguyên lý của hệ xử lý thông tin tự động

1.4.1 Nguyên lý làm việc của máy tính Von Neumann là người đề xuất ra nguyên lý làm việc của máy tính số, và nguyên lý này

vẫn được dùng làm cơ sở cho hầu hết các MTĐT hiện nay. Theo đó thì MTĐT làm việc theo chương trình có trong bộ nhớ của nó. Để đảm bảo nguyên tắc này, MTĐT cần phải gồm đủ 5 thành phần cơ bản: bộ nhớ để ghi thông tin, bộ số học logic để thực hiện các tính toán, bộ điều khiển, các thiết bị nhập và thiết bị xuất dữ liệu.

Máy tính phải thi hành được các lệnh của người dùng đưa vào. Một chương trình thực chất là một chuỗi các lệnh, nhằm thực hiện những công việc nào đó. Một tập hợp các qui ước để viết nên các dòng lệnh đưa vào máy, cho máy nhận diện và thi hành gọi là ngôn ngữ. Ngôn ngữ được thực hiện trực tiếp dựa trên qui ước của các mạch điện tử trong máy gọi là ngôn ngữ máy. Mỗi loại máy có một ngôn ngữ riêng. Ngôn ngữ máy có ưu điểm là máy hiểu được ngay, nhưng nó quá khác biệt so với ngôn ngữ của con người, nên việc xây dựng, kiểm thử chương trình rất khó khăn.

Page 8: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

9

Từ đầu những năm 60 của thế kỷ trước đã bắt đầu xuất hiện những ngôn ngữ lập trình (NNLT) bậc cao. Gọi là ngôn ngữ bậc cao vì các ngôn ngữ này thường sử dụng những từ khóa dựa trên tiếng Anh, có cấu trúc gần gũi hơn với ngôn ngữ của con người. Các NNLT luôn không ngừng phát triển, các NNLT mới luôn xuất hiện, ngày càng hoàn thiện hơn để đáp ứng những nhu cầu ngày một cao về qui mô, chất lượng, độ tin cậy, ... của phần mềm. Trên thực tế, sự phát triển của các ngôn ngữ lập trình gắn liền với sự phát triển của công nghệ phần mềm và của tin học. Một chương trình viết bằng một NNLT nào đó gọi là chương trình nguồn. Chúng ta cần phải có một chương trình dịch cho NNLT đó để dịch các chương trình nguồn bằng NNLT này ra ngôn ngữ máy, khi đó MTĐT mới có thể hiểu và thực hiện.

Để tự động hóa một số công việc của người vận hành máy, cũng như quản lý, khai thác các thiết bị phần cứng hiệu quả hơn, từ những năm 1960 người ta đã xây dựng các hệ điều hành cho máy tính. Ngày nay nói đến một hệ thống máy tính, ta phải hiểu đó là thiết bị phần cứng và hệ điều hành cài đặt trên nó. Các hệ điều hành ngày càng phát triển để đáp ứng nhu cầu không có giới hạn của người dùng và sự thay đổi, tiến bộ liên tục của phần cứng. Một số hệ điều hành tiêu biểu hiện nay là: MS-DOS, Windows, Linux, ...

1.4.2 Lịch sử phát triển của máy tính Lịch sử kỹ thuật tính toán đã có từ lâu đời. Công cụ tính toán của con người bắt đầu từ

những thứ rất thô sơ như ngón tay, hòn sỏi, rồi đến bàn tính gảy, máy tính cơ, máy tính cơ điện. Đến năm 1946, việc chế tạo thành công máy tính ENIAC tại Mỹ được coi như mốc đánh dấu sự ra đời của MTĐT đầu tiên trên thế giới. Từ khi có MTĐT, kỹ thuật tính toán đã chuyển sang một giai đoạn mới.

Năm Sự kiện Trước CN Bàn tính gảy ở Trung Quốc

1642 Máy tính cơ, làm được phép cộng (Blaise Passcal) 1670 Máy tính cơ, làm được cộng,trừ,nhân,chia,căn bậc 2 (Leibnitz) 1842 Máy tính có thể lập trình để tính tự động (Charles Babbage) 1890 Herman Hollerith thiết kế hệ thống có thể lưu thông tin trên bìa đục

lỗ, đọc ra bằng tế bào quang điện, thành lập công ty IBM 1946 Máy ENIAC (Eckert, Mauchly), gồm 18000 bóng chân không, giá

500000$ 1958 Máy tính đầu tiên dùng bóng bán dẫn transitor (IBM 7090) 1964 Máy tính đầu tiên dùng mạch tích hợp IC (IBM 360) 1976 Hãng DEC giới thiệu máy vi tính VAX 11/780 1981 Hãng IBM đưa ra máy vi tính IBM PC

Một số mốc trong lịch sử phát triển máy tính

Máy tính điện tử ENIAC

Page 9: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

10

Sự phát triển của MTĐT từ năm 1946 đến nay đã trải qua nhiều thế hệ. Mỗi thế hệ là một bước phát triển lớn và được xác định căn cứ vào tiêu chuẩn kỹ thuật và mức độ phong phú của phần mềm.

Thế hệ thứ nhất (khoảng 1946-1955): Dùng bóng đèn điện tử, độ tin cậy thấp, tiêu hao nhiều năng lượng, tốc độ tính toán chỉ từ vài nghìn đến vài chục nghìn phép tính một giây. Phần mềm chưa phát triển, chủ yếu dùng ngôn ngữ máy để lập trình. Thế hệ MTĐT này thường chỉ dùng trong mục đích nghiên cứu khoa học.

Thế hệ thứ hai (khoảng 1955-1965): Dùng bóng bán dẫn thay đèn điện tử, tiêu thụ năng lượng ít hơn, bộ nhớ có dung lượng lớn hơn, tốc độ khoảng vài chục nghìn phép tính một giây. Đã bắt đầu xuất hiện một số NNLT bậc cao như ALGOL, FORTRAN, COBOL, ... Về ứng dụng, đã bắt đầu dùng vào các mục đích tính toán trong quản lý kinh tế, thống kê, ...

Thế hệ thứ ba (khoảng 1965-1980): Dùng mạch tích hợp thay cho bóng bán dẫn, tốc độ tính toán lên đến hàng triệu phép tính một giây. Các tiến bộ khác phải kể đến: xuất hiện nhiều hệ điều hành tốt hơn, có khả năng sử dụng bộ nhớ ảo, đa chương trình, các thiết bị ngoại vi phát triển rất mạnh mẽ. Phần mềm phát triển đa dạng, ứng dụng trong nhiều lĩnh vực.

Thế hệ thứ tư (khoảng từ sau 1980): Dùng mạch tích hợp cỡ lớn VLSI, sự phát triển của mạng máy tính, các kiến trúc song song, tốc độ tính toán lên đến nhiều triệu, thậm chí hàng tỷ phép tính một giây. Về ứng dụng, đã được sử dụng trong tất cả mọi lĩnh vực.

Dựa trên kích thước, kiến trúc vật lý, tính năng, tốc độ và quy mô xử lý, người ta phân chia MTĐT thành các loại: Máy tính lớn (mainfraim), máy tính mini (mini computer) và máy vi tính (micro computer). Các máy tính lớn có giá thành rất đắt, thường được sử dụng vào các lĩnh vực quan trọng, đòi hỏi nhiều tính toán phức tạp. Thuộc loại này có thể kể đến các máy Cray, IBM 3090/300, Gen/Blue, ... Các máy tính mini có giá thành vừa phải, thích hợp cho các mục đích chuyên dùng. Một số máy loại này là PDP, HP-300, IBM 360, Sun 4, ... Các máy vi tính xuất hiện từ cuối những năm 70 của thế kỷ 20. Các máy vi tính có kích thước nhỏ, giá thành rẻ hơn các loại máy trên, nên đã dần được sử dụng rộng rãi, kể cả trong những công ty nhỏ, trường học, hộ gia đình hay chỉ cho cá nhân. Chính vì thế phiên bản máy vi tính đầu tiên của hãng IBM được gọi là máy tính cá nhân (Personal Computer, viết tắt là PC). Máy vi tính của IBM chiếm thị phần lớn nhất vào đầu những năm 1980, nên dần dần người ta gần như đồng nghĩa từ PC với từ máy vi tính.

Cần lưu ý rằng cách phân loại trên chỉ là tương đối, cần quan tâm đến cả yếu tố thời gian. Nhiều máy vi tính ngày nay có tính năng sử dụng vượt xa các máy tính lớn vào những năm 1970.

1.5 Cấu trúc máy tính Về cấu trúc logic, một MTĐT gồm các bộ phận chính là: bộ nhớ, bộ số học -logic, bộ

điều khiển, các thiết bị nhập/ xuất dữ liệu, và các đường truyền dẫn. Về tổ chức vật lý, các bộ phận này đóng gói thành các thiết bị sau:

- Bo mạch chủ (Mainboard hoặc Motherboard)

- Bộ xử lý trung tâm (Center Processing Unit, viết tắt là CPU)

- Bộ nhớ: gồm bộ nhớ trong (ROM, RAM) và bộ nhớ ngoài hay còn gọi là các thiết bị lưu trữ (đĩa từ, đĩa CD, ...)

- Đường truyền (Bus) và các cổng giao tiếp

- Bộ nguồn

- Các thiết bị ngoại vi: gồm các thiết bị nhập dữ liệu (bàn phím, chuột, ...), các thiết bị xuất dữ liệu (màn hình, máy in, máy vẽ, ...), ...

Page 10: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

11

Máy vi tính Máy tính xách tay (laptop)

Thùng máy (case): Hầu hết các thiết bị của MTĐT kể ở trên đều được đặt bên trong thùng máy, trừ một số

thiết bị ngoại vi. Về hình thức, thường có 2 kiểu thùng máy: đặt đứng và đặt nằm ngang. Chú ý rằng nhiều người quen gọi cả thùng máy là CPU, gọi như vậy là sai vì CPU chỉ là bộ xử lý trung tâm gắn trên bo mạch chủ, đặt bên trong thùng máy.

Bo mạch chủ: Là thành phần rất quan trọng trong MTĐT, kết nối các bộ phận của máy tính với nhau.

Tất cả các thành phần của MTĐT đều được cắm trực tiếp, hoặc gián tiếp (thông qua cáp) vào bo mạch chủ. Bo mạch chủ gồm các thành phần chính: ổ cắm bộ xử lý trung tâm (để cắm CPU), rãnh cắm bộ nhớ trong (để cắm các thanh RAM), BIOS, các rãnh cắm cho các thiết bị ngoại vi (để cắm cạc màn hình, cạc mạng, ...), các cổng giao tiếp với các thiết bị ngoại vi, ...

Bên trong máy vi tính

Bộ xử lý trung tâm (CPU): Là bộ não của MTĐT, và có thể nói sức mạnh của máy tính phụ thuộc chủ yếu vào khả

năng tính toán của CPU. Bộ xử lý trung tâm bao gồm bộ số học – logic, bộ điều khiển và các thanh ghi. Bộ số học – logic có chức năng thực hiện các phép tính số học cơ bản và các phép tính logic. Bộ điều khiển có chức năng tìm nạp lệnh từ bộ nhớ, điều khiển các bước thực hiện của chương trình. Còn các thanh ghi thực chất là bộ nhớ tốc độ cao, mỗi thanh ghi có chức năng riêng.

CPU có một bộ phận tạo ra xung nhịp để điều khiển hoạt động của nó và đồng bộ sự hoạt động của các bộ phận khác trong toàn hệ thống máy tính. Tốc độ CPU chính là thể hiện nhịp đồng hồ này, đo bằng megaherz (MHz). Tốc độ càng cao tức là máy tính hoạt động càng nhanh.

Page 11: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

12

Hầu hết các CPU sử dụng hiện nay được sản xuất bởi các hãng của Mỹ là Intel, AMD, Motorola.

Bộ xử lý trung tâm (CPU)

Bộ nhớ Bộ nhớ dùng để lưu trữ thông tin. Đơn vị để đo lượng thông tin là byte (viết tắt là B).

Một byte thực chất là một dãy các bit liên tiếp (8 bit). Để lưu trữ một ký tự trong bộ nhớ, ta cần 1 byte. Trong thực tế, thường sử dụng một số đơn vị là bội số của byte là: kylobyte (viết tắt là KB, 1 KB = 210 B), megabyte (viết tắt là MB, 1 MB = 210 KB), gigabyte (viết tắt là GB, 1 GB = 210 MB), tetrabyte (viết tắt là TB, 1 TB = 210 GB).

Bộ nhớ trong gồm bộ nhớ chỉ đọc (Read Only Memory, viết tắt là ROM) và bộ nhớ truy nhập ngẫu nhiên (Random Access Memory, viết tắt là RAM). ROM chứa những số liệu và chương trình rất cơ bản để máy tính có thể khởi động và làm việc. ROM được các hãng sản xuất máy tính ghi sẵn, nó không bị mất đi khi tắt máy nhưng ta không thể thay đổi dữ liệu trong ROM.

Trên thực tế, khi nói đến bộ nhớ của máy tính người ta thường ngầm hiểu là RAM. RAM dùng để lưu trữ chương trình tạm thời trong khi máy đang làm việc. Chúng ta có thể đọc, ghi, sửa xóa dữ liệu trong RAM, nhưng do đọc ghi bằng điện nên khi tắt máy hoặc mất điện thì mọi thông tin lưu trong đó sẽ bị mất hết. Bộ nhớ RAM thường được tổ chức thành từng băng (gòn gọi là thanh RAM), có dung lượng 16 MB, 32 MB, 64 MB, ... Các thanh RAM được cắm trên bo mạch chủ. Trên bo mạch chủ có thể cắm được nhiều thanh RAM.

Bộ nhớ RAM có tốc độ truy cập cao, nhưng không lưu được dữ liệu sau khi tắt máy, vì thế những dữ liệu muốn lưu trữ lâu dài cần phải ghi vào các thiết bị lưu trữ. Các thiết bị lưu trữ hiện nay rất đa dạng, gồm: băng từ, các loại đĩa từ (đĩa mềm, đĩa cứng), các loại đĩa quang (đĩa CD, đĩa DVD), đĩa USB (USB Flash Disk), ...

Bộ nhớ RAM

Bộ nguồn Bộ nguồn chuyển đổi điện lưới xoay chiều thành dòng điện một chiều điện áp thấp

(thường khoảng 3v đến 12v) để cung cấp cho mọi bộ phận trong máy tính.

1.6 Một số ứng dụng của Tin học

Page 12: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

13

Tin học ngày nay đã trở thành động lực sản xuất của xã hội. MTĐT khác các máy móc khác ở chỗ nó gia công thông tin chứ không gia công nguyên vật liệu. Sản phẩm của MTĐT là những thông tin hướng dẫn các hoạt động thực tiễn. Ban đầu tin học chủ yếu phục vụ các vấn đề khoa học kỹ thuật, người sử dụng khi đó cũng chủ yếu là những nhà chuyên môn trong các lĩnh vực đó. Sự phát triển nhanh chóng của MTĐT và mạng Internet cho phép tin học xâm nhập vào mọi lĩnh vực. Do sự phát triển nhanh, mạnh và rộng khắp của tin học nên sẽ rất khó để nói hết được những ứng dụng của nó, dưới đây chỉ tóm lược một số phần mềm ứng dụng cơ bản, phổ biến hiện nay.

Phầm mềm toán học: - Mathematica: là phần mềm cho phép tính toán từ đơn giản như các tính toán số

học đến phức tạp hơn, như: các bài toán về đa thức, đại số tuyến tính, tìm giới hạn, tìm đạo hàm, tính tích phân, giải phương trình vi phân, khai triển Taylor, ... Ngoài ta phần mềm này còn cho phép vẽ biểu đồ và đồ thị.

- Matlab: phần mềm này có thể thực hiện được các tính toán tương tự như Mathematica. Ngoài ra Matlab còn dùng kỹ thuật đồ họa 3 chiều để thiết kế các mô hình trong khoa học kỹ thuật hoặc làm các đoạn phim hoạt hình đơn giản.

Phần mềm văn phòng: Bộ phần mềm văn phòng nổi tiếng nhất, có mặt ở hầu hết các máy tính hiện nay là

Microsoft Office. Trong bộ phần mềm này có những chương trình:

- Word: để soạn thảo, lưu trữ, sửa chữa, in ấn các văn bản.

- Excel: để tạo lập, lưu trữ, sửa chữa, in ấn các bảng tính, ví dụ: bảng lương, bảng thống kê bán hàng, ...

- PowerPoint: để tạo lập các bản báo cáo (slide) và trình bày báo cáo.

- Access: là một hệ quản trị cơ sở dữ liệu.

- FrontPage: để xây dựng các trang Web.

- Outlook: để trao đổi, quản lý thư điện tử, lập lịch làm việc, ...

Phần mềm thiết kế:

- AutoCAD: để tạo lập và quản lý các bản vẽ kỹ thuật.

- Sap: để tính toán kế cấu và ổn định lực học.

- 3D Max: là một công cụ mạnh, có sự hỗ trợ của multimedia để phục vụ cho công tác thiết kế.

Page 13: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

14

CHƯƠNG 2 – HỆ ĐIỀU HÀNH

Hệ điều hành (HĐH) là tập hợp các chương trình đặc biệt dùng để tổ chức, phối hợp hoạt động của các thiết bị phần cứng, tạo ra môi trường làm việc cho các chương trình ứng dụng và giao diện với người dùng. HĐH là một phần mềm không thể thiếu trên bất kỳ máy tính nào. HĐH tự động được tải vào bộ nhớ sau khi khởi động máy tính.

Hiện nay có rất nhiều HĐH cho các hệ máy khác nhau. Số lượng các HĐH cho máy vi tính cũng không ít, nhưng trên thế giới cũng như ở Việt Nam từ trước tới nay sử dụng phổ biến các HĐH của hãng Microsoft là MS-DOS và Windows.

2.1 Hệ điều hành MS-DOS Một trong những HĐH đầu tiên cho các máy vi tính là MS-DOS (Microsoft Disk

Operating System), thường gọi tắt là DOS. MS-DOS đã phát triển qua nhiều phiên bản từ 1.0 đến 6.0 rồi dần được thay thế bởi HĐH Windows. Tuy nhiên, nhiều tư tưởng và qui định của DOS vẫn được áp dụng trong Windows. Ngoài ra, có nhiều phần mềm được viết từ khi HĐH Windows chưa phổ biến, chúng chỉ chạy được trên nền DOS, nên ngay cả trong Windows vẫn cho phép chúng ta tạo ra môi trường DOS ảo, giống như khi dùng MS-DOS để chạy được các phần mềm cũ.

2.1.1 Một số khái niệm Tệp tin (file): là tập hợp các thông tin được tổ chức lưu trữ thành một đơn vị độc lập. Có

hai loại tệp tin là: tệp tin dữ liệu và tệp tin chương trình. Mỗi tệp tin có một tên, gồm 2 phần, được phân cách bằng dấu chấm (.) là: phần tên và phần mở rộng. Đặt tên tệp tin trên DOS phải tuân theo một số qui tắc: phần tên không quá 8 ký tự, phần mở rộng không quá 3 ký tự và không chứa dấu cách.

Thư mục: Để tạo sự dễ dàng và thuận lợi trong việc quản lý và truy xuất đến các tệp tin, DOS cho phép tổ chức các tệp tin thành từng nhóm, gọi là thư mục. Có thể ví thư mục như những tủ hồ sơ để chứa hồ sơ là các tệp tin. Trong thư mục có thể tạo những thư mục con của nó. Thư mục mà bên trong không có thư mục con cũng không có tệp tin nào thì gọi là thư mục rỗng. Thư mục hiện hành là thư mục mà ta đang làm việc, nó được thể hiện trên dấu nhắc của DOS. Tên thư mục cũng không được đặt quá 8 ký tự.

Dựa trên khái niệm thư mục, DOS tổ chức dữ liệu trên đĩa một cách logic dưới dạng hình cây, với “gốc” là ổ đĩa, rồi phân chia tiếp ra các thư mục, từ các thư mục có thể đến các thư mục con của nó, ... và cuối cùng “lá” là các tệp tin. Cách tổ chức dữ liệu trên đĩa của HĐH Windows cũng tương tự như vậy, chỉ có điều trên Windows có thể đặt tên tệp tin và tên thư mục với độ dài lớn hơn, có thể bao gồm cả dấu cách.

Đường dẫn: Để truy cập đến một thư mục hay một tệp tin ta phải chỉ ra nó nằm ở đâu tính từ thư mục hiện hành. Các thông tin này được trình bày bằng cách liệt kê tên các thư mục và tệp tin, giữa hai thư mục hoặc tệp tin sử dụng dấu sổ chéo (\). Dãy thư mục và tệp tin đó gọi là đường dẫn. Nếu phải xác định thư mục hoặc tệp tin ở ổ đĩa khác với ổ đĩa hiện hành thì cần chỉ ra tên ổ đĩa, kèm theo dấu hai chấm (:). Tên ổ đĩa thường ký hiệu A cho ổ đĩa mềm, C, D cho ổ đĩa cứng, ...

Ví dụ một đường dẫn: C:\GIAOTRINH\THDC\CHUONG1.DOC

Các ký tự đại diện: thường được sử dụng khi phải làm việc với nhiều tệp tin có chung một tính chất nào đó. Có hai loại ký tự đại diện là: ‘ ? ‘ đại diện cho 1 ký tự tại vị trí nó đứng và ‘ * ‘ đại diện cho nhiều ký tự kể từ vị trí nó đứng.

Page 14: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

15

2.1.2 Một số qui ước Một lệnh của DOS được viết bắt đầu từ dấu nhắc của DOS trên màn hình. Giữa phần lệnh

và phần thông tin phía sau phải có ít nhất một dấu cách. Trong lệnh của DOS không phân biệt chữ hoa và chữ thường. Sau khi viết xong lệnh, gõ phím Enter để thực hiện lệnh đó.

Trong cách viết lệnh sau đây, phần đặt giữa dấu < và dấu > là bắt buộc phải có, nếu không lệnh sẽ sai cú pháp, còn phần đặt giữa dấu [ và ] là phần lựa chọn, tùy theo yêu cầu mà có cần sử dụng hay không.

2.1.3 Một số lệnh làm việc với thư mục: 1) Tạo thư mục mới:

MD [đường dẫn] <tên thư mục> <ENTER>

Trong đó: [đường dẫn] là tên ổ đĩa, tên các thư mục để xác định thư mục cần làm việc, tức là thư mục mà ta sẽ tạo thư mục mới trong nó, <tên thư mục> là tên thư mục mới cần tạo, <ENTER> là gõ phím Enter trên bàn phím.

Ví dụ trên ổ đĩa C hiện hành có thư mục GIAOTRINH, cần tạo một thư mục mới có tên VANPHONG:

MD GIAOTRINH\VANPHONG <ENTER>

2) Xóa một thư mục rỗng:

RD [đường dẫn] <tên thư mục> <ENTER>

3) Chuyển đến một thư mục:

CD [đường dẫn] <tên thư mục> <ENTER>

Thư mục sau khi được chuyển đến sẽ trở thành thư mục hiện hành.

Chuyển đến thư mục cha:

CD .. <ENTER>

Chuyển đến thư mục gốc:

CD\ <ENTER>

4) Xem nội dung thư mục:

DIR [đường dẫn] [tên thư mục] [/p] <ENTER>

Nếu chỉ dùng DIR thì ta sẽ xem được nội dung của thư mục hiện hành: nó có những thư mục con nào, tệp tin nào, kích thước từng tệp tin là bao nhiêu byte. Tham số /p để xem từng trang màn hình, dùng khi số lượng tệp tin của thư mục cần xem lớn.

2.1.4 Một số lệnh làm việc với tệp tin

1) Xóa tệp tin:

DEL [đường dẫn] <tên tệp tin> <ENTER>

Để xác định tên tệp tin cần chỉ rõ tên và phần mở rộng. Có thể sử dụng các ký tự đại diện để xóa cùng lúc nhiều tệp tin có chung những tính chất nào đó.

Ví dụ: xóa tất cả các tệp tin có phần mở rộng là TMP trong thư mục THDC

DEL GIAOTRINH\THDC\*.TMP <ENTER>

Page 15: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

16

2) Đổi tên tệp tin:

REN [đường dẫn] <tên tệp tin> <tên mới> <ENTER>

3) Sao chép tệp tin:

COPY <Nguồn> <Đích> <ENTER>

Trong đó phần <Nguồn> cần chỉ ra các tệp tin cần sao chép và phần <Đích> chỉ ra ổ đĩa hoặc thư mục sẽ sao chép các tệp tin trên vào.

2.2 Hệ điều hành Windows

2.2.1 Một số đặc điểm HĐH Windows là bước phát triển tiếp theo của MS-DOS. Khác biệt dễ nhận thấy nhất

của Windows so với DOS là nó có giao diện đồ họa, với các thực đơn (menu), cửa sổ và biểu tượng. Các thao tác trên Windows rất trực quan và dễ dàng, người sử dụng không cần phải nhớ và gõ những dòng lệnh như trên DOS. Windows đã có một quá trình phát triển khá dài, từ giữa những năm 80 của thế kỷ 20, dần dần thay thế DOS và trở thành HĐH được sử dụng nhiều nhất trên thế giới.

Những phiên bản được sử dụng rộng rãi đầu tiên là Windows 3.0 và Windows 3.1. Các phiên bản được sử dụng phổ biến hiện nay là Windows 98, Windows 2000, Windows XP. Nếu máy tính đã cài đặt HĐH Windows, sau khi khởi động máy, Windows sẽ tự động nạp và chạy.

Sau khi đăng nhập, sẽ xuất hiện màn hình nền (desktop) của Windows (các ví dụ ở đây là trên phiên bản Windows XP). Mỗi biểu tượng trên màn hình thường đại diện cho một chương trình. Muốn thực hiện chương trình nào ta nháy đúp chuột vào biểu tượng đó. Chúng ta cũng có thể tạo các biểu tượng (shortcut) trên màn hình cho bất kỳ tệp tin hay thư mục nào cần thường xuyên dùng tới. Thanh tác vụ (taskbar) phía dưới màn hình cho biết các ứng dụng nào đang thực hiện.

Nút Start chứa đựng nhiều chức năng quan trọng của Windows. Trong Start, chọn All Programs ta sẽ có danh sách các chương trình đã cài đặt trên máy, muốn chạy chương trình nào chỉ cần bấm chuột vào biểu tượng tương ứng. Để tắt máy chọn Turn Off Computer --> Turn Off, để khởi động lại máy chọn Turn Off Computer --> Restart.

Page 16: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

17

Màn hình desktop của Windows XP

Sau khi bấm chọn nút Start Sau khi chọn All Programs

Page 17: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

18

Sau khi chọn Log Off Sau khi chọn Turn Off Computer

Con chuột là thiết bị giao tiếp chủ yếu dùng trong giao diện đồ họa. Con chuột thường có hai phím: phím trái và phím phải. Một số thao tác cơ bản với chuột là:

- Bấm chuột (hoặc còn gọi là nháy chuột, kích đơn, ... ) là thao tác ấn vào nút trái chuột, dùng để chọn một đối tượng nào đó.

- Bấm chuột phải là thao tác ấn vào nút phải chuột, thường dùng để kích hoạt bảng chọn tức thời (bảng chọn gồm những chức năng nào còn phụ thuộc vào ngữ cảnh).

- Bấm đúp chuột (hoặc còn gọi là nháy kép, kích đúp, ...) là thao tác bấm nhanh 2 lần liên tiếp phím trái chuột, thường dùng để kích hoạt một đối tượng nào đó.

- Thao tác kéo-thả: bấm và giữ phím trái chuột, kéo chuột tới vị trí dự định, nhả phím bấm ra. Thao tác này dùng để di chuyển vị trí hay thay đổi kích thước một đối tượng.

Bảng chọn tức thời

Để thực hiện các công tác quản lý tệp tin, ta cần mở chương trình Windows Explorer,

bằng cách nháy đúp vào biểu tượng trên màn hình desktop, hoặc bấm tổ hợp phím tắt: - E.

Page 18: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

19

Windows Explorer

2.2.2 Các thao tác trong Windows Explorer

Hiển thị nội dung: Phía bên trái màn hình Windows Explorer là tổ chức thư mục, cách tổ chức này cũng

giống như ở DOS. Khi chọn một thư mục nào đó (bằng cách bấm chuột vào nó) thì danh sách các tệp tin và thư mục con của nó xuất hiện ở bên phải màn hình. Ta có thể sắp xếp và xem các tệp tin này theo nhiều cách khác nhau (theo tên, theo kiểu, ...) bằng cách bấm chuột phải ở màn hình bên phải, chọn Arrange Icons By, sau đó chọn cách sắp xếp tương ứng.

Chọn cách sắp xếp các biểu tượng tệp tin

Đóng mở thư mục:

Để mở một thư mục: bấm chọn biểu tượng dấu cộng , để đóng một thư mục: bấm chọn biểu tượng dấu trừ .

Chọn đối tượng (tệp tin và thư mục): Để chọn một tệp tin (hoặc thư mục) ta bấm chuột vào nó, để chọn nhiều tệp tin liền nhau

ta bấm chuột vào tệp tin đầu, giữ phím Shift rồi bấm chuột vào tệp tin cuối, để chọn nhiều tệp tin không liền nhau, ta giữ phím Ctrl rồi lần lượt bấm chọn các tệp tin.

Page 19: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

20

Sao chép đối tượng (các tệp tin và thư mục từ thư mục nguồn sang thư mục đích): Tìm đến thư mục nguồn, nơi chứa đối tượng. Đánh dấu chọn đối tượng cần sao chép.

Bấm chuột phải để mở bảng chọn tức thời, chọn Copy. Cuối cùng tìm đến thư mục đích, bấm chuột phải, chọn Paste trên bảng chọn tức thời. Nếu muốn thay vì sao chép, ta chuyển đối tượng từ thư mục nguồn sang thư mục đích (đối tượng đó không còn trong thư mục nguồn), chỉ việc thay Copy bằng Cut.

Bảng chọn khi Copy Bảng chọn khi Paste

Đổi tên tệp tin, thư mục: Chọn một đối tượng (tệp tin hoặc thư mục), bấm chuột phải vào đối tượng, chọn chức

năng Rename trong bảng chọn, cuối cùng gõ tên mới.

Xóa tệp tin, thư mục: Chọn một đối tượng (tệp tin hoặc thư mục), bấm chuột phải vào đối tượng, chọn chức

năng Delete trong bảng chọn hoặc gõ phím Delete trên bàn phím. Chú ý rằng các tệp tin, thư mục sau khi thực hiện các thao tác trên không bị xóa hẳn, mà chỉ bị đưa vào thùng rác. Nếu muốn phục hồi ta chỉ cần vào thùng rác, chọn các tệp tin, thư mục cần phục hồi, bấm chuột phải, chọn Restore. Nếu muốn xóa hẳn tệp tin, thư mục nào, thì ta cần giữ phím Shift khi chọn chức năng Delete.

Biểu tượng thùng rác

Thao tác trong Windows Explorer chủ yếu sử dụng chuột, ngoài các thao tác đơn giản, nên tận dụng thêm khả năng kéo-thả. Chẳng hạn để sao chép các tệp tin vào một thư mục nào đó, ta có thể đánh dấu chọn các tệp tin đó rồi kéo và thả vào thư mục đích. Để xóa các tệp tin, ta có thể bấm chọn các tệp tin đó, rồi kéo và thả vào biểu tượng thùng rác.

Chúng tôi chỉ giới thiệu ở đây một số kiến thức cơ bản nhất, vì các khả năng của HĐH Windows rất phong phú, không thể đề cập hết trong giáo trình này. Tuy nhiên với giao diện đồ họa, trực quan, việc tự học và làm chủ các thao tác, khai thác các chức năng khác của Windows sau khi đã nắm được những kiến thức cơ bản là hoàn toàn không khó.

Page 20: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

21

CHƯƠNG 3 – THUẬT TOÁN

3.1 Khái niệm Thuât toán là một dãy các quy tắc, nhằm xác định một dãy các thao tác trên các đối

tượng (dữ liệu đầu vào) sao cho sau một số hữu hạn bước thực hiện các thao tác đó ta đạt được mục tiêu cần làm (dữ liệu ra là kết quả bài toán).

Ví dụ: Thuật toán tìm ước số chung lớn nhất (USCLN) của hai số nguyên dương a,b.

- Input: a,b hai số nguyên

- Output: ƯSCLN của a, b

Có thể mô tả thuật toán này như sau:

Bước 1: Tìm số dư r của phép chia a cho b

Bước 2: Kiểm tra:

- Nếu r = 0 thì thông báo b là USCLN và kết thúc

- Nếu r<>0 thì thực hiện đặt a=b, b=r rồi quay lại làm lại Bước 1

Thuật toán trên gồm các thao tác tính số dư r, kiểm tra r<>0?, nếu r<>0 đặt a=b, b=r.

Các đặc trưng cơ bản của thuật toán

- Thuật toán phải có tính dừng: Thuật toán phải kết thúc sau một số hữu hạn bước.

- Tính xác định: Ở mỗi bước các thao tác phải rõ ràng, không gây nhập nhằng, tùy chọn.

- Đại lượng vào: Mỗi thuật toán phải có một hoặc nhiều dữ liệu đầu vào

- Đại lượng ra: Sau khi kết thúc thuật toán ta có thê thu được một số đại lượng ra là kết quả của bài toán.

- Tính hiệu quả: Mỗi bài toán có thể có nhiều thuật toán khác nhau để giải. Một thuật toán là tốt thì nó phải đơn giản, tiết kiệm bộ nhớ và thời gian thực hiện.

- Tính phổ dụng: Thuật toán có thể giải được một số bài toán trong một lớp bài toán.

- Tính hình thức hóa: Thuật toán phải có thể hình thức được và cài đặt được trên máy tính.

3.2 Một số phương pháp biểu diễn thuật toán Máy tính được sử dung như là một công cụ để hỗ trợ con người giải quyết các bài toán

trong thực tế. Bản thân máy tính chỉ là một vật vô chi vô giác, không có tư duy. Do đó, bản thân nó không thể tự giải các bài toán trong thực tế được, mà nó chỉ có thể thực hiện được các lệnh, do con người bảo nó làm thông qua một ngôn ngữ lập trình. Vì vậy để máy có thể giúp chúng ta giải một bài toán nào đó thì ta cần phải cài đặt thuật toán giải bài toán đó cho máy, theo đó máy thực hiện giải bài toán. Để cài đặt thuật toán cho máy người cài đặt phải có thuật toán giải bài toán đó.

Có nhiều cách biểu diễn thuật toán như đặc tả tự nhiên (liệt kê từng bước), sơ đồ khối, giả mã, …. Ở đây ta làm quen với một số cách biểu diễn thuật toán thông dụng

3.2.1 Đặc tả tự nhiên (Liệt kê từng bước)

Page 21: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

22

Sử dụng ngôn ngữ tự nhiên để biểu diễn thuật toán bằng cách chỉ ra từng bước cần thực hiện của thuật toán.

Ví dụ: Thuật toán giải phương trình bậc 2: ax2+bx+c=0 hệ số a,c là các số thực.

Bước 1: Xác định các hệ số a=?, b=?, c=? của phương trình

Bước 2: Tính ∆ = b2 - 4ac

Bước 3: Kiểm tra ∆:

- Nếu ∆ < 0 thì kết luận phương trình vô nghiệm

- Nếu ∆ = 0 thì kết luận phương trình có nghiệp kép x1=x2=-b/(2a)

- Nếu ∆>0 thì kết luận phương trình có 2 nghiệm

x1=(-b + ∆ )/(2a); x2=(-b- ∆ )/(2a)

3.2.2 Sử dụng sơ đồ khối Sử dụng hệ thống các kí hiệu để biểu diễn thuật toán.

Một số ký hiệu sử dụng biểu diễn thuật toán:

STT Ký hiệu Ý nghĩa của ký hiệu

1

Ký hiệu bắt đầu thuật toán

2

Ký hiệu kết thúc thuật toán

3 Ký hiệu nhập dữ liệu

4

Ký hiệu xuất dữ liệu ra.

5

Ký hiệu rẽ nhánh Nếu Bt Lôgíc có giá trị Đúng thì

thực hiện theo nhánh Đ Nếu Bt Lôgíc có giá trị Sai thì thì

thực hiện theo nhánh S

6

Ký hiệu vòng lặp với số lần xác định trước.

Thực hiện công việc A n lần, ban đầu Biến được gán bằng 1, sau mỗi

lần lặp biến tăng lên 1 đơn vị

7

Kí hiệu khối các thao tác Thực hiện các công việc A

8

Kí hiệu gọi chương trình con A thực hiện

A

Biến = 1, 2, ..n

Bt Lôgíc S

Đ

A

A

Input:

Output:

begin

end

Page 22: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

23

9 Kí hiệu chỉ hướng thực hiện thuật

toán

Ví dụ: Biểu diễn thuật toán giải phương trình bậc 2 bằng sơ đồ khối.

Sơ đồ khối biểu diễn thuật giải phương trình bậc hai ax2+bx+c=0, a<>0, a, b, c, x ∈ R.

Nhận xét: Sử dụng sơ đồ khối để biểu diễn thuật toán có ưu điểm là trực quan, dễ hiểu, dễ kiểm tra. Nhưng có một số nhược điểm là phải vẽ khá nhiều, cồng kềnh, không thuận lợi cho bài toán phức tạp. Phương pháp này chủ yếu sử dụng cho người mới lập trình và để biểu diễn các thuật toán đơn giản (ít thao tác).

3.3 Các cấu trúc cơ bản của thuật toán Khi mô tả thuật toán ta sử dụng các cấu trúc sau đây để mô tả.

- Cấu trúc tuần tự

- Cấu trúc rẽ nhánh

- Cấu trúc lặp

3.3.1 Cấu trúc tuần tự Khái niệm: Cấu trúc tuần tự là cấu trúc bao gồm nhiều bước. Các bước này được sắp

xếp theo một trật tự nhất định. Khi máy thực hiện nó sẽ thực hiện theo thứ tự các bước đã được sắp xếp.

Trong biểu diễn thuật toán bằng phương pháp đặc tả tự nhiên thì các bước được sắp xếp tuần tự. Trong đặc tả đó chỉ ra bước nào thực hiện trước bước nào thực hiện sau.

S

Begin

Input: a, b, c

Delta = b2 – 4ac

Output: Pt có 2 nghiệm x1, x2

Delta < 0

Output: Pt vô nghiệm

Delta = 0

x = -b/2a

Output: Pt Có nghiệm kép x

1 ( ) /(2 )2 ( ) /(2 )

x b Delta ax b Delta a= − += − −

Đ

End

S

Đ

Page 23: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

24

Ví du: Đặc tả thuật toán giải phương trình bậc hai ở 3.2a thì thứ tự thực hiện các bước là: Thực hiện bước 1, sau khi thực hiện xong bước 1 thì thực hiện bước 2 và sau khi thực hiện xong bước 2 thì thực hiện bước 2.

Trong biểu diễn thuật toán bằng sơ đồ khối thì trình tự thực hiện của thuật toán được thực hiện theo chiều mũi tên.

Ví du: Tính diện tích, chu vi của một hình tròn bán kính r.

Sơ đồ khối mô tả thuật toán giải bài toán trên:

3.3.2 Cấu trúc rẽ nhánh Khái niệm: Cấu trúc rẽ nhánh là cấu trúc báo cho máy cần kiểm tra một điều kiện nào đó

của bài toán. Ở đây kết quả của điều kiện kiểm tra chỉ nhận một trong hai giá trị đúng hoặc sai. Nếu kết quả kiểm tra có giá trị đúng sẽ thực hiện thoe nhánh đúng, nếu sai sẽ thực hiện theo nhánh sai.

Biểu thức điều kiện chính là một biểu thức lôgíc

Sơ đồ khối thể hiện cấu trúc rẽ nhánh

Ví dụ: Giải phương trình bậc nhất ax + b = 0

Sơ đồ khối thể hiện thuật toán:

Input: r

S = πr2 C = 2πr

Output: S, C

begin

End

Biểu thức Lôgíc

Đ

S

Page 24: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

25

3.3.3 Cấu trúc lặp Trong lập trình chúng ta có hai dạng cấu trúc lặp: Cấu trúc lặp xác định trước và cấu trúc

lặp không xác định trước.

Cấu trúc lặp xác định: Khái niệm: Cấu trúc lặp xác đinh trước là cấu trúc báo cho máy lặp đi lặp lại một miền

tác động nào đó với số lần lặp xác định trước.

Trong miền tác động có thể bao gồm một tập cấu trúc cơ bản.

Sơ đồ khối thể hiện cấu trúc

Cấu trúc lặp không xác định: Khái niệm: Cấu trúc lặp không xác định là cấu trúc báo cho máy lặp đi lặp lại một miền

tác động nào đó với số lần lặp không xác định trước. Điều kiện kết thúc vòng lặp là một biểu thức lôgíc.

Input :a, b

a = 0

b = 0

Output: Pt vô số nghiệm

Đ

Ouput: Pt vô nghiệm

x = -b/a

Output: x

S

S

Đ

begin

end

Biến = 1, 2,

Miền tác động

Page 25: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

26

Trong miền tác động có thể bao gồm một tập cấu trúc cơ bản.

Sơ đồ khối thể hiện cấu trúc

Ví dụ: Tìm số tự nhiên N nhỏ nhất để tổng 1 1 11 ... 2.52 3

sn

= + + + + >=

Giải: Theo yêu cầu bài toán là cần tìm N nhỏ nhất để s .=2.5. Để tìm được N ta thực hiện theo thuẩt toán sau:

Sử dụng phương pháp đặc tả tự nhiên mô tả thuật toán: Bước 1. Khỏi tạo giá trị ban đầu n = 0, s = 0.

Bước 2. Tăng giá trị n lên 1 đơn vị (n = n + 1), tính s = s + 1n

Bước 3. Kiểm tra: Nếu s >= 2.5 thì dừng lại ta có n là giá trị cần tìm

Nếu s < 2.5 thì quay lại thực hiện lại bước 2.

Sử dụng sơ đồ khối mô tả thuật toán

3.4 Một số thuật toán giải một số bài toán đơn giản

s = 0, n = 1

s < 2.5

s = s + 1/n n = n +1

Đ

S

s, n

begin

end

Miền tác động

Miền tác động Biểu thức lôgíc

Biểu thức lôgíc

Đ

S

Đ

S

Hoặc

Page 26: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

27

3.4.1 Bài toán đếm Bài toán: Cho một dãy n các phần tử a1, a2,…, an. Hãy đếm xem trong dãy có bao nhiêu

phần tử thoả mãn điều kiện nào đó.

Một cách tự nhiên thì để giải bài toán trên, ta thực hiện duyệt qua từng phần tử. Với mỗi phần tử thoả mãn điều kiện thì tăng biến đếm lên một đơn vị.

Thuật toán Bước 1. Xác định n và các phần tử

Bước 2. Khởi tạo một biến đếm với giá trị là 0

Bước 3. Thực hiện duyệt qua từng phần tử. Với mỗi phần tử được duyệt, thực hiện kiểm tra xem nó có thoả mãn điều kiện bài toán không?. Nếu thoả mãn thì tăng biến đếm lên một đơn vị. Nếu không thoả mãn thì duyệt phần tử tiếp theo.

Mô tả thuật toán bằng sơ đồ khối

Ví dụ 1: Cho một dãy n số nguyên. Đếm xem trong dãy có bao nhiêu số chẵn.

Thuật toán

Sử dụng phương pháp đặc tả tự nhiên mô tả thuật toán Bước 1. Xác định n và các phần tử

Bước 2. Khởi tạo một biến đếm với giá trị là 0

n

i = 1, 2, .., n

ai

Dem = 0

i = 1, 2, .., n

Bt Lôgíc

Dem

S

Đ

Dem = Dem +1

Begin

End

Page 27: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

28

Bước 3. Thực hiện duyệt qua từng phần tử. Với mỗi phần tử được duyệt, thực hiện kiểm tra: Nếu ai chia hết cho 2 thì tăng biến đếm lên một đơn vị. Ngược lại, duyệt phần tử tiếp theo.

Sử dụng sơ đồ khối mô tả thuật toán Trong sơ đồ khối ta sử dụng phép toán mod, phép toán chia các số nguyên lấy phần dư.

Mô tả thuật toán đếm các số chẵn trong một dãy số

3.4.2 Bài toán tìm giá trị lớn nhất, giá trị nhỏ nhất Trong cuộc sống thực tế, hàng ngày chúng ta luôn phải đi tìm giá trị lớn nhất, nhỏ nhất

trong một tập phần tử. Ví dụ như tìm người có chiều cao cao nhất (thấp nhất) trong lớp; tìm sinh viên có điểm tổng kết cao nhất (thấp nhất) trong lớp, trong khoa, trong trường; …. Như vậy nếu có một thuật toán giải bài toán này và cài đặt nó trên máy tính để máy giải gúp chúng ta thì tốt biết bao. Bài toán cụ thể được phát biểu như sau:

Bài toán: Cho một dãy n số bất kỳ. Hãy tìm giá trị lớn nhất (nhỏ nhất) của dãy số đó.

Để tìm giá trị lớn nhất (nhỏ nhất) của các phần tử trong dãy. Ta thực hiện so sánh các phần tử trong dãy với nhau sẽ tìm ra được giá trị mong muốn. Quá trình tìm được thể hiện bằng thuật toán sau đây.

Thuật toán

Sử dụng phương pháp đặc tả tự nhiên môt tả thuật toán Bước 1. Xác định n và các số a1, a2, …, an

Bươc 2. Sử dụng Max lưu giá trị lớn nhất. Giả sử giá trị lớn nhất là a1 (tức là Max = a1).

Bước 3. Duyệt lần lượt qua các phần tử, a2, a3, …, an. So sánh giá trị của phần tử ai với Max. Nếu ai > Max (i=2..n) thì gán giá trị của ai cho Max (Max = ai). Nếu ai < Max thì chuyển xét phần tử tiếp theo.

Giá trị cuối cùng lưu trong Max chính là giá trị lớn nhất của dãy số.

Sử dụng sơ đồ khối mô tả thuật toán

Input: n

i = 1, 2, .., n

Input: ai

Dem = 0

i = 1, 2, .., n

ai mod 2 = 0

Dem = Dem +1

Output: Dem

S

Đ

Begin

End

Page 28: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

29

Thuật toán tìm giá trị lớn nhất của một dãy số.

Đối với bài toán tìm giá trị nhỏ nhất cũng tương tự, nhưng trong phép so sánh ta phải thay dấu “<” bằng dấu “>” và thay tên Max thành Min để phù hợp với ý nghĩa kết của kết quả lưu trong nó.

Một số bài toán qui về bài toán tìm max, min

Bài 1. Cho tọa độ của một dãy n điểm { } 1, n

i i ix y

= trong mặt phẳng. Tìm diện tích đường

tròn tâm O(0,0) có bán kính nhỏ nhất chứa n điểm trên.

Gợi ý: Bài toán này qui về bài toán tìm Max

Bài 2. Cho tọa độ của một dãy n điểm { } 1, n

i i ix y

= trong mặt phẳng. Tìm hình chữ nhật có

diện tích nhỏ nhất và các cạnh song song với các trục toạ độ chứa n điểm trên.

Gợi ý: Bài toán này qui về bài toán tìm cả Min và Max.

3.4.3 Bài toán tính tổng một dãy số Bài toán: Cho 1 dãy n số. Tính tổng tất cả các phần tử của dãy.

Thuật toán

Sử dụng phương pháp đặc tả tự nhiên mô tả thuật toán Bước 1. Xác định n, a1, a2, …, an

Bước 2 .Khởi tạo S = 0

Bước 3. Duyệt qua từng phần tử của dãy số. Với phần tử ai của dãy thực hiện S = S + ai.

Sau khi duyệt qua hết các phần tử ta được tổng của dãy lưu trong S.

Sử dụng sơ đồ khối mô tả thuật toán

i = 2, 3,..., n Input: n

i = 1, 2, .., n

Input: ai

Max = a1

Max<ai

Output: Max

S

Đ Max = ai

Begin

End

Page 29: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

30

Một số bài toán qui về bài toán tính tổng

Bài 1. Tính giá trị của đa thực Pn(x) = a0 + a1x + a1x2 + … +a1xn

Bài 2. Tính tổng theo công thức ( công thức tổng quát dạng S = f(x) + n

i=1f(x,n)∑ )

Ví dụ 1: Cho x là số thực, n là số nguyên dương. Tính

S = ex + 12

x+ + 21

3x+ + … + 1

1

nxn++

Ví dụ 2: Cho x là số thực, n là số nguyên dương. Tính

S = | x+ (1+x)3 + (2+x)3 + … +(n+x)3|

Ví dụ 3: Cho x là số thực, n là số nguyên dương. Tính

1 22006 ... ( 1)1! 2! !

nx x x ns

n+ + +

= − + − + −

Ví dụ 4: Cho x là số thực, n là số nguyên dương. Tính

2

2006 ...2! !

nx xS xn

= + + + +

3.4.4 Bài toán tính tích một dãy số Bài toán: Cho 1 dãy n số. Tính tích tất cả các phần tử của dãy.

Thuật toán tính tích của một dãy số cũng tương tự như thuật toán tổng. tuy nhiên khác với thuật toán tính tổng là khi khởi gán cho đại lượng lưu trữ tích là 1 thay vì khởi gán 0 và thay phép + bằng phép * (nhân).

Input: n

i = 1, 2, .., n

Input: ai

S = 0

i = 1, 2,..., n

S = S + ai

Output: S

Begin

End

Page 30: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

31

Các bài toán qui về thuật toán tính tích

Bài 1. Cho số tự nhiên n. Tính S = n!

Bài 2. Cho số thực x, số tự nhiên n. Tính S = xn

Page 31: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

32

PHẦN 2 NGÔN NGỮ LẬP TRÌNH C

Page 32: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

33

CHƯƠNG 1 - MỘT SỐ KHÁI NIỆM MỞ ĐẦU

Chương này sẽ giới thiệu những thành phần cơ bản của ngôn ngữ lập trình C, đó là: Tập ký tự, từ khóa và tên. Để có thể lập được một chương trình đầy đủ, chúng tôi sẽ trình bầy đôi điều về câu lệnh gán, các câu lệnh vào ra, chỉ thị #include và những qui tắc cần lưu ý khi viết chương trình. Ngoài ra để giúp bạn đọc mau chóng tiếp cận với máy, chúng tôi sẽ giới thiệu vài chương trình đơn giản nhưng hoàn chỉnh và cách vận hành chúng trên máy để nhận được kết quả cuối cùng. Tất cả những điều nói trên là bổ ích và đáng ghi nhớ vì chúng sẽ được thường xuyên sử dụng sau này. Đọc xong chương 1 bạn có thể lập được một số chương trình đơn giản. Ngoài ra còn biết cách thực hiện chương trình trên môi trường Turbo C 2.0 và Turbo C++ 3.0

1.1 Tập ký tự Mọi ngôn ngữ lập trình đều được xây dựng từ một bộ ký tự nào đó. Các ký tự được nhóm

lại theo nhiều cách khác nhau để lập lên các từ. Đến lượt mình, các từ lại được liên kết theo một qui tắc nào đó để tạo thành các câu lệnh. Một chương trình bao gồm nhiều câu lệnh và diễn đạt một thuật toán để giải một bài toán nào đó. Ngôn ngữ C được xây dựng trên bộ ký tự sau:

26 chữ cái hoa: A B C ... Z

26 chữ cái thường: a b c ... z

10 chữ số: 0 1 2 ... 9

Các ký hiệu toán học như: + - * / = ( )

Ký tự gạch nối: _ ( chú ý phân biệt với dấu - )

Các ký hiệu đặc biệt khác như: . ,;: [] {} ?! \ & | % # $ , ...

Dấu cách (space) thực sự là một khoảng trống dùng để tách các từ. Ví dụ HA NOI gồm 6 ký tự, còn HANOI gồm 5 ký tự.

Chú ý: Khi viết chương trình ta không được sử dụng bất kỳ ký hiệu nào khác ngoài tập các ký tự nói trên.

Chẳng hạn khi giải phương trình bậc hai:

ax2 + bx + c = 0

ta cần tính biểu thức:

∆ = b2 - 4ac

Ký tự ∆ không cho phép dùng trong ngôn ngữ C, vì vậy ta phải dùng một cách ký hiệu khác như d hay delta.

1.2 Từ khóa Từ khóa là những từ được định nghĩa trước và có một ý nghĩa hoàn toàn xác định. Chúng

thường được sử dụng để khai báo các kiểu dữ liệu, để viết các toán tử và các câu lệnh. Sau đây là các từ khóa của TURBO C:

asm break case cdecl

char const continue default

do double else enum

Page 33: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

34

extern far float for

goto huge if int

interrupt long near pascal

register return short signed

sizeof static struct switch

typedef union unsigned void

volatile while

Ý nghĩa và cách sử dụng của chúng sẽ được lần lượt giới thiệu ở các mục sau. Ở đây chỉ cần nhớ hai điều:

- Không được dùng từ khóa để đặt tên cho các hằng, biến, mảng, hàm, ...

- Từ khóa phải được viết bằng chữ thường. Chẳng hạn không được viết iNT mà phải viết int.

1.3 Tên Tên là một khái niệm rất quan trọng, nó dùng để xác định các đối tượng khác nhau trong

một chương trình. Chúng ta có tên hằng, tên biến, tên mảng, tên hàm, tên con trỏ, tên cấu trúc, tên nhãn,...:

Việc đặt tên phải tuân theo một số quy tắc: Tên là một dãy các ký tự gồm chữ, số và dấu gạch nối. Ký tự đầu của tên không được là số. Tên không được trùng với từ khóa (xem 1.2). Độ dài cực đại của tên đối với môi trường Turbo C mặc định là 32.

Các ví dụ đúng về tên:

a_1 BETA x1 delta_7 _x1

Các ví dụ sai về tên:

3XYZ_7 (Ký tự đầu tiên là số)

r#3 (sử dụng ký tự # )

f(x) (sử dụng các dấu ngoặc tròn)

case (trùng với từ khóa )

be ta (sử dụng khoảng trống)

X-1 (sử dụng dấu gạch ngang)

Chú ý: Trong các tên, chữ hoa và chữ thường được xem là khác nhau, như vậy tên AB khác tên ab.

1.4 Một số khái niệm

1.4.1 Biến Biến là đại lượng dùng để chứa (lưu trữ) các giá trị trong quá trình tính toán. Có thể hiểu

khái niệm biến ở đây giống như khái niệm biến trong toán học.

Vấn đề khai báo sẽ nói kỹ trong chương 2. Ở đây chúng ta chỉ cần biết vài điều sơ lược. Mọi biến trước khi sử dụng đều phải khai báo để xác định kiểu của nó. Để khai báo các biến nguyên (kiểu int) ta dùng từ khoá int. Đối với biến thực (kiểu float) ta dùng từ khoá float. Ví dụ:

Page 34: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

35

int a,b,c; /* khai báo các biến a, b, c kiểu int */ float x,y,z; /* khai báo các biến x,y,z kiểu float */

Sự khác nhau giữa biến kiểu int và biến kiểu float là ở chỗ: biến kiểu int luôn luôn nhận giá trị nguyên trong quá trình tính toán còn biến kiểu float có thể nhận cả các giá trị không nguyên.

1.4.2 Hằng Hằng là các đại lựong có giá trị không đổi trong chương trình. Khái niệm này sẽ được đề

cập chi tiết trong 2.2

1.4.3 Toán tử gán

Câu lệnh gán sẽ nói kỹ trong chương 2. Ở đây ta có thể hiểu toán tử gán có dạng: b = bt;

Trong đó b là một biến, còn bt là một biểu thức toán học nào đó. Tác dụng của câu lệnh này là: trước tiên tính biểu thức bt và sau đó gán giá trị tính được cho biến b.

Ví dụ: Sau khi thực hiện đoạn chương trình: float x; x = 10.5; x = 2*x - 2.5;

biến x sẽ nhận giá trị là 18.5.

Chú ý là khái niệm gán không giống như khái niệm đẳng thức trong toán học.

1.4.4 Câu lệnh và khối lệnh Mỗi câu lệnh thực hiện 1 chức năng (công việc) nào đó, nó có thể được viết trên một

hoặc nhiều dòng nhưng phải kết thúc bằng dấu;

Ví dụ: clsrcr(); printf("Hello");

Khối lệnh là một dãy các câu lệnh được bao bởi cặp dấu { và }.

Ví dụ: {

int a,b; a=2; b=3; printf ("\n%6d%6d",a,b);

}

Chú ý: Về mặt cú pháp, C xem một khối lệnh cũng như một câu lệnh riêng lẻ. Nói cách khác chỗ nào viết được một câu lệnh thì ở đó cũng có quyền đặt một khối lệnh.

Khai báo ở đầu khối lệnh Các khai báo biến, mảng có thể đặt ở đầu của một hàm, hoặc có thể viết ở đầu khối lệnh,

ví dụ: {

int a,b,c[50]; float x,y,z,t[20][30]; a = 3; b = 5; x = 5.7; y=a*x; z=b*x;

Page 35: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

36

printf ("\ny=%8.2f\nz=%8.2f",y,z); }

Sự lồng nhau của các khối lệnh Bên trong một khối lệnh lại có thể viết các khối lệnh khác. Số các khối lệnh lồng nhau là

không hạn chế.

Phạm vi hoạt động của các biến và mảng Khi gặp khai báo của biến và mảng, máy sẽ cấp phát bộ nhớ cho biến và mảng. Các biến

chỉ tồn tại trong khối lệnh mà biến được khai báo, và sẽ mất đi khi kết thúc khối lệnh.

Từ đó có thể rút ra một số kết luận sau:

- Giá trị của một biến hay một mảng khai báo bên trong một khối lệnh không thể đưa ra để sử dụng ở bất kỳ chỗ nào bên ngoài khối lệnh đó.

- Từ bên ngoài một khối lệnh, không thể can thiệp đến các biến và các mảng được khai báo bên trong khối lệnh.

Về các khối lệnh lồng nhau

Ta có thể khai báo hai biến hoặc hàm cùng tên, một ở ngoài và một ở khối lệnh bên trong, khi đó hai biến đó là hai biến độc lập cùng tên.

Ví dụ xét đoạn chương trình: { int a=5; {

int a=4; printf ("a = %d\n", a);

} printf("a = %d\n", a); }

Đoạn chương trình trên có hai lệnh printf giống nhau, cùng in ra giá trị của a, nhưng là hai biến a khác nhau, kết quả đưa ra sẽ là:

a = 4 a = 5

Biến a bên trong trùng tên với biến a bên ngoài, do đó lệnh in bên trong sẽ in giá trị của biến a ở khối lệnh bên trong, hay nói cách khác, ở khối lệnh bên trong, biến a bên trong đã che biến a bên ngoài.

1.4.5 Chú thích

Trong một chương trình, ngoài các câu lệnh, ta có thể đưa thêm vào các lời chú thích. Các chú thích này không ảnh hưởng đến kết quả họat động của chương trình, nó chỉ có tác dụng đối với người đọc chương trình.

Các lời giải thích cần được đặt giữa dấu /* và dấu */ và có thể được viết:

- Trên một dòng.

- Trên nhiều dòng.

- Trên phần còn lại của một dòng.

Trong TC 3.0 ta có thể dùng dấu // để chú thích. Phần chú thích sẽ bắt đầu từ dấu // đến cuối dòng.

Ví dụ:

Page 36: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

37

clrscr(); // xoá màn hình printf(“Hello”); // in ra màn hình dòng chữ Hello

1.5 Nhập xuất dữ liệu Nhập xuất dữ liệu là cách chúng ta đưa dữ liệu vào chương trình và đưa ra kết quả của

chương trình. Thông thường, dữ liệu được đưa vào thông qua bàn phím, và kết quả được đưa ra màn hình.

1.5.1 Đưa kết quả ra màn hình Có thể đưa ra màn hình một dòng chữ, hoặc các giá trị số bằng lệnh printf. Lệnh printf có

dạng: printf (<chuỗi điều khiển>, bt1, bt2, ..., btn);

Ở đây bt1, bt2,..., btn là các biểu thức mà giá trị của chúng cần được đưa ra màn hình.

Trong chuỗi điều khiển, có thể chứa:

- Ký tự điều khiển.

- Các ký tự hiển thị.

- Các ký tự dùng để mô tả kiểu cách đưa ra của các biến, ta sẽ gọi chúng là các đặc tả.

Một số ký tự điều khiển được định nghĩa trước, thường có dấu \ phía trước, ví dụ ký tự điều khiển xuống dòng là \n, ký tự tab là \t.

Các ký tự hiển thị sẽ được đưa ra giống như khi chúng xuất hiện ở trong chuỗi điều khiển.

Các đặc tả sẽ chỉ ra cách mà giá trị của các biểu thức sẽ được đưa ra. Mỗi biểu thức cần phải có một đặc tả tương ứng. Khi in ra màn hình, giá trị của các biểu thức sẽ được thay thế tương ứng vào vị trí các đặc tả.

Sau đây là một số dạng thường dùng của câu lệnh printf.

Đưa ra một thông báo

Đôi khi chúng ta chỉ muốn đưa ra một thông báo, một câu hướng dẫn, khi đó chỉ cần đưa vào chuỗi điều khiển không chứa các đặc tả. Nội dung của xâu sẽ được đưa ra màn hình.

Ví dụ, để đưa ra một thông báo nhắc người dùng nhập vào hệ số của đa thức, có thể dùng lệnh:

printf(“\nNhap he so da thuc: ”);

Khi đó trên màn hình sẽ xuất hiện: Nhap he so da thuc:

Đưa ra các giá trị nguyên Khi muốn đưa ra các kết quả là các giá trị nguyên, chúng ta dùng đặc tả %d. Sau đây

chúng ta sẽ xét một số ví dụ để có thể hiểu được hoạt động của đặc tả này.

Ví dụ, đoạn mã sau đưa ra tổng của hai số nguyên: int a, b; a = 10; b = 25; printf(“Tong cua %d va %d la %d”, a, b, a + b);

Page 37: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

38

Câu lệnh printf sẽ thay thế các đặc tả %d bằng giá trị các biểu thức tương ứng theo thứ tự đưa vào. Trong đoạn mã trên, giá trị của a, b và a + b sẽ lần lượt được thay thế vào các vị trí %d trong chuỗi điều khiển, kết quả đưa ra màn hình như sau:

Tong cua 10 va 25 la 35

Trong ví dụ trên, giá trị của các biểu thức có bao nhiêu chữ số thì bấy nhiêu vị trí trên màn hình được sử dụng để in giá trị, ví dụ giá trị 10 cần hai vị trí thì máy sẽ dành đúng hai vị trí để in ra giá trị 10.

Tuy nhiên, trong một số trường hợp, như in ra các giá trị của một ma trận, hoặc in các giá trị theo dạng cột, thì chúng ta cần dành một số vị trí nhất định cho một giá trị, mặc dù số vị trí cần thiết để in ra giá trị đó có thể nhỏ hơn.

Ví dụ, đoạn chương trình sau in ra giá trị các luỹ thừa của 2 theo dạng cột: #include <stdio.h> void main() { int i, a; a = 1; for (i = 1; i <= 10; i++) {

a*= 2; printf("2 ^ %2d = %4d\n", i, a);

} }

Kết quả đưa ra như sau: 2 ^ 1 = 2 2 ^ 2 = 4 2 ^ 3 = 8 2 ^ 4 = 16 2 ^ 5 = 32 2 ^ 6 = 64 2 ^ 7 = 128 2 ^ 8 = 256 2 ^ 9 = 512 2 ^ 10 = 1024

Trong ví dụ trên, ta đã dành 2 vị trí cho việc in số mũ, và dành 4 vị trí để in ra các luỹ thừa, bất kể các giá trị này bằng bao nhiêu.

Đưa ra các giá trị thực Để đưa ra các giá trị thực, chúng ta dùng đặc tả %f. Ví dụ sau tính diện tích của một hình

tròn và đưa kết quả ra màn hình. #include <stdio.h> void main() { float r; r = 2.34f; printf("Dien tich hinh tron ban kinh %f la %f\n", r, 3.14*r*r); }

Kết quả in ra là: Dien tich hinh tron ban kinh 2.340000 la 17.193383

Tuy nhiên, đôi khi ta không cần kết quả gồm nhiều chữ số thập phân như thế, mà chỉ cần lấy một số lượng chữ số sau dấu phẩy nhất định.

Page 38: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

39

Câu lệnh printf sau sẽ thay thế cho câu lệnh printf trong đoạn mã trên để đưa ra các kết quả lấy hai chữ số sau dấu phẩy, và dành 6 ký tự cho việc in ra mỗi giá trị.

printf("Dien tich hinh tron ban kinh %6.2f la %6.2f\n", r, 3.14*r*r);

Kết quả là: Dien tich hinh tron ban kinh 2.34 la 17.19

Một trường hợp nữa là chúng ta vẫn muốn lấy một số lượng chữ số sau dấu phẩy nhất định, nhưng không có ý định dành sẵn một số vị trí xác định, khi đó trong đặc tả có thể vắng mặt số phía trước dấu chấm.

Sau đây là câu lệnh printf thường dùng nhất cho các bài dạng trên: printf("Dien tich hinh tron ban kinh %.2f la %.2f\n", r, 3.14*r*r);

Kết quả là: Dien tich hinh tron ban kinh 2.34 la 17.19

Đưa ra các xâu ký tự Khi muốn đưa ra các giá trị là các xâu ký tự, ví dụ như họ và tên hay địa chỉ, dùng đặc tả

%s.

Ví dụ sau yêu cầu nhập vào tên và in ra lời chào. #include <stdio.h> void main() { char szHoTen[100]; printf("Nhap ten ban: "); fflush(stdin); gets(szHoTen); printf("Xin chao %s", szHoTen); }

Khi chạy, nhập vào một tên và máy sẽ in ra lời chào tương ứng. Nhap ten ban: Minh Quang Xin chao Minh Quang

Với đặc tả %s, ta cũng có thể dành sẵn độ rộng cho giá trị in ra, sử dụng trong các trường hợp như in họ tên theo cột. Việc chỉ định độ rộng giống như đối với trường hợp số nguyên.

1.5.2 Nhập dữ liệu từ bàn phím Nhập dữ liệu từ bàn phím là một cách thông dụng để nạp giá trị cho các biến hoặc mảng.

Trong phần này, chúng ta sẽ tìm hiểu cách nhập liệu cho các biến nguyên, biến thực và xâu ký tự.

Nhập số nguyên, số thực bằng scanf Câu lệnh scanf có thể dùng để nhập dữ liệu cho các biến nguyên, thực. Một cách tổng

quát câu lệnh scanf có dạng: scanf("t1t2...tk", &b1,&b2,...,&bk);

Trong đó b1, b2,..., bk là các biến (kiểu int và kiểu float) còn t1, t2,..., tk là các đặc tả tương ứng. Dùng đặc tả %d đối với biến nguyên và %f đối với biến thực.

Một vài chú ý:

Page 39: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

40

- Trong câu lệnh scanf, không dùng tên biến như trong câu lệnh printf mà dùng địa chỉ của biến bằng cách đặt phép toán & trước tên biến.

- Mỗi biến ứng với một đặc tả. Như vậy số đặc tả bằng số biến.

- Trong chuỗi điều khiển chỉ nên chứa các đặc tả, và các đặc tả nên viết liền nhau.

Ví dụ, để vào 3 giá trị: 25, -137, 45.3 cho hai biến nguyên m, n và một biến thực f, dùng lệnh:

scanf(“%d%d%f”, &n, &m, &f);

Khi gặp câu lệnh này, máy sẽ dừng để đợi thao tác viên vào số liệu từ bàn phím. Các giá trị cần được phân cách nhau bởi một hoặc vài khoảng trắng (ở đây khoảng trắng được hiểu là dấu cách hoặc dấu xuống dòng).

Thao tác viên có thể sử dụng một trong các cách bấm phím sau:

Cách 1: Mỗi giá trị trên một dòng, bằng cách nhấn phím Enter sau mỗi số. 25 -137 45.3

Cách 2: Đặt cả 3 giá trị trên một dòng, cách nhau bằng các dấu cách. 25 -137 45.3

Sau khi nhập xong, n nhận giá trị 25, m nhận giá trị -137 và f nhận giá trị 45.3.

Nhập xâu ký tự bằng gets Để nhập xâu ký tự, có thể dùng lệnh gets. Lệnh gets có dạng:

gets(<xâu ký tự>)

Ở đây, xâu ký tự là một mảng kiểu char.

Chú ý: Nếu trước lệnh gets mà có các lệnh scanf, thì có thể không nhập được xâu do ký tự return còn ở trong bộ đệm. Vì vậy để sử dụng đúng đắn câu lệnh gets, nên thêm lệnh fflush(stdin) trước lệnh gets trong mọi trường hợp.

1.6 Một số chương trình đơn giản Dưới đây là các ví dụ nhằm minh hoạ cấu trúc của một chương trình C. Độc giả dễ dàng

hiểu được mỗi câu lệnh qua các giải thích viết giữa các dấu /* */

Ví dụ 1. Viết chương trình cho hiện lên màn hình hai dòng chữ: TURBO C HAN HANH LAM QUEN VOI BAN

Dưới đây là hai chương trình cùng thực hiện yêu cầu đề ra. /* Chương trình in hai dòng chữ - Bản 1 */ #include <stdio.h> /* sử dụng thư viện vào ra chuẩn */ #include <conio.h> void main () /* hàm chính */ { /* Xuống dòng (\n) và in: TURBO C HAN HANH */ printf("\nTURBO C HAN HANH"); /* Xuống dòng và in: LAM QUEN VOI BAN */ printf("\nLAM QUEN VOI BAN"); getch(); /* Tạm dừng máy để xem kết quả */ }

Phiên bản sau ghép hai câu lệnh printf thành một câu lệnh duy nhất.

Page 40: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

41

/* Chương trình in 2 dòng chữ - Bản 2 */ #include "stdio.h" /* sử dụng thư viện vào ra chuẩn */ #include "conio.h" void main () /* hàm chính */ {

/* Xuống dòng, in: TURBO C HAN HANH, tiếp tục xuống dòng rồi in: LAM QUEN VOI BAN */ printf("\nTURBO C HAN HANH\nLAM QUEN VOI BAN"); getch(); /* Tạm dừng máy để xem kết quả */

}

Nhận xét: Mỗi cậu lệnh printf trong bản 1 in được một dòng. Câu lệnh printf trong bản 2 in được hai dòng.

Ví dụ 2. Chương trình dưới đây tính chu vi và diện tích hình tròn theo giá trị bán kính r nhập từ bàn phím.

#include "stdio.h" #include "conio.h" #include "math.h" /*Sử dụng thêm thư viện các hàm toán học*/ void main() {

float r,cv,dt; /* Khai báo 3 biến thực */ /* Đưa ra man hình thông báo về yêu cầu nhập số liệu */ printf("\nBan kinh r= "); /* Nhập một giá trị thực đưa vào biến r */ scanf("%f",&r); /* Tính chu vi và diên tích hình tròn Dùng hằng M_PI (PI) đã định nghĩa trong math.h */ cv = 2*M_PI*r; dt = M_PI*r*r; /* In kết quả */ printf("\nChu vi=%10.2f\nDien tich=%10.2f",cv,dt); getch(); /* Tạm dừng máy để xem kết quả */

}

Ví dụ 3: Tính x luỹ thừa y. /* chuong trinh tinh x luy thua y */ #include "stdio.h" #include "math.h" void main () {

float x,y,z; // khai bao ba bien kieu float printf("\n vao x va y "); scanf("%f%f",&x,&y); // vao x, y tu ban phim z=pow(x,y); // tinh z = x ^ y /* in ket qua tren 3 dong */ printf("\nx = %f\ny = %f\nz = %f", x, y, z);

}

Ví dụ 4: Minh hoạ khả năng đưa ra /* chuong trinh minh hoa cac kha nang dua ra */ #include "stdio.h" void main() {

int a,c,t; float b,d; a = 123; c = -4685; t = 12; b = -45.855; d = 123.425; printf("\nChuc cac ban may man \n"); printf("Tong san luong hang nam tang %d %",t);

Page 41: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

42

/* giua cac so dua ra khong co khoang cach */ printf("\n%d%f%d%f",a,b,c,d); /* giua cac so dua ra co nhung khoang trong */ printf("\n%d %f %d %f",a,b,c,d); /* giua cac so co dat them cac ky tu khac */ printf("\na = %d, b = %f, c=%d, d=%f", a,b,c,d);

}

Kết quả thực hiện chương trình: Chuc cac ban may man Tong san luong hang nam tang 12 % 123-45.855000-4685123.425000 123 -45.855000 -4685 123.425000 a = 123, b = -45.85, c = -4685, d = 123.43

1.7 Cách thực hiện các chương trình trên máy tính Phần việc còn lại sau khi đã có chương trình là thực hiện chương trình trên máy tính để

nhận kết qủa cuối cùng. Đây là phần việc có tính chất tác nghiệp ít đòi hỏi suy nghĩ và sáng tạo hơn so với công việc lập trình. Quá trình vận hành một chương trình trên máy tính bao gồm các bước cơ bản sau:

- Tạo tệp chương trình gốc đuôi C và soạn thảo chương trình.

- Dịch và chạy chương trình.

Dưới đây sẽ trình bầy cách sử dụng các phần mềm TC2.0 (Turbo C 2.0) và TC++3.0 (Turbo C++ 3.0) để thực hiện chương trình. Chúng ta sẽ thấy trình tự thao tác là rất đơn giản và tượng tự như nhau (đối với TC2.0 và TC++3.0) .

Thực hiện chương trình trong TC2.0 Giả sử TC2.0 đã được cài đặt trong thư mục C:\TC

Soạn thảo chương trình: Vào môi trường của TC2.0 bằng cách khởi động tệp TC.EXE trong thư mục C:\TC. Khi đó sẽ nhận được menu chính của TC2.0 gồm các menu: File, Edit, Run, Compile, Project, Option, Debug và Break/Watch.

Chọn menu File, mục New để nhận cửa sổ soạn thảo. Dùng bàn phím để soạn thảo chương trình trong cửa sổ này, sau đó dùng phím F2 (hoặc chọn File - Save) để ghi chương trình lên tệp.

Dịch và chạy chương trình: Bấm đồng thời 2 phím Ctrl và F9, hoặc chọn menu Run, mục Run.

Thực hiện chương trình trong TC++3.0

Giả sử TC++3.0 đã được cài đặt trong thư mục C:\TC++

Soạn thảo chương trình: Vào môi trường của TC++3.0 bằng cách khởi động tệp TC.EXE trong thư mục C:\TC++\BIN. Khi đó sẽ nhận được menu chính của TC++3.0 gồm các menu: File, Edit, Search, Run, Compile, Debug, Project, Option, Window và Help.

Chọn menu File, mục New để nhận cửa sổ soạn thảo. Dùng bàn phím để soạn thảo chương trình trong cửa sổ này, sau đó dùng phím F2 (hoặc chọn File - Save) để ghi chương trình lên tệp.

Dịch và chạy chương trình: Bấm đồng thời 2 phím Ctrl và F9, hoặc chọn menu Run, mục Run.

BÀI TẬP CHƯƠNG 1

Page 42: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

43

Bài 1. Thực hiện các chương trình viết trong các mục 1.5 và 1.7.1 trên máy. Đối chiếu kết qủa nêu trong sách với kết qủa nhận được.

Bài 2. Lập chương trình tính tích của 4 số thực được nạp từ bàn phím, sau đó thực hiện chương trình trên máy (dùng dấu * để biểu thị thị phép nhân).

Bài 3. Cho biết lương kỳ hai của cán bộ tính theo công thức:

lk bl n lk226

1=×

trong đó bl là bậc lương, n là số ngày công trong tháng, lk1 là các khoản tiền đã lĩnh ở kỳ một. Lập chương trình nhập bl, n, lk1 từ bàn phím, sau đó tính lk2 theo công thức trên. Thực hiện chương trình trên máy với các số liệu cụ thể (dùng dấu / để biểu thị phép chia, ví dụ a/b = a:b).

Page 43: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

44

CHƯƠNG 2 - CÁC KIỂU DỮ LIỆU

Kiểu dữ liệu của một biến hay hằng là khái niệm chỉ dạng thông tin của biến hay hằng đó. Ví dụ biến có kiểu nguyên dùng để lưu các giá trị nguyên, biến kiểu thực dùng để lưu các giá trị thực.

2.1 Các kiểu dữ liệu cơ bản Trong chương này, chúng ta sẽ tìm hiểu một số kiểu dữ liệu cơ bản được định nghĩa trong Turbo C, bao gồm kiểu nguyên và kiểu thực.

2.1.1 Các kiểu số nguyên Tuỳ từng yêu cầu cụ thể mà chúng ta có thể sử dụng các kiểu số nguyên có phạm vi biểu

diễn khác nhau. Bảng sau chỉ ra các kiểu số nguyên và phạm vi biểu diễn tương ứng.

Kiểu Phạm vi biểu diễn Kích thước char -128 → 127 1 byte int -32768 → 32767 2 byte

long hoặc long int -2147483648→2147483647 4 byte

Tương ứng với các kiểu số nguyên có dấu là các kiểu số nguyên không dấu. Các kiểu số nguyên không dấu được thành lập bằng cách thêm từ khoá unsigned vào trước kiểu số nguyên có dấu tương ứng. Bảng sau chỉ ra các kiểu số nguyên không dấu:

Kiểu Phạm vi biểu diễn Kích thước unsigned char 0 → 255 1 byte unsigned int 0 → 65535 2 byte

unsigned long 0 → 4294967295 4 byte

2.1.2 Các kiểu số thực

Kiểu số thực, hay kiểu dấu phẩy động dùng để lưu các giá trị thực. Trong C cho phép sử dụng ba kiểu dấu phẩy động là float, double và long double. Kích cỡ và phạm vi biểu diễn của chúng được chỉ ra trong bảng dưới đây:

Kiểu Phạm vi biểu diễn Số chữ số có nghĩa Kích thước (byte)

float 3.4E-38 → 3.4E+38 7-8 4 double 1.7E-308 → 1.7E+308 15-16 8 long double 3.4E-4932 → 1.1E4932 17-18 10

Giải thích: Máy có thể lưu trữ được số kiểu float có giá trị tuyệt đối từ 3.4E-38 đến 3.4e+38. Số có giá trị tuyệt đối nhỏ hơn 3.4E-38 được xem bằng 0. Phạm vi biểu diễn của số double được hiểu theo nghĩa tương tự.

2.1.3 Biểu diễn các kiểu khác qua kiểu cơ bản

Kiểu ký tự Để biểu diễn các ký tự, người ta dùng một số nguyên lưu mã của ký tự đó trong bảng mã.

Với bảng mã ASCII, mỗi ký tự được biểu diễn bằng một số nguyên 8 bit.

Ví dụ:

Page 44: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

45

Ký tự Mã ASCII 0 48 1 49 2 50 A 65 B 66 a 97 b 98

Bảng mã ASCII gồm 256 ký tự, có thể phân thành 3 nhóm:

- Nhóm các ký tự điều khiển có mã từ 0 đến 31. Chẳng hạn ký tự mã 13 dùng để chuyển con trỏ về đầu dòng, ký tự 10 chuyển con trỏ xuống dòng dưới (trên cùng cột). Các ký tự nhóm này nói chung không hiển thị ra màn hình.

- Nhóm các ký tự văn bản có mã từ 32 đến 126. Các ký tự này có thể đưa ra màn hình và máy in.

- Nhóm các ký tự đồ hoạ có mã số từ 127 đến 255. Các ký tự này có thể đưa ra màn hình nhưng không in được (bằng các lệnh DOS).

Kiểu đúng sai

Trong TC quy định rằng, các biểu thức có giá trị khác 0 là đúng và ngược lại các biểu thức có giá trị bằng 0 là sai.

2.2 Hằng Hằng là các đại lượng mà giá trị của nó không thay đổi trong quá trình tính toán. Dưới

đây trình bầy cách biểu diễn các hằng trong C.

2.2.1 Hằng dấu phẩy động (float và double) Hằng dấu phẩy động được viết theo hai cách:

Cách 1 (dạng thập phân): Số gồm phần nguyên, dấu chấm thập phân và phần phân, ví dụ:

214.35 -4563.48 234.0

Chú ý: Phần nguyên hay phần phân có thể vắng mặt nhưng dấu chấm không thể thiếu, ví dụ cho phép viết:

.34 15.

Cách 2 (dạng khoa học hay dạng mũ): Số được tách thành 2 phần là định trị và phần bậc. Phần định trị là một số nguyên hoặc số thực dạng thập phân, phần bậc là một số nguyên. Hai phần này cách nhau bởi ký tự e hoặc E. Ví dụ:

123.456E-4 (biểu diễn giá trị 0.0123456)

0.12e3 (biểu diễn giá trị 120.0)

-49.5e-2 (biểu diễn giá trị -0.495)

1e8 (biểu diễn giá trị 100000000.0)

2.2.2 Hằng kiểu int Là hằng số nguyên có giá trị trong khoảng từ -32768 đến 32767.

Ví dụ:

Page 45: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

46

-45 4007 635 ...

Chú ý phân biệt 125 và 125.0. Số 125 là hằng nguyên còn 125.0 là hằng thực (dấu phảy động).

2.2.3 Hằng kiểu long Hằng kiểu long được biểu diễn bằng cách thêm L hoặc l vào cuối giá trị nguyên.

Ví dụ:

-4893L hoặc -4893l

Một số nguyên vượt ra ngoài miền xác định của int cũng được xem là hằng long.

Ví dụ:

4563946L và 4563946 là hai hằng long có cùng giá trị.

2.2.4 Biểu diễn hằng nguyên trong hệ 8 Có thể biểu diễn các hằng số nguyên theo hệ cơ số 8 bằng cách đặt số 0 ở đầu, khi đó các

chữ số phía sau phải nằm trong khoảng từ 0 đến 7. Hằng nguyên hệ 8 luôn luôn nhận giá trị dương.

Ví dụ:

0345

là một hằng nguyên hệ 8. Giá trị của nó trong hệ 10 là

3*8*8 + 4*8 + 5 = 229

2.2.5 Biểu diễn hằng nguyên trong hệ 16

Hệ cơ số 16 cần 16 ký tự để biểu diễn các chữ số, vì vậy ngoài các giá trị từ 0 đến 9, còn dùng các ký tự từ a (hoặc A) đến f (hoặc F) để biểu diễn. Hằng biểu diễn trong hệ 16 bắt đầu bằng 0x hoặc 0X.

Ví dụ:

0xa9 , 0Xa9 , 0xA9, 0XA9

Các hằng trên cùng biểu diễn một giá trị, trong hệ 10 là:

10*16 + 9 = 169

2.2.6 Biểu diễn hằng nguyên dạng ký tự

Có thể biểu diễn một giá trị nguyên trong khoảng từ 0 đến 255 bằng một ký tự đặt trong cặp dấu nháy đơn, khi đó giá trị của hằng bằng mã ASCII của ký tự đó.

Ví dụ:

'9' tương đương với 57

'a' tương đương với 97

Để biểu diễn một số hằng đặc biệt, người ta dùng cách biểu diễn với dấu \. Bảng sau chỉ ra cách biểu diễn một số hằng đặc biệt:

Cách viết Ký tự '\'' ' '\"' " '\\' \

Page 46: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

47

'\n' \n (chuyển dòng) '\0' \0 (null) '\t' Tab '\b' Backspace '\r' CR (về đầu dòng) '\f' LF (sang trang)

2.2.7 Hằng xâu ký tự Hằng xâu ký tự dùng để biểu diễn một dãy các ký tự, trong đó các ký tự được đặt trong

hai dấu nháy kép, ví dụ:

"Ha noi"

"Hai phong"

"" /* xâu rỗng */

Xâu ký tự được lưu trữ trong máy dưới dạng một mảng có các phần tử là các ký tự riêng biệt. Trình biên dịch tự động thêm ký tự \0 vào cuối mỗi xâu (ký tự \0 được xem là dấu hiệu kết thúc của một xâu ký tự).

Chú ý: Cần phân biệt 'a' và "a", 'a' là hằng nguyên được lưu trữ trong một byte, còn "a" là hằng xâu ký tự được lưu trữ trong một mảng hai phần tử: phần tử thứ nhất chứa mã chữ a còn phần tử thứ hai chứa \0.

2.2.8 Đặt tên cho hằng

Một số hằng có ý nghĩa định trước, ví dụ số pi. Trong trường hợp này, chúng ta có thể đặt cho hằng đó một cái tên, và thay vì viết trực tiếp hằng thì ta dùng tên của hằng trong các biểu thức. Để đặt tên cho hằng, dùng chỉ thị #include.

Ví dụ: #define MAX 1000 #define PI 3.141593

Khi đã đặt tên cho các hằng, chúng ta có thể sử dụng chúng trong các biểu thức, ví dụ: float r, s; r = 5.0f; s = PI*r*r;

2.3 Biến

2.3.1. Khai báo

Như đã đề cập ở 1.4.1, biến là đại lượng dùng để lưu trữ các giá trị trong quá trình tính toán. Mọi biến cần phải khai báo trước khi sử dụng. Việc khai báo biến được thực hiện theo mẫu sau:

<kiểu dữ liệu> <danh_sách_tên_biến>;

Tên các biến được đặt theo quy tắc đặt tên của TC được nêu trong 1.3, các biến trong danh sách được phân biệt nhau bởi dấu phẩy “,”.

2.3.2 Vị trí của các khai báo biến Các khai báo cần đặt ngay sau dấu { đầu tiên của thân hàm hoặc của khối lệnh và cần

đứng trước mọi câu lệnh khác. Như vậy, sau một câu lệnh gán chẳng hạn thì không được khai báo nữa . Sau đây là một ví dụ sai về vị trí của khai báo

Page 47: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

48

#include <stdio.h> void main () {

int a; a = 35; int d; /* Vị trí của khai báo sai */ d = a * 2; printf(“%d”, d);

}

2.3.3 Việc khởi đầu cho các biến Nếu trong khai báo, ngay sau tên biến ta đặt dấu = và một giá trị nào đó thì đây chính là

cách vừa khai báo vừa khởi đầu cho một biến.

Ví dụ: int a, b = 20, c ,d = 40; float e = -35.1, x =23.0, y, z, t =36.1;

Tất nhiên điều này có thể đạt được nhờ toán tử gán, và về thực tế hai cách này là tương đương. Vậy để đạt được ý định như ví dụ trên ta có thể dùng các câu lệnh:

int a, b, c, d; float e, x, y, z ,t; b = 20; d = 40; e = -35.1; x = 23.0; t = 36.1;

2.3.4 Cấp phát bộ nhớ cho biến Khi thực hiện chương trình, nếu máy gặp một khai báo biến nó sẽ thực hiện việc cấp phát

bộ nhớ cho biến gồm một số byte liên tiếp nhau tùy thuộc vào kiểu dữ liệu của biến. Ví dụ như biến kiểu int được cấp phát hai byte bộ nhớ, biến kiểu float được cấp phát 4 byte bộ nhớ….

2.3.5 Lấy địa chỉ của biến Mỗi biến được cấp phát một vùng nhớ gồm một số byte liên tiếp. Số hiệu của byte đầu

chính là địa chỉ của biến. Địa chỉ biến dùng trong một số hàm, như hàm scanf. Để nhận địa chỉ biến ta dùng phép toán:

& tên_biến

2.4 Mảng

2.4.1 Khái niệm về mảng, cách khai báo

Mỗi biến chỉ có thể chứa một giá trị. Để chứa một dẫy số hay một bảng số ta có thể dùng nhiều biến nhưng cách này không tiện lợi. Việc sử dụng mảng là cách tốt hơn nhiều trong những trường hợp như vậy .

Mảng có thể hiểu là một tập hợp nhiều phần tử có cùng một kiểu giá trị và có chung một tên . Mỗi phần tử mảng có vai trò như một biến và chứa được một giá trị . Có bao nhiêu kiểu biến thì cũng có bấy nhiêu kiểu mảng . Mảng cần được khai báo để định rõ:

- Kiểu mảng (int, float double,... )

- Tên mảng

- Số chiều và kích thước mỗi chiều.

Page 48: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

49

Khái niệm về kiểu mảng và tên mảng cũng giống như khái niệm kiểu biến và tên biến, điều này đã nói ở các mục trên. Ta sẽ giải thích khái niệm số chiều và kích thước mỗi chiều thông qua các ví dụ sau. Các khai báo:

int a[10], b[4][2]; float x[5], y[3][3];

sẽ xác định 4 mảng: a, b, x và y. ý nghĩa của chúng như sau:

- Đối với mảng thứ nhất thì kiểu là int, tên là a, số chiều là một, kích thước bằng 10. Mảng có 10 phần tử được đánh số như sau: a[0], a[1], a[2], ..., a[9]. Mỗi phần tử a[i] chứa được một giá trị kiểu int và mảng a có thể biểu diễn được một dẫy 10 số nguyên.

- Đối với mảng thứ hai thì kiểu là int, tên là b số chiều là 2. Kích thước của các chiều là 4 và 2. Mảng có 8 phần tử, chúng được đánh số và được sắp xếp như sau:

b[0][0] b[0][1] b[1][0] b[1][1] b[2][0] b[2][1] b[3][0] b[3][1]

Mỗi phần tử b[i][j] chứa được một giá trị kiểu int, và mảng b có thể biểu diễn được một bảng số nguyên 4 dòng, 2 cột.

- Đối với mảng thứ ba thì kiểu là float, tên là x, số chiều là một, kích thước bằng 5. Mảng có 5 phần tử được đánh số như sau:

x[0], x[1], x[2], x[3], x[4]

Mỗi phần tử x[i] chứa được một giá trị kiểu float, và mảng x có thể biểu diễn được một dẫy 5 số thực.

- Đối với mảng thứ 4 thì kiểu là float, tên là y, số chiều là 2, kích thước của các chiều là 3. Mảng có 9 phần tử, chúng được đánh số và được sắp xếp như sau:

y[0][0] y[0][1] y[0][2] y[1][0] y[1][1] y[1][2] y[2][0] y[2][1] y[2][2]

Mỗi phần tử y[i][j] chứa được một giá trị kiểu float, và mảng y có thể biểu diễn được một bảng số thực 3 dòng, 3 cột.

Chú ý:

- Các phần tử của mảng được cấp phát các khoảng nhớ liên tiếp nhau trong bộ nhớ. Nói cách khác, các phần tử mảng có địa chỉ liên tiếp nhau.

- Trong bộ nhớ, các phần tử của mảng hai chiều được sắp xếp theo hàng.

2.4.2 Chỉ số mảng Một phần tử cụ thể của mảng được xác định nhờ các chỉ số của nó. Chỉ số của mảng phải

có giá trị int không vượt quá kích thước của chiều tương ứng. Số chỉ số phải bằng số chiều của mảng.

Giả sử a, b, x, y đã được khai báo như trên và giả sử i, j là các biến nguyên trong đó i=2, j=1. Khi đó:

a[j+i-1] là a[2] b[j+i][2-i] là b[3][0] x[j/i] là x[0] y[i][j] là y[2][1]

Các cách viết sau là sai:

Page 49: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

50

y[j] vì y là mảng hai chiều, cần hai chỉ số

b[i][j][1] vì b là mảng hai chiều, chỉ cần hai chỉ số

2.4.3 Lấy địa chỉ phần tử mảng.

Dưới đây khi nói mảng ta hiểu là mảng một chiều. Mảng có từ hai chiều trở lên ta nói mảng kèm số chiều (ví dụ mảng hai chiều, ...). Có một vài hạn chế trên các mảng nhiều chiều. Chẳng hạn có thể lấy địa chỉ phần tử mảng một chiều, nhưng nói chung không cho phép lấy địa chỉ phần tử mảng nhiều chiều. Như vậy máy sẽ chấp nhận phép tính:

&a[i]

nhưng không chấp nhận phép tính &y[i][j]

2.5 Các phép toán trên các kiểu

2.5.1 Biểu thức Biểu thức là một sự kết hợp giữa các phép toán và các toán hạng để diễn đạt một công

thức toán học nào đó. Khi viết biểu thức có thể và nên dùng các dấu ngoặc tròn để thể hiện đúng trình tự tính toán trong biểu thức. Mỗi biểu thức sẽ có một giá. Hằng, biến, phần tử mảng và hàm cũng được xem là biểu thức. Trong C đưa ra nhiều quan niệm mới về biểu thức như biểu thức gán, biểu thức điều kiện.

Biểu thức được phân loại theo kiểu giá trị: nguyên và thực. Trong các mệnh đề logic, biểu thức được phân thành đúng (giá trị khác không) và sai (giá trị bằng 0).

2.5.2 Phép toán số học Các phép toán hai ngôi số học là:

Phép toán Ý nghĩa Ví dụ + Cộng a + b - Trừ a - b * Nhân a * b / Chia a / b

% Lấy phần dư a % b

Có phép toán một ngôi - ví dụ -(a+b) nhưng không có phép +. Phép chia hai số nguyên sẽ chặt cụt phần thập phân, ví dụ:

11/3 = 3

Phép toán % cho phần dư của phép chia nguyên, nó không áp dụng được cho các giá trị kiểu float và double. Ví dụ:

11%3 = 2

Các phép toán + và - có cùng số ưu tiên, và nhỏ hơn số ưu tiên của * / và %. Ba phép toán này lại có số thứ tự ưu tiên nhỏ hơn phép trừ một ngôi. Các phép toán số học được thực hiện từ trái sang phải.

Các phép toán số học dùng để viết các công thức toán học, ví dụ: (a*a-b*b)/(x*x+y*y)

2.5.3 Các phép toán so sánh

Page 50: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

51

Phép toán so sánh và logic cho ta hoặc giá trị đúng (1) hoặc giá trị sai (0). Nói cách khác, khi các điều kiện nêu ra là đúng thì ta nhận được giá trị 1, trong trường hợp trái lại, ta nhận được giá trị 0

Các phép toán so sánh cho trong bảng sau:

Phép toán ý nghĩa Ví dụ > Có lớn hơn không ? a>b

3>7 có giá trị 0 >= Có lớn hơn hay a>=b

bằng không ? 8>=8 có giá trị 1 < Có nhỏ hơn không? a<b

9<9 có giá trị 0 <= Có nhỏ hơn hay a<=b

bằng không ? 3<=10 có giá trị 1 == Có bằng nhau không? a==b

3==9 có giá trị 0 != Có khác nhau không a!=b

3!=9 có giá trị 1

Bốn phép đầu có cùng số ưu tiên, hai phép sau có cùng số thứ tự ưu tiên nhưng thấp hơn số thứ tự ưu tiên của bốn phép đầu.

Các phép so sánh có số ưu tiên thấp hơn so với các phép toán số học, cho nên biểu thức: i < n-1 được hiểu là: i < (n-1).

Nói chung, nên dùng các dấu ngoặc để tránh những lỗi do độ ưu tiên phép toán gây nên.

2.5.4 Phép toán logic Trong C sử dụng ba phép toán logic:

- Phép Phủ định một ngôi !

- Phép Và (AND) &&

- Phép Hoặc (OR) ||

Ý nghĩa của chúng được cho trong các bảng:

a !a Khác không 0 Bằng không 1

a b a&&b a||b

Khác không Khác không 1 1 Khác không Bằng không 0 1 Bằng không Khác không 0 1 Bằng không Bằng không 0 0

Trong đó a và b có thể nguyên hay thực.

Ví dụ:

3>7 có giá trị 0

7>3 có giá trị 1

3 && 7 có giá trị 1

Page 51: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

52

! 15.6 có giá trị 0

Các phép toán so sánh và logic được dùng để thiết lập điều kiện rẽ nhánh trong toán tử if và điều kiện kết thúc chu trình trong các toán tử for, while và do while. ở chương 5 sẽ có rất nhiều ví dụ về việc sử dụng các phép toán này

2.5.5 Chuyển kiểu Việc chuyển đổi kiểu giá trị thường diễn ra một cách tự động trong hai trường hợp sau:

- Khi biểu thức gồm các toán hạng khác kiểu.

- Khi gán một giá trị kiểu này cho một biến (hoặc phần tử mảng) kiểu kia. Điều này xẩy ra trong toán tử gán, trong việc truyền giá trị các tham số thực sự cho các đối (chương 5), trong câu lệnh return (chương 5).

Ngoài ra ta có thể chuyển từ một kiểu giá trị sang một kiểu bất kỳ mà ta muốn bằng phép ép kiểu:

(<Kiểu dữ liệu>) (<biểu thức>)

Ví dụ: (float)(a+b)

2.5.6 Các phép toán tăng giảm C đưa ra hai phép toán một ngôi để tăng và giảm các biến (nguyên và thực). Toán tử tăng

++ sẽ cộng 1 vào toán hạng của nó, toán tử giảm -- sẽ trừ đi 1. Chẳng hạn nếu n đang có giá trị bằng 5 thì:

Sau phép tính ++n, n có giá trị 6

Sau phép tính --n, n có giá trị 4

Dấu phép toán ++ và -- có thể đứng trước hoặc sau toán hạng, như vậy có thể viết:

++n n++ --n n--

Sự khác nhau của ++n và n++ ở chỗ: Trong phép n++ thì n tăng sau khi giá trị của nó đã được sử dụng, còn trong phép ++n thì n được tăng trước khi nó được sử dụng. Sự khác nhau giữa --n và n-- cũng như vậy.

Ví dụ: Nếu n bằng 5 thì câu lệnh

x = n++;

sẽ gán 5 cho x, còn câu lệnh

x = ++n;

sẽ gán 6 cho x. Trong cả hai trường hợp n đều trở thành 6.

Việc chọn phương án này hay phương án khác là tùy thuộc ngữ cảnh. Phép toán tăng giảm thường được sử dụng trong các toán tử for, while,... để tăng hay giảm giá trị cho các biến điều khiển. Rất nhiều ví dụ như vậy có thể tìm thấy trong các chương sau.

Cuối cùng, một điều cần lưu ý là không nên sử dụng toán tử tăng giảm quá tùy tiện trong các biểu thức, vì việc đó có thể dẫn đến các kết quả sai.

2.5.7 Biểu thức điều kiện Biểu thức điều kiện là biểu thức có dạng:

<biểu thức kiểm tra> ? <biểu thức 1> : <biểu thức 2>

Page 52: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

53

Giá trị của biểu thức điều kiện bằng giá trị của biểu thức 1 nếu biểu thức kiểm tra đúng (khác không) và bằng giá trị của biểu thức 2 nếu biểu thức kiểm tra sai (bằng không).

Ví dụ:: printf("\n %8.2f", a < b ? a : b);

đưa ra giá trị nhỏ nhất của hai biến thực a và b.

2.5.8 Câu lệnh gán và biểu thức gán

Biểu thức gán là biểu thức có dạng: <biến> = <biểu thức>

Vế trái của biểu thức là một biến (hay phần tử mảng), vế phải là một biểu thức. Giá trị của biểu thức gán là giá trị được gán. Nếu đặt dấu ; vào sau biểu thức gán thì ta được lệnh gán:

<biến> = <biểu thức>;

Biểu thức gán có thể sử dụng trong các phép toán và các câu lệnh như các biểu thức khác. Ví dụ, khi viết

a = b = 5;

thì điều đó có nghĩa là gán giá trị của biểu thức b = 5

cho biến a. Kết qủa là b=5 và a=5.

Một số dạng khác của toán tử gán. Trong trường hợp các biểu thức gán có dạng như:

i = i+2;

trong đó vế trái được lặp lại có thể viết gọn hơn như sau: i += 2;

Các biểu thức gán này có dạng: <biến> <phép toán> = <biểu thức>;

Trong đó <phép toán> là một phép toán hai ngôi.

Ví dụ câu lệnh: x = x*(y+3);

có thể viết thành: x *= y+3;

2.5.9 Thứ tự ưu tiên các phép toán

Các phép toán có độ ưu tiên khác nhau, điều này có nghĩa là trong cùng một biểu thức một số phép toán này được thực hiện trước một số phép toán khác. Thứ tự ưu tiên của các phép toán được trình bầy trong bảng sau.

Stt Phép toán Trình tự kết hợp 1 () [] -> . Trái qua phải 2 ! ~ & * - ++ -- (type) sizeof Phải qua trái 3 * (phép nhân) / % Trái qua phải 4 + - Trái qua phải 5 < <= > >= Trái qua phải 6 == != Trái qua phải

Page 53: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

54

7 && Trái qua phải 8 || Trái qua phải 9 ? : Phải qua trái 10 = += -= *= /= %= <<= >>= &= ^= |= Phải qua trái 11 , Trái qua phải

Giải thích: - Các phép toán trên một dòng có cùng thứ tự ưu tiên, các phép toán ở hàng trên có

số ưu tiên cao hơn các phép toán ở hàng dưới.

- Đối với các phép toán cùng mức ưu tiên thì trình tự tính toán có thể từ trái qua phải hay ngược lại. Điều này chỉ ra trong cột "Trình tự kết hợp".

- Để viết biểu thức một cách chính xác nên sử dụng các dấu ngoặc tròn.

2.6 Một số hàm thường dùng Độc giả xem chi tiết danh mục các hàm trong phụ lục 2 của bài giảng. Tại đây chúng tôi

chỉ trích giới thiệu một số ít các hàm thường dùng.

2.6.1 Hàm toán học

Các hàm thuộc thư viện math.h hoặc trong stdlib.h

1. abs – Tính giá trị tuyệt đối của số nguyên x int abs(int x);

2. labs-Tính giá trị tuyệt đối của số nguyên dài x long int labs(long int x) 3. cos – Tính cosine của x double cos(double x) 4. exp – Tính e mũ x double exp(double x) 5. fabs-Tính giá trị tuyệt đối của x double fabs(double x) 6. log – Tính logarit cơ số tự nhiên của x double log(double x) 7.log10 - Tính logarit cơ số10 của x double log10(double x) 8. pow – Tính x mũ y double pow(double x, double y) 9. sin – Tính sine của x double sin(double x) 10. sqrt – Tính căn bậc hai của x

double sqrt(double x)

2.6.2 Hàm xử lý chuỗi ký tự Các hàm khai báo trong string.h

1. strcmp: so sánh 2 chuỗi s1, s2 phân biệt chữ thường và chữ hoa int strcmp(char * s1, char *s2) 2. strcmpi: so sánh 2 chuỗi không phân biệt chữ thường và chữ hoa int strcmpi(char *s1, char *s2) 3. strcpy : sao chép chuỗi int strcpy(char *dest, char *sour) 4. stricmp: giống hàm strcmpi

Page 54: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

55

5. strlen: tính độ dài của chuỗi 6. strrev: đảo ngược 1 chuỗi

Các hàm strcmpi và strcpy sẽ được dùng trong các bài tập ở chương 6 mục 6.6

2.6.3 Các hàm chuyển đổi dữ liệu Các hàm khai báo trong ctype.h

1. atof: chuyển 1 chuỗi sang giá trị double 2. atoi: chuyển 1 chuỗi sang giá trị int 3. atol: chuyển 1 chuỗi sang giá trị long 4. itoa: chuyển số nguyên int sang chuỗi 5. ltoa: chuyển giá trị long dang chuỗi

BÀI TẬP CHƯƠNG 2 Bài 1. Tìm các chỗ sai trong chương trình sau

#include "stdio.h" void main() {

printf("\na=%10.0f, b=%10d, c=%10ld, d=%10d", -3456, 25e3, 4635, 456398461);

}

Sửa lại cho đúng rồi thực hiện trên máy.

Bài 2. Viết chương trình in một dòng với nội dung sau: N = 365

Bằng cách sử dụng các loại hằng khác nhau (hằng số dấu phẩy động, hằng int, hằng long, hằng int hệ 8, hằng int hệ 16, hằng kí tự, hằng xâu kí tự).

Bài 3. Tìm các chỗ sai trong đoạn chương trình float a[3], b = 2; a[0] = 5; a[10] = 4, a[b] = 7;

Bài 4. Tìm các chỗ sai trong đoạn chương trình {

int a = 6; float b=5.3; {

float x = a*b, y=a+b; } printf("\na=%10.2f, b=%10.2f, x=%10.2f,

y=%10.2f ", a, b, x, y); }

Sửa chữa bổ sung để được một chương trình hoàn chỉnh sau đó thực hiện trên máy.

Page 55: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

56

CHƯƠNG 3 - CÁC LỆNH ĐIỀU KHIỂN

Một chương trình bao gồm nhiều câu lệnh. Thông thường các câu lệnh được thực hiện một cách lần lượt theo thứ tự mà chúng được viết ra. Các lệnh điều khiển cho phép thay đổi trật tự nói trên, do đó máy có thể đang từ một câu lệnh này nhảy tới thực hiện một câu lệnh khác ở trước hoặc sau nó. Đường đi của máy trở nên linh hoạt hơn và nhờ vậy ta có thể viết chương trình một cách hiệu quả hơn. Xét về mặt công dụng có thể chia các lệnh điều khiển thành ba nhóm chính:

- Nhảy không điều kiện (goto)

- Rẽ nhánh (if, switch )

- Tổ chức chu trình (for, while,do while)

Ngoài ra còn có một số lệnh khác có chức năng bổ trợ như break, continue.

Chương này sẽ giới thiệu cách viết và các nguyên tắc hoạt động của một số lệnh nêu trên. Chúng ta sẽ thấy các lệnh điều khiển của C có những khả năng làm việc rất linh hoạt, phong phú và mạnh mẽ. Tất cả những điều này được giải thích tỉ mỉ và được minh họa rõ ràng trên nhiều chương trình hoàn chỉnh đã thử nghiệm trên máy.

3.1 Nhắc lại khái niệm về câu lệnh và khối lệnh Trong C mỗi câu lệnh có thể viết trên một hoặc nhiều dòng và được kết thúc bằng dấu

chấm phảy. Khái niệm về khối lệnh hay câu lệnh hợp thành đã trình bày ở mục 1.4.4, ở đây ta chỉ nhắc lại vài điều.

- Khối lệnh là một dẫy các câu lệnh đặt trong các dấu { }.

- Không được đặt dấu chấm phảy sau dấu ngoặc nhọn kết thúc khối.

- Khối lệnh tương đương với câu lệnh riêng lẻ về mặt cú pháp. Nói cách khác, chỗ nào đặt được một câu lệnh thì ở chỗ đó ta cũng có quyền viết một khối lệnh.

- Khi khối lệnh chỉ gồm một câu lệnh thì có thể bỏ các dấu ngoặc nhọn đầu và cuối. Nói cách khác có thể xem câu lệnh là trường hợp riêng của khối lệnh.

Dưới đây khi trình bầy các lệnh điều khiển như if, for, while, ..., ta dùng thuật ngữ "khối lệnh", nhưng mọi điều vẫn đúng nếu ta dùng "câu lệnh" (vì câu lệnh xem như trường hợp riêng của khối lệnh).

3.2. Lệnh if Lệnh if cho phép lựa chọn để thực hiện một trong hai nhánh tùy thuộc vào điều kiện đúng

(khác không) hay sai (bằng không) của một biểu thức, gọi là biểu thức điều kiện. Mỗi nhánh của lệnh if là một khối lệnh khác nhau.

3.2.1 Cú pháp của if

Lệnh if có hai dạng sau:

Dạng 1 if (<biểu thức điều kiện>)

<khối lệnh>

Dạng 2 if (<biểu thức điều kiện>)

Page 56: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

57

<khối lệnh 1> else

<khối lệnh 2>

Trong cú pháp trên, biểu thức điều kiện có thể là một biểu thức bất kỳ. Các khối lệnh có thể là một câu lệnh đơn, khi đó kết thúc câu lệnh phải có dấu chấm phẩy.

Lệnh if dạng 1 dùng khi cần kiểm tra điều kiện xem có hay không thực hiện một khối lệnh nào đó.

Lệnh if dạng 2 dùng khi muốn lựa chọn một trong hai khối lệnh để thực hiện.

3.2.2 Hoạt động của if

Sự hoạt động của lệnh if dạng 1 Khi gặp câu lệnh này, máy sẽ tính giá trị của biểu thức. Nếu biểu thức đúng thì máy thực

hiện khối lệnh và sau đó thực hiện các lệnh tiếp theo. Nếu biểu thức sai thì máy bỏ qua khối lệnh và chuyển đến các lệnh viết sau nó.

Sự hoạt động của lệnh if dạng 2 Trước tiên máy sẽ xác định giá trị của biểu thức. Nếu biểu thức đúng máy sẽ thực hiện

khối lệnh 1, sau đó nhẩy tới các lệnh viết sau khối lệnh 2. Nếu biểu thức thì máy sẽ không thực hiện khối lệnh 1 mà chỉ thực hiện khối lệnh 2 và sau đó thực hiện các lệnh viết sau nó.

Ví dụ sau minh hoạ cho hoạt động của câu lệnh if. Để tính giá trị lớn nhất của hai biến a và b ta có thể sử dụng hai chương trình ứng với hai dạng khác nhau của lệnh if.

/* Chuong trinh tinh max cua hai so thuc, dung if dang 1 */ #include <stdio.h> void main() {

float a,b,max; int k; printf("\nVao hai so a va b: "); scanf("%f%f", &a, &b);/*gia tri cua a va b nhan tu ban phim*/ max = a; if (b > max) max = b; printf("\na = %8.2f\nb = %8.2f\nmax = %8.2f", a, b, max );

} /* Chuong trinh tinh max cua hai so thuc, dung if dang 2 */ #include <stdio.h> void main() {

float a,b,max; int k; printf("\nVao hai so a va b: "); scanf("%f%f",&a,&b);/*gia tri cua a va b nhan tu ban phim */ if (a > b) max = a; else max = b; printf("\na = %8.2f\n b = %8.2f\n max = %8.2f", a, b, max);

}

3.2.3 Sự lồng nhau của lệnh if Các lệnh if có thể lồng nhau. Điều đó có nghĩa là: các khối lệnh 1 và khối lệnh 2 (xem

dạng 1 và dạng 2) lại có thể chứa các lệnh if khác.

Page 57: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

58

Trong trường hợp có nhiều if và else, thì một vấn đề quan trọng là chúng ta phải xác định được mệnh đề else nào thuộc if nào. Có một nguyên tắc để xác định, đó là: mệnh đề else sẽ được gắn với if gần nhất trước nó.

Tuy nhiên, để tránh nhầm lẫn, nên dùng cặp ngoặc {}.

Sau đây là ví dụ giải phương trình bậc nhất ax + b = 0 sử dụng if lồng nhau. #include <stdio.h> void main() { float a, b; printf("Nhap a, b: "); scanf("%f%f", &a, &b); if (a == 0) if (b == 0) printf("Vo so nghiem."); else printf("Vo nghiem."); else printf("x = %f", -b/a); }

Để lựa chọn một trong nhiều trường hợp, ta có thể dùng lệnh if lồng nhau. Ví dụ, với chương trình giải phương trình bậc 2, giá trị của delta có thể rơi vào các trường hợp: lớn hơn 0, bằng 0 và nhỏ hơn 0.

Với các trường hợp này, câu lệnh if – else viết có phần hơi khác bình thường, bằng cách đặt câu lệnh if con nằm cùng hàng với else trước đó.

Sau đây là ví dụ giải phương trình bậc 2 sử dụng if lồng nhau. #include <stdio.h> #include <math.h> void main() { float a, b, c, delta; printf("Nhap a, b, c: "); scanf("%f%f%f", &a, &b, &c); delta = b*b - 4*a*c; if (delta < 0) printf("Vo nghiem."); else if (delta == 0) printf("x = %f", -b/(2*a)); else //if (delta > 0) printf("x1 = %f\nx2 = %f", (-b - sqrt(delta))/(2*a), (-b + sqrt(delta))/(2*a)); }

Chú ý đối với trường hợp cuối cùng có thể không cần if, như ở ví dụ trên.

3.2.4 Viết chương trình theo cấu trúc Để chương trình rõ ràng, dễ kiểm tra và tránh nhầm lẫn, ta nên viết chương trình theo các

quy tắc sau:

- Các câu lệnh và khối lệnh nằm trong một lệnh điều khiển thì viết tụt vào bên phải.

- Các câu lệnh và khối lệnh cùng cấp thì viết trên cùng một cột (thẳng cột).

- Điểm đầu và điểm cuối của một khối lệnh cũng thẳng cột.

Page 58: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

59

Các chương trình và đoạn chương trình trong tài liệu này đều viết có cấu trúc.

3.3 Lệnh for Lệnh for cho phép thực hiện một khối lệnh một số lần xác định. Lệnh for thường dùng để

giải các bài toán có tính chu trình, ví dụ như các bài toán về dãy số, về ma trận.

3.3.1 Cú pháp của for

Lệnh for có dạng sau: for (<biểu thức khởi tạo>; <biểu thức kiểm tra>; <biểu thức tăng>)

<khối lệnh>

Trong cú pháp trên:

- for: từ khoá của lệnh for.

- biểu thức khởi tạo, biểu thức kiểm tra và biểu thức tăng bắt buộc phải được trong cặp ngoặc tròn và cách nhau bởi dấu chấm phẩy. Các biểu thức này có thể vắng mặt, nhưng vẫn phải đủ các dấu chấm phẩy.

- Khối lệnh, còn được gọi là phần thân của lệnh for là khối lệnh cần thực hiện nhiều lần.

Thông thường, biểu thức khởi tạo thường được dùng để khởi tạo giá trị cho các biến điều khiển, biểu thức tăng dùng để thay đổi giá trị của biến điều khiển.

3.3.2 Hoạt động của for

Lệnh for làm việc theo các bước sau:

- Bước 1. Tính giá trị biểu thức khởi tạo.

- Bước 2. Tính giá trị của biểu thức kiểm tra. Nếu đúng, tới bước 3, ngược lại thoát khỏi lệnh for.

- Bước 3. Thực hiện khối lệnh.

- Bước 4. Tính giá trị biểu thức tăng, sau đó quay trở lại bước 2.

Chú ý: - Nếu biểu thức kiểm tra vắng mặt thì nó được xem là đúng. Để tránh lặp vô tận,

trong phần thân của for phải có lệnh nhảy ra khỏi for bằng các lệnh break, return hoặc goto.

- Các biểu thức trong lệnh for có thể là một biểu thức ghép, tức là gồm nhiều biểu thức cách nhau bởi dấu phẩy. Trong trường hợp đó, tính đúng sai được xác định theo biểu thức cuối cùng trong biểu thức ghép.

3.3.3 Ví dụ minh hoạ

Ví dụ 1: Đảo ngược một dẫy số cho trước. /* Chuong trinh dao nguoc mot day so */ #include <stdio.h> float x[] = { 63.2, -45.6, 70.1, 3.6, 14.5}; int n = sizeof(x)/sizeof(float); void main() {

int i, j; float c; for(i = 0, j = n - 1; i < j; i++, j--)

Page 59: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

60

{ c = x[i]; x[i] = x[j]; x[j] = c; } printf("\nDay ket qua: \n"); for(i = 0; i < n; i++) printf(“%8.2f", x[i]);

}

Ví dụ 2: Chương trình dưới đây giải quyết bài toán tìm giá trị lớn nhất và nhỏ nhất trên mỗi hàng của ma trận. Trong chương trình sử dụng các chu trình lồng nhau.

#include <stdio.h> float a[3][4] = { {15.0f, 46.0f, 3.5f, 6.3f}, {34.0f, 0.0f, -25.0f, 35.0f} , { 1.0f, -13.0f, 46.0f, -38.0f}}; void main() { int i, j; float max, min; for (i = 0; i < 3; i++) { max = a[i][0]; min = a[i][0]; for (j = 0; j < 4; j++) { if (max < a[i][j]) max = a[i][j]; if (min > a[i][j]) min = a[i][j]; } printf("Gia tri lon nhat va nho nhat cot %d la %.2f va %.2f\n", i + 1, max, min); } }

Ví dụ 3: Chương trình nhập một dẫy số, và in ra màn hình dãy vừa nhập. #include <stdio.h> void main() { float a[100]; int n, i ; printf("\nSo phan tu cua day: "); scanf("%d", &n); for (i = 0; i < n; i++) { printf("Phan tu thu %d: ", i + 1); scanf("%f", &a[i]); } printf("Day so vua nhap:\n"); for (i = 0; i < n; i++) printf("%8.2f", a[i]); }

Ví dụ 4: Chương trình dưới đây sẽ nhập một ma trận thực cấp MxN sau đó tính các tổng cột của ma trận.

#include <stdio.h>

Page 60: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

61

#include <conio.h> void main() { float a[20][20], tc, tg; int m, n, i, j; printf("\nNhap so hang va so cot cua ma tran: "); scanf("%d%d", &m, &n); for (i = 1; i<= m; i++) for (j = 1; j <= n; j++) { printf("a[%d][%d] = ", i, j); scanf("%f", &tg); a[i][j] = tg ; } /* Tinh tong cot */ for (j = 1; j <= n; j++) { tc = 0; for (i = 1; i <= m; ++i) tc += a[i][j] ; printf ("\nTong cot %d = %.1f", j, tc); } }

3.4 Lệnh while Lệnh while cho phép thực hiện một khối lệnh nhiều lần. Thông thường while sử dụng

trong các trường hợp mà số lần lặp không xác định trước.

3.4.1 Cú pháp của while Cú pháp của while có dạng: while (<biểu thức kiểm tra>) <khối lệnh>

Trong cú pháp trên:

- while: từ khoá của lệnh while.

- Biểu thức kiểm tra: bắt buộc phải đặt trong cặp ngoặc tròn.

- Khối lệnh, còn gọi là phần thân của while, là khối lệnh cần thực hiện nhiều lần.

3.4.2 Hoạt động của while.

Lệnh while làm việc theo các bước sau:

- Bước 1: Tính giá trị của biểu thức kiểm tra. Nếu biểu thức đúng, sang bước 2, ngược lại thoát khỏi lệnh while.

- Bước 2: Thực hiện khối lệnh, sau đó quay trở lại bước 1.

Nhận xét: Thân của while có thể được thực hiện một lần hoặc nhiều lần và cũng có thể không được thực hiện lần nào nếu ngay từ đầu biểu thức kiểm tra đã sai.

Chú ý:

Page 61: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

62

- Để tránh lặp vô tận, trong phần thân của while cần có lệnh làm thay đổi giá trị biểu thức kiểm tra, và cần đảm bảo tới một lúc nào đó thì biểu thức kiểm tra sẽ sai.

- Biểu thức kiểm tra có thể là một biểu thức ghép, tức là gồm một dãy các biểu thức cách nhau bởi dấu phẩy. Tính đúng sai được xác định dựa vào biểu thức cuối cùng trong dãy.

3.4.3 Ví dụ minh hoạ Ví dụ 1: Tính tích vô hướng của hai véc tơ x và y. /* Chương trinh tinh tich vo huong */ #include <stdio.h> float x[] = {4.0f, 6.0f, 8.0f, 3.5f}; float y[] = {2.6f, 3.2f, 4.0f, 7.0f}; void main() { float s; int i; s = 0; i = 0; while (i < 4) { s += x[i]*y[i]; i += 1; } printf("\nTich vo huong = %.2f", s); }

Ví dụ 2: Chương trình dưới đây sẽ tìm số nguyên dương n nhỏ nhất sao cho:

1 + 2 + ... + n > 10000. #include <stdio.h> void main() { float s; int n; s = 0; n = 0; while (s <= 1000) s += ++n; printf("\nN = %d", n); }

Ví dụ 3: Tìm phần tử âm đầu tiên trong một dãy số nguyên. #include <stdio.h> int a[] = {2, 34, 16, -5, 43, 27}; void main() { int i, n; i = 0; n = 6; while ((i < n) && (a[i] >= 0)) i++; if (i < n) printf("Phan tu am a[%d] = %d", i, a[i]); else printf("Khong co phan tu am."); }

Page 62: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

63

3.5 Lệnh do - while Trong các lệnh while và for, việc kiểm tra điều kiện kết thúc đặt ở đầu chu trình. khác với

hai lệnh trên, trong chu trình do while việc kiểm tra điều kiện kết thúc đặt cuối chu trình. Như vậy thân của chu trình bao giờ cũng được thực hiện ít nhất một lần.

3.5.1 Cú pháp của do – while

Lệnh do - while có dạng sau: do <khối lệnh> while (<biểu thức kiểm tra>);

Tron cú pháp trên:

- do, while là các từ khoá của lệnh do – while.

- Khối lệnh, còn gọi là phần thân của do – while là khối lệnh cần thực hiện nhiều lần.

- Biểu thức kiểm tra phải đặt trong cặp ngoặc tròn.

3.5.2 Hoạt động của do while.

Lệnh do – while thực hiện như sau:

- Bước 1: Thực hiện khối lệnh.

- Bước 2: Tính giá trị biểu thức kiểm tra. Nếu đúng, quay trở lại bước 1, ngược lại, thoát khỏi lệnh do – while,

3.5.3 Ví dụ minh hoạ Ví dụ : Tính căn bậc hai của một số nguyên a, thuật toán như sau:

x(0) = a

x(n+1) = ( x(n)*x(n) + a ) / ( 2*x(n) ) , với n>=0

Quá trình lặp kết thúc khi

| (x(n+1) - x(n)) / x(n)| < 0.00001

Khi đó x(n+1) được xem là giá trị gần đúng của căn a.

Thuật toán trên được chương trình hoá như sau. /* Chuong trinh tinh can bac hai */ #include <stdio.h> #include <math.h> void main() { double a, x, c; printf("\na = "); scanf("%lf", &a); x = a; do { c = x; x = (x*x + a)/(2*x); } while (fabs((x-c)/c) >= 1e-5); printf("Can bac hai cua %.4f la %.4f", a, x); }

Page 63: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

64

3.6 Lệnh break Khi sử dụng các lệnh lặp như for, while hay do – while ở các ví dụ trên, điều kiện thoát ra

khỏi các vòng lặp này là biểu thức kiểm tra sai. Tuy nhiên, trong một vài trường hợp, ta muốn thoát ra khỏi các vòng lặp này ngay tức thời, khi đó có thể sử dụng lệnh break.

3.6.1 Cú pháp của break

Lệnh break có dạng sau: break;

Ghi chú: - Lệnh break có thể được đặt ở bất cứ đâu trong thân của các lệnh lặp.

- Khi có nhiều lệnh lặp lồng nhau, lệnh break chỉ thoát ra khỏi lệnh lặp trong cùng.

3.6.2 Hoạt động của break Khi gặp break, máy sẽ bỏ qua các lệnh còn lại trong phần thân của lệnh lặp, dừng lặp và

thoát ra khỏi lệnh lặp.

3.6.3 Ví dụ minh hoạ Chương trình tìm phần tử âm đầu tiên của một ma trận dưới đây sẽ minh họa cách sử

dụng các chu trình lồng nhau và cách dùng break để ra khỏi chu trình. /* Chuong trinh tim phan tu am dau tien cua ma tran dùng break */ #include <stdio.h> float a[3][4] = {

{15.0f, 46.0f, 3.5f, 6.3f}, {34.0f, 0.0f, -25.0f, 35.0f} , { 1.0f, -13.0f, 46.0f, -38.0f}};

void main() { int i, j; for (i = 0; i < 3; i++) { for (j = 0; j < 4; j++) if (a[i][j] < 0) break; /* ra khoi for j */ if ( j < 4) break; /* ra khoi for i */ } if ((i < 3)&&(j < 4))

printf("\nPhan tu am dau tien la a(%d,%d) = %.2f", i + 1, j + 1, a[i][j]); else

printf("\nMa tran khong co phan tu am."); }

3.7 Lệnh continue Lệnh continue dùng để bắt đầu lại một chu trình.

3.7.1 Cú pháp của continue

Lệnh continue có dạng: continue;

Ghi chú:

Page 64: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

65

- Lệnh continue chỉ sử dụng trong các lệnh lặp.

- Lệnh continue có thể đặt bất cứ đâu trong phần thân của lệnh lặp.

- Khi có nhiều lệnh lặp lồng nhau, lệnh continue chỉ có tác dụng đối với lệnh lặp trong cùng.

3.7.2 Hoạt động của continue Khi gặp continue, máy sẽ bỏ qua các lệnh còn lại trong phần thân của lệnh lặp và quay lại

bặt đầu vòng lặp mới.

Đối với while và do – while, vòng lặp mới bắt đầu từ bước tính biểu thức kiểm tra.

Đối với for, vòng lặp mới bắt đầu từ bước tính biểu thức tăng.

3.7.3 Ví dụ minh hoạ Cho ma trận a, viết chương trình để từ một ma trận a cho trước:

- Tính tổng các phần tử dương của a.

- Xác định số phần tử dương của a.

- Tìm giá trị lớn nhất của các phần tử dương của A. #include <stdio.h> float a[][4] = { { 25.0f, 0.0f, -3.0f, 5.0f}, { -6.0f, 4.0f, 0.0f, -2.0f}, { 30.0f, -4.0f, 7.0f, -3.0f}}; void main() { int i, j, demD; float tongD, maxD; demD = 0; tongD = 0; maxD = 0; for (i = 0; i < 3; i++) for(j = 0; j < 4; j++) { if(a[i][j] <= 0) continue; ++demD; tongD += a[i][j]; if (maxD < a[i][j]) maxD = a[i][j]; } printf("\nSo phan tu duong la: %d", demD); printf("\nTong cac phan tu duong la: %.2f", tongD); printf("\nMax cac phan tu duong la: %.2f", maxD); }

BÀI TẬP CHƯƠNG 3 Bài 1. Lập chương trình giải hệ phương trình:

ax + by = c

dx + ey = f

các hệ số a, b, c, d, e, f nhận từ bàn phím . yêu cầu xét tất cả các trương hợp có thể.

Page 65: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

66

Bài 2. Lập chương trình để:

- Nhập một dãy số từ bàn phím.

- Tính trung bình cộng của các số dương và trung bình cộng của các số âm trong dãy số trên.

Bài 3. Lập chương trình tính ex theo công thức xấp xỉ

e x x xn

xn

= + + + +11 2

2

!...

!

với độ chính xác 0.00001. Tức là n cần chọn sao cho

xn

n

!.< 0 00001

Bài 4. Lập chương trình tính sin(x) với độ chính xác 0.0001 theo công thức:

sin( )! !

... ( )( )!

x x x x xn

nn

= − + + + −−

−3 5 2 1

3 51

2 1

Bài 5. Lập chương trình vào bốn dãy số a1, ..., an, b1, ..., bn, c1, ..., cn, d1, ..., dn. In kết quả trên n dòng , mỗi dòng 5 giá trị theo mẫu sau:

ai bi ci di min(ai,bi,ci,di) max(ai,bi,ci,di)

Bài 6. Lập chương trình tính tổ hợp chập m của n

C m n n n n mm

( , ) .( ) ...( )!

=− − +1 1

Bài 7. Lập chương trình để in một dãy n số thực x1,..., xn trên nhiều dòng, mỗi dòng gồm m số (dòng cuối cùng có thể ít hơn). Các giá trị m, n và x1,..., xn nhận từ bàn phím.

Bài 8. Nhập các hệ số a1 ,..., an từ bàn phím sau đó in hàm f(x) trên một dòng theo mẫu sau:

f(x) = a1x1 + ... + anxn

Bài 9. Lập chương trình tính 5.022

221 )...( naaaS +++=

trong đó n và a1,...,an nhận từ bàn phím.

Bài 10. Cần có tổng số 200000đ từ 3 loại giấy bạc 1000đ, 2000đ và 5000đ. Lập chương trình để tìm tất cả các phương án có thể.

Bài 11. Lập chương trình tìm phần tử âm cuối cùng của dãy a1,...,an.

Bài 12. Cho hai dãy số: a1,...,an và b1,...,bm, cả hai đều xếp theo thứ tự tăng. Lập chương trình trộn hai dãy trên thành một dãy mới cũng theo thứ tự tăng.

Bài 13. Cho dãy số a1,...,an. Lọc các số dương đưa vào mảng b, các số âm đưa vào mảng c.

Bài 14. Sắp xếp một dãy số theo thứ tự tăng dần.

Bài 15. Cho dãy số a1,...,an. Lập chương trình in các số âm trên một dòng, các số dương trên dòng tiếp theo.

Bài 16. Cho hiện lên màn hình các kí tự có mã ASCII từ 33 đến 255.

Bài 17. Viết chương trình tính giá trị của đa thức và đạo hàm của nó.

Page 66: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

67

Bài 18. Viết chương trình tính định thức của ma trận vuông cấp n.

Bài 19. Viết chương trình nhập toạ độ x, y của một dẫy n điểm, sau đó tìm một cặp điểm cách xa nhau nhất.

Page 67: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

68

CHƯƠNG 4 - HÀM VÀ TỔ CHỨC CHƯƠNG TRÌNH

Một chương trình viết theo ngôn ngữ C là một dãy các hàm trong đó có một hàm chính (hàm main). Thứ tự của các hàm trong chương trình là bất kỳ nhưng chương trình bao giờ cũng được thực hiện từ hàm main. Mỗi hàm sẽ thực hiện một phần việc nào đó và chương trình sẽ giải quyết cả bài toán trọn vẹn. Một trong các ưu điểm của C là nó cho phép tổ chức và sử dụng các hàm một cách đơn giản và hiệu quả. Chương này sẽ giới thiệu các qui tắc xây dựng và sử dụng hàm.

4.1 Tổ chức chương trình thành các hàm

4.1.1. Khái niệm chung về hàm Xét bài toán đơn giản sau: Tìm giá trị lớn nhất của ba số mà giá trị của chúng được đưa

vào từ bàn phím. Ta tổ chức chương trình thành hai hàm: hàm main và một hàm mà ta đặt tên là max3s. Nhiệm vụ của hàm max3s là tính giá trị lớn nhất của ba số giả định mà ta gọi là a, b, c. Nhiệm vụ của hàm main là đọc ba giá trị từ bàn phím, dùng hàm max3s để tính max của ba giá trị vừa đọc được, đưa kết qủa ra màn hình. Chương trình được viết như sau.

#include <stdio.h> /* Nguyen mau ham max3s */ float max3s(float a,float b,float c); void main() { float x, y, z; printf("\nNhap ba so thuc: "); scanf("%f%f%f", &x, &y, &z); printf("\nx = %0.2f\ny = %0.2f\nz= %0.2f\nmax = %0.2f", x, y, z, max3s(x, y, z)); } /* Dinh nghia ham max3s */ float max3s(float a, float b, float c) { float max; max = a>b?a:b; return (max>c?max:c); /* Gia tri tra ve */ }

Ghi chú:

- Nên khai báo nguyên mẫu của hàm trước khi sử dụng hàm.

- Nguyên mẫu của hàm thực chất là dòng đầu của hàm và thêm vào dấu chấm phẩy. Tuy nhiên trong nguyên mẫu có thể bỏ tên các đối.

Qua chương trình này có thể rút ra nhiều khái niệm và qui tắc quan trọng liên quan đến việc xây dựng và sử dụng hàm:

- Mỗi hàm phải có một tên. Ta có thể đặt cho mỗi hàm một tên bất kỳ theo các qui tắc nêu trong chương 1.

- Trong cùng một chương trình, các hàm phải có tên khác nhau và mặc dù tên là tùy ý nhưng ta cũng nên đặt cho hàm những tên phù hợp với chức năng của hàm.

- Hàm thường có một vài đối. Ví dụ hàm max3s có ba đối là a, b, c. Cả ba đối này đều có kiểu giá trị float. Cũng có hàm không đối như hàm main trong các ví dụ trên, khi đó vẫn phải có cặp dấu ngoặc tròn.

Page 68: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

69

- Hàm thường cho ta một giá trị nào đó. Ví dụ, hàm max3s cho giá trị lớn nhất của ba đối của nó. Giá trị của hàm có thể có kiểu int, float, double, ... . Hàm max3s có giá trị kiểu float. Ngoài ra còn có những hàm không có giá trị trả về, khi đó khai báo kiểu trả về của hàm là void.

4.1.2 Quy tắc xây dựng một hàm Hàm có thể xem là một đơn vị độc lập của chương trình. Trong C không cho phép xây

dựng một hàm bên trong các hàm khác. Hàm được viết theo thứ tự sau:

Nguyên mẫu hàm

Nguyên mẫu hàm cho biết tên hàm, các đối của hàm và kiểu giá trị trả về. Việc khai báo nguyên mẫu hàm cho phép sử dụng hàm trước khi định nghĩa hàm.

Nguyên mẫu hàm khai báo theo mẫu sau: <kiểu> <tên_hàm>(

<kiểu 1> [<đối1>, <kiểu 2> [<đối 2>], …, <kiểu n> [<đối n>]

);

Như vậy, nguyên mẫu của hàm khai báo những thông tin tối thiểu nhất của hàm để có thể sử dụng được hàm đó.

Trong trường hợp hàm được định nghĩa trước khi sử dụng, thì không cần thiết phải khai báo nguyên mẫu.

Định nghĩa hàm Định nghĩa hàm gồm hai phần: tiêu đề và thân hàm. Xét ví dụ về hàm max3s:

/* Dinh nghia ham max3s */ float max3s(float a, float b, float c) { float max; max = a>b?a:b; return (max>c?max:c); /* Gia tri tra ve */ }

Trong ví dụ trên, tiêu đề của hàm là: float max3s(float a, float b, float c)

Thân hàm bắt đầu bằng dấu { và kết thúc bởi dấu }. Trong thân hàm chứa các câu lệnh cần thiết để thực hiện một yêu cầu nào đó đã đề ra cho hàm. Thân của hàm max3s là đoạn chương trình tính giá trị lớn nhất của ba đối a, b, c.

Trong thân hàm ta dùng thêm biến max. Cần phân biệt sự khác nhau giữa biến max và đối a, b, c. Biến max là biến cục bộ nó chỉ có tác dụng trong thân hàm và không có bất cứ một liên hệ gì đến các biến của các hàm khác trong chương trình. Trái lại các đối a, b, c lại được dùng để trao đổi dữ liệu giữa các hàm.

Trong thân hàm có thể sử dụng một câu lệnh return, có thể dùng nhiều câu lệnh return ở những chỗ khác nhau và cũng có thể không sử dụng câu lệnh này. Dạng tổng quát của nó là:

return [<biểu thức>];

Giá trị của biểu thức trong câu lệnh return sẽ được gán cho hàm. Trong ví dụ đang xét, giá trị của biểu thức này là giá trị lớn nhất của ba đối a, b, c.

4.1.3 Sử dụng hàm

Page 69: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

70

Hàm được sử dụng bằng cách gọi hàm. Lời gọi hàm có dạng sau: <tên hàm> ([<danh sách tham số thực>])

Khi gọi hàm, cần phải truyền cho mỗi tham số một giá trị. Các giá trị này gọi là các tham số thực để phân biệt với các tham số được khai báo khi định nghĩa hàm (tham số hình thức).

Khi gặp một lời gọi hàm thì hàm bắt đầu được thực hiện. Nói cách khác, khi máy gặp một lời gọi hàm ở một chỗ nào đó của chương trình, thì máy sẽ tạm rời chỗ đó và chuyển đến hàm tương ứng. Quá trình đó sẽ diễn ra theo trình tự 4 bước như sau:

a/ Cấp phát bộ nhớ cho các đối và các biến cục bộ.

b/ Gán giá trị của các tham số thực cho các đối tương ứng.

c/ Thực hiện các câu lệnh trong thân hàm.

d/ Khi gặp câu lệnh return hoặc dấu } cuối cùng của thân hàm thì máy sẽ xoá các đối, các biến cục bộ (giải phóng bộ nhớ của các đối, biến cục bộ) và thoát khỏi hàm.

Nếu trở về từ một câu lệnh return có chứa biểu thức thì giá trị của biểu thức được gán cho hàm. Giá trị của hàm sẽ được sử dụng trong các biểu thức chứa nó.

Trong ví dụ trên, giá trị của hàm max3s(x,y,z) sẽ được sử dụng trong câu lệnh printf. Nói cách khác, giá trị lớn nhất của ba số x, y, z sẽ được đưa ra màn hình.

4.1.4 Cấu trúc tổng quát của chương trình

Chương trình gồm nhiều hàm được viết theo trình tự sau:

- Các #include

- Các #define

- Khai báo các đối tượng dữ liệu ngoài (biến, mảng, cấu trúc, hợp,...).

- Khai báo nguyên mẫu của các hàm

- Hàm main

- Xây dựng (định nghĩa) các hàm

Chú ý: Hàm main có thể đặt sau hoặc xen vào giữa các hàm khác.

4.2 Tham số kiểu con trỏ Trong phần này, chúng tôi giới thiệu sơ lược về con trỏ trong C, và ứng dụng trong

truyền tham số cho hàm.

4.2.1 Địa chỉ Liên quan đến một biến ta đã có khái niệm:

- Tên biến

- Kiểu biến

- Giá trị của biến

Ví dụ câu lệnh float alpha = 30.5;

xác định một biến có tên là alpha có kiểu float và có giá trị 30.5. Ta cũng đã biết, theo khai báo trên, máy sẽ cấp phát cho biến alpha một khoảng nhớ gồm 4 byte liên tiếp.

Địa chỉ của biến là số thứ tự của byte đầu tiên của vùng nhớ của biến trong bộ nhớ.

Page 70: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

71

Một điều cần chú ý là mặc dù địa chỉ của biến là một số nguyên nhưng không được đánh đồng nó với các số nguyên thông thường dùng trong các phép tính.

Để lấy địa chỉ của một biến, dùng phép toán toán &. Ví dụ để lấy địa chỉ của biến alpha. &alpha

4.2.2 Con trỏ Con trỏ là biến dùng để chứa địa chỉ, có nghĩa là giá trị của con trỏ là địa chỉ của một

biến nào đó.

Vì có nhiều loại địa chỉ nên cũng có nhiều kiểu con trỏ tương ứng. Con trỏ kiểu int dùng để chứa địa chỉ các biến kiểu int. Tương tự, ta có con trỏ kiểu float, kiểu double,... . Cũng như đối với bất kỳ một biến nào khác, một con trỏ cần khai báo trước khi sử dụng.

Việc khai báo biến con trỏ được thực hiện theo mẫu sau: <kiểu> *<tên con trỏ>;

Ví dụ câu lệnh sau khai báo hai biến kiểu int là x, y và hai con trỏ kiểu int là px và py. int x, y, *px, *py;

Tương tự câu lệnh sau khai báo các con trỏ kiểu float. float f, *pf;

Khi đã có các khai báo trên thì các câu lệnh sau hoàn toàn xác định. px = &x; py = &y;

Câu lệnh thứ nhất sẽ gán địa chỉ của x cho con trỏ px và câu lệnh thứ hai sẽ gán địa chỉ của biến y cho con trỏ py.

Khi con trỏ px chứa địa chỉ của biến x thì ta nói px trỏ tới x.

Chúng ta không được gán địa chỉ của một biến nguyên cho một con trỏ kiểu thực. Ví dụ câu lệnh sau là không hợp lệ.

pf = &y;

4.2.3 Qui tắc sử dụng con trỏ trong các biểu thức

Với một biến, có hai đại lượng liên quan, đó là giá trị của biến và địa chỉ của biến. Khi một con trỏ trỏ tới một biến, khi đó cũng có hai đại lượng liên quan, đó là giá trị con trỏ (chính là địa chỉ của biến) và giá trị của biến mà con trỏ đang trỏ tới.

Trong biểu thức, tên con trỏ đại diện cho giá trị của con trỏ và dạng khai báo đại diện cho giá trị biến mà con trỏ đang trỏ tới.

Sử dụng tên con trỏ Con trỏ cũng là một biến nên khi tên của nó xuất hiện trong một biểu thức thì giá trị của

nó sẽ được sử dụng trong biểu thức này. Khi tên con trỏ đứng ở bên trái của một toán tử gán thì giá trị của biểu thức bên phải (giá trị này phải là địa chỉ) được gán cho con trỏ.

Ta hãy xem các câu lệnh sau làm gì ? float a, *p, *q; p = &a; q = p;

Page 71: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

72

Câu lệnh thứ nhất khai báo một biến kiểu float (biến a) và hai con trỏ p và q kiểu float. Câu lệnh thứ hai sẽ gán địa chỉ của biến a cho con trỏ p và câu lệnh thứ ba sẽ gán giá trị của p cho q. Két quả là con trỏ q chứa địa chỉ của biến a.

Sử dụng dạng khai báo của con trỏ Xét đoạn lệnh sau:

float x, y, *px, *py; x = 100.0f; y = 215.3f; px = &x; py = &y;

Sau các lệnh gán thì px trỏ tới x, py trỏ tới y. Khi đó biến mà px trỏ tới (biến x) được biểu diễn dưới dạng *px.

Nói một cách khác, nếu con trỏ px trỏ tới biến x thì các cách viết

x và *px

là tương đương trong mọi ngữ cảnh.

Theo nguyên lý này thì ba câu lệnh sau đều có hiệu lực như nhau y = 3*x + 1; *py = 3*x + 1; *py = 3*(*px) + 1;

Từ đây có thể rút ra một kết luận quan trong là: Khi biết được địa chỉ của một biến thì chẳng những chúng ta có thể sử dụng giá trị của nó mà còn có thể gán cho nó một giá trị mới (làm thay đổi nội dung của nó). Điều này sẽ được áp dụng như một phương pháp chủ yếu để nhận kết quả của hàm thông qua đối.

4.2.4 Mảng và con trỏ Khi khai báo một mảng, máy cấp phát một vùng nhớ dùng để lưu giá trị các phần tử của

mảng.

Ví dụ khai báo một mảng số nguyên: int a[100];

Khi đó máy sẽ cấp phát 100 ô nhớ, mỗi ô nhớ có kích thước của một số nguyên tương ứng với một phần tử, và các phần tử sẽ sắp xếp liên tiếp nhau trong bộ nhớ, từ phần tử đầu tiên.

Trong C, tên mảng chính là địa chỉ của phần tử đầu tiên của mảng, điều có nghĩa là:

a bằng &a[0]

Vì tên mảng là một địa chỉ, nên ta có thể gán cho một con trỏ. Ví dụ: int *p; p = a;

Như vậy giữa mảng con trỏ có sự tương đồng. Do đó, trong C cho phép sử dụng thay thế giữa mảng và con trỏ trong một số trường hợp.

Ví dụ, sau khi đã gán p bằng a thì:

a[4] và p[4] đều biểu diễn phần tử thứ 5 của mảng.

a[0], *a và *p cùng biểu diễn phần tử đầu tiên của mảng.

Page 72: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

73

Tuy nhiên giữa mảng và con trỏ có sự khác nhau. Con trỏ là một biến, vì thế giá trị của nó có thể thay đổi được và ta có thể gán giá trị cho một con trỏ. Trong khi đó mảng là một hằng địa chỉ, vì khi mảng được cấp phát thì địa chỉ của phần tử đầu tiên là xác định. Vì vậy không thể thay đổi được giá trị của mảng.

4.2.5 Hàm có đối con trỏ Đối con trỏ thường được sử dụng trong các trường hợp sau đây:

- Sử dụng hàm để thay đổi giá trị của một biến.

- Truyền một mảng vào cho hàm.

- Trả về nhiều kết quả.

Sử dụng hàm để thay đổi giá trị của một biến Như chúng ta đã biết, khi truyền tham số thực cho hàm, thì chỉ có giá trị của các biểu

thức là được sử dụng. Nếu chúng ta thay đổi giá trị của đối số bên trong hàm, thì sự thay đổi đó không ảnh hưởng đến giá trị các biến truyền vào cho hàm.

Vì vậy, nếu muốn dùng hàm để thay đổi giá trị của một biến, thì phải truyền địa chỉ của biến thay vì giá trị của biến.

Để khai báo một tham số là địa chỉ của một biến, ta khai báo tham số đó là một con trỏ có kiểu tương ứng. Ví dụ sau định nghĩa một hàm cho phép đảo giá trị của hai biến.

#include <stdio.h> void hoan_vi(float *px, float *py) { float z; z = *px; *px = *py; *py = z; } void main() { float a = 7.6f, b = 13.5f; hoan_vi(&a, &b); printf("\na = %0.2f b = %0.2f", a, b); }

Kết quả thực hiện chương trình a = 13.50 b = 7.60

Ta hãy xem hàm hoán_vị làm việc thế nào. Như đã biết, chương trình bắt đầu từ câu lệnh đầu tiên trong hàm main(). Kết qủa là biến a nhận giá trị 7.6 và biến b nhận giá trị 13.5. Tiếp đó là lời gọi hàm hoan_vi. Máy sẽ gán giá trị của các tham số thực cho đối tương ứng. Như vậy địa chỉ của a được gán cho con trỏ px , địa chỉ của b được gán cho con trỏ py. Sau đó máy lần lượt xét đến các câu lệnh trong thân hàm. Câu lệnh thứ nhất sẽ cấp phát cho biến cục bộ z một khoảng nhớ 4 byte. Theo qui tắc về sử dụng con trỏ nêu trong mục 4.2.3 thì ba câu lệnh tiếp theo tương đương với các câu lệnh:

z = a; a = b; b = z;

Như vậy a sẽ nhận giá trị của b và ngược lại. Tiếp đó, máy trở về hàm main() và in ra những dòng kết qủa như đã chỉ ra ở trên.

Truyền một mảng một chiều vào cho hàm

Page 73: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

74

Khi muốn truyền một mảng vào cho một hàm, ví dụ như hàm in các số hạng của một dãy số, khi đó ta dùng đối con trỏ.

Do mảng là địa chỉ của phần tử đầu nên kiểu của đối là kiểu con trỏ của kiểu phần tử mảng. Ví dụ, với mảng các phần tử int thì kiểu đối là con trỏ kiểu int.

Khi truyền mảng vào cho hàm, bên trong hàm không rõ số lượng phần tử của mảng, do đó cần thêm đối chỉ ra số lượng phần tử của mảng.

Ví dụ sau định nghĩa hai hàm, một hàm nhập dữ liệu cho một dãy số và một hàm in dãy số đó ra màn hình.

#include <stdio.h> // Nguyen mau ham void NhapDaySo(int *, int); void InDaySo(int *, int); void main() { int a[100]; int n; printf("Nhap so phan tu: "); scanf("%d", &n); // Nhap day so NhapDaySo(a, n); printf("Day so vua nhap:\n"); // In day so InDaySo(a, n); } void NhapDaySo(int *a, int n) { int i; for (i = 0; i < n; i++) { printf("a[%d] = ", i + 1); scanf("%d", &a[i]); } } void InDaySo(int *a, int n) { int i; for (i = 0; i < n; i++) printf("%8d", a[i]); }

Trong ví dụ trên, các tham số của hai hàm NhapDaySo và InDaySo được khai báo giống nhau, bao gồm một tham số kiểu con trỏ nguyên và một tham số nguyên.

Tuy nhiên, trong hai trường hợp ý nghĩa tham số là khác nhau.

- Tham số a trong hàm NhapDaySo là kết quả đưa ra.

- Tham số a trong hàm InDaySo là dữ liệu đầu vào.

Về mặt cú pháp, chúng ta không phân biệt được sự khác nhau ở trên, mà chỉ phân biệt được theo mục đích sử dụng.

Page 74: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

75

Vì vậy, khi truyền một mảng vào cho hàm mà trong hàm không có nhu cầu thay đổi giá trị của các phần tử của mảng, thì có thể thêm từ khoá const khi khai báo tham số. Ví dụ, hàm InDaySo có thể được định nghĩa như sau:

void InDaySo(const int *a, int n) { int i; for (i = 0; i < n; i++) printf("%8d", a[i]); }

Khi đó thì có thể xác định ngay tham số a là dữ liệu vào cho hàm.

Truyền một mảng nhiều chiều vào cho hàm Trong một số trường hợp, chúng ta phải truyền một mảng nhiều chiều vào cho hàm, ví dụ

như truyền một ma trận vào hàm in ma trận.

Khi khai báo một tham số là một mảng nhiều chiều, cần phải chỉ ra số phần tử tương ứng của các chiều, trừ chiều đầu tiên là không cần thiết phải chỉ ra.

Ví dụ sau nhập in một ma trận thực theo dạng bảng, sử dụng cả hai cú pháp khai báo là mảng và con trỏ.

#include <stdio.h> // Nguyen mau ham // Su dung dang khai bao con tro void NhapMaTran(float (*)[20], int, int); // Su dung dang khai bao mang void InMaTran(float [][20], int, int); void main() { float a[20][20]; int m, n; printf("Nhap so hang, so cot: "); scanf("%d%d", &m, &n); // Nhap ma tran NhapMaTran(a, m, n); // In ma tran InMaTran(a, 3, 3); } void NhapMaTran(float (*a)[20], int m, int n) { int i, j; float f; for (i = 0; i < m; i++) for (j = 0; j < n; j++) { printf("a[%d][%d] = ", i + 1, j + 1); scanf("%f", &f); a[i][j] = f; } } void InMaTran(float a[][20], int m, int n) { int i, j; for (i = 0; i < m; i++)

Page 75: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

76

{ for (j = 0; j < n; j++) printf("%8.2f", a[i][j]); printf("\n"); } }

Chú ý là một số trình dịch không cho phép lấy địa chỉ của một phần tử mảng nhiều chiều, do đó chúng ta phải dùng một biến trung gian khi nhi nhập giá trị các phần tử mảng, như trong hàm NhapMaTran ở trên.

Trả về nhiều kết quả Một trường hợp mà đối là con trỏ thường được sử dụng đó là khi chúng ta muốn hàm trả

về nhiều giá trị. Như chúng ta đã biết, hàm chỉ có thể trả về một giá trị dưới dạng tên hàm, do đó để trả về nhiều giá trị chúng ta phải sử dụng tham số là con trỏ.

Ví dụ, khi viết một hàm giải phương trình bậc hai, thì chúng ta cần phải trả về các đại lượng:

- Hàm đó có bao nhiêu nghiệm (0, 1, 2).

- Nếu có nghiệm, thì giá trị của nghiệm là bao nhiêu.

Như vậy ở đây chúng ta phải trả về ba đại lượng: số nghiệm, một hoặc hai nghiệm (trong trường hợp có nghiệm).

Ví dụ sau thể hiện cách chúng ta trả về nhiều kết quả. /* Chuong trinh giai phuong trinh bac hai */ #include <stdio.h> #include <math.h> // Nguyen mau ham int GiaiPTBac2(float, float, float, float*, float*); void main() { float a, b, c, x1, x2; int songhiem; printf("Nhap a, b, c: "); scanf("%f%f%f", &a, &b, &c); // Giai phuong trinh songhiem = GiaiPTBac2(a, b, c, &x1, &x2); if (songhiem == 0) printf("Phuong trinh vo nghiem."); else if (songhiem == 1) printf("Nghiem kep: %.3f", x1); else printf("x1: %.3f\nx2: %.3f", x1, x2); } int GiaiPTBac2(float a, float b, float c, float *px1, float *px2) { float delta; delta = b*b - 4*a*c; if (delta < 0) return 0; else if (delta == 0) { *px1 = -b/(2*a);

Page 76: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

77

return 1; } else { *px1 = (-b - sqrt(delta))/(2*a); *px2 = (-b + sqrt(delta))/(2*a); return 2; } }

4.3 Đệ quy

4.3.1 Khái niêm chung về đệ quy C không những cho phép từ hàm này gọi tới hàm khác, mà nó còn cho phép từ một vị trí

trong thân của một hàm gọi tới chính hàm đó. Hàm như vậy gọi là hàm đệ quy. Trong một số trường hợp, sử dụng đệ quy sẽ làm chương trình ngắn gọn, dễ hiểu hơn.

Khi hàm gọi đệ quy đến chính nó thì mỗi lần gọi, máy sẽ tạo ra một tập các biến cục bộ mới hoàn toàn độc lập với các tập biến (cục bộ) đã được tạo ra trong các lần gọi trước.

Ta cũng chú ý rằng: Có bao nhiêu lần gọi tới hàm thì cũng có bấy nhiêu lần thoát ra khỏi hàm và cứ mỗi lần ra khỏi hàm thì một tập các biến cục bộ bị xóa. Sự tương ứng giữa các lần gọi tới hàm và các lần ra khỏi hàm được thực hiện theo thứ tự ngược, nghĩa là: Lần ra đầu tiên ứng với lần vào cuối cùng và lần ra khỏi hàm cuối cùng ứng với lần đầu tiên gọi tới hàm.

Để minh họa những điều nói trên, ta đưa ra một ví dụ đơn giản. Giả sử ta cần viết một hàm tính n giai thừa. Thông thường ta sẽ viết như sau:

long giai_thua(int n) { long s; int i; for (s = 1, i = 1; i <= n; i++) s*= i; return s; }

Một cách khác, ta thấy rằng n! có thể tính theo công thức truy hồi như sau:

n!= 1 nếu n = 0

n!= n*(n-1)! nếu n > 0

Dựa vào công thức trên ta có thể xây dựng hàm để tính n! một cách đệ quy như sau: #include <stdio.h> long giai_thua(int n) { return (n > 0)?n*giai_thua(n - 1) : 1; } void main() { printf("%d", giai_thua(5)); }

Cơ chế hoạt động của hàm giai_thua trong chương trình trên có thể giải thích như sau:

- Trong hàm main, có một lời gọi hàm giai_thua(5) để tính giai thừa của 5. Khi đó hàm giai_thua sẽ được gọi ra để thực hiện với tham số n bằng 5.

Page 77: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

78

- Trong hàm giai_thua, do n lớn hơn 0 nên giá trị trả về là n*giai_thua(n -1), tức là 5*giai_thua(4). Tuy nhiên lúc này giá trị giai_thua(4) chưa xác định, nên máy lại tiếp tục gọi hàm giai_thua để tính giai thừa của 4.

- Trong lần gọi thứ hai này, do n vẫn lớn hơn 0, nên tiếp tục cần tính giai_thua(3).

- Cứ như vậy, cho tới khi n bằng 0, khi đó giá trị trả về của lần gọi giai_thua(0) là 1 và được sử dụng để tính biểu thức trả về cho lần gọi giai_thua(1) bằng 1*giai_thua(0), bằng 1*1.

- Giá trị giai_thua(1) bằng 1, lại được sử dụng để tính biểu thức trả về cho lần gọi giai_thua(2), bằng 2*1.

- Cứ như vậy, cuối cùng giá trị trả về của lời gọi giai_thua(5) trong main có giá trị bằng 5*4*3*2*1*1.

4.3.2 Cách dùng đệ quy

Bài toán nào có thể dùng đệ quy

Phương pháp đệ quy thường áp dụng cho các bài toán phụ thuộc tham số có hai đặc điểm sau:

- Bài toán dễ dàng giải quyết trong một số trường hợp riêng ứng với các giá trị đặc biệt của tham số. Ta gọi đây là trường hợp suy biến.

- Trong trường hợp tổng quát, bài toán có thể quy về một bài toán cùng dạng nhưng giá trị tham số thay đổi. Và sau một số hữu hạn bước biến đổi đệ quy, sẽ dẫn tới trường hợp suy biến.

Ta nhận thấy bài toán tính n! nêu trên thể hiên rất rõ các đặc điểm này.

Cách xây dựng hàm đệ quy Hàm đệ quy thường được viết theo thuật toán sau:

if (trường hợp suy biến) {

trình bầy cách giải bài toán (giả định đã có cách giải)

} else /* trường hợp tổng quát */ {

gọi đệ quy tới hàm (đang lập) với giá trị khác của tham số

}

4.3.3 Các ví dụ Mục này sẽ trình bầy một số ví dụ nhằm minh hoạ cách xây dựng hàm đệ.

Ví dụ 1: Xét bài toán tìm ước số chung lớn nhất của hai số nguyên dương x và y.

- Trường hợp suy biến là trường hợp x = y. Khi đó:

usc(x,y) = x.

- Trường hợp x khác y có thể tính ƯSCLN một cách đệ quy như sau:

usc(x,y) = usc(x-y,y) nếu x > y

usc(x,y) = usc(x,y-x) nếu x < y

Chương trình sau định nghĩa hàm tính ước số chung lớn nhất và sử dụng hàm đó để tính ước số chung lớn nhất của hai số nhập vào:

Page 78: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

79

#include <stdio.h> // Nguyen mau ham int uscln(int, int); void main() { int a, b; printf("Nhap hai so nguyen: "); scanf("%d%d", &a, &b); printf("USCLN cua %d va %d la %d.", a, b, uscln(a, b)); } int uscln(int a, int b) { if (a > b) return uscln(a - b, b); else if (a < b) return uscln(a, b - a); else return a; }

Ví dụ 2: Bài toán tháp Hà Nội.

Bài toán tháp Hà Nội được đặt ra như sau: Có một tháp gồm n tầng, tầng trên nhỏ hơn tầng dưới. Nhiệm vụ là phải chuyển tháp từ một vị trí A đến một vị trí mới B. Điều kiện khi chuyển là:

- Mỗi lần chỉ được phép chuyển một tầng.

- Cho phép sử dụng thêm một vị trí trung gian C để đặt các tầng.

- Luôn đảm bảo tầng trên nhỏ hơn tầng dưới ở mọi vị trí và mọi thời điểm.

Thuật toán chuyển tháp có thể diễn đạt như sau:

Trường hợp suy biến: n = 1, khi đó chỉ cần chuyển tầng 1 từ A đến B.

Trường hợp tổng quát n > 1 có thể giải quyết đệ quy như sau:

- Chuyển tháp n -1 tầng từ A đến C, dùng B làm vị trí trung gian.

- Chuyển tầng n từ A đến B.

- Chuyển tháp n - 1 tầng từ C đến B, dùng A làm vị trí trung gian.

Chương trình sau cài đặt thuật toán trên. /* Thap Ha noi */ #include <stdio.h> // Nguyen mau ham void Chuyen(int, int, int, int); void main() { int n; printf("Nhap so tang: "); scanf("%d", &n); Chuyen(n, 'A', 'B', 'C'); } void Chuyen(int n, int A, int B, int C) {

Page 79: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

80

if (n == 1) printf("Chuyen tang 1 tu %c sang %c\n", A, B); else { Chuyen(n - 1, A, C, B); printf("Chuyen tang %d tu %c sang %c\n", n, A, B); Chuyen(n - 1, C, B, A); } }

BÀI TẬP CHƯƠNG 4 Viết hàm thực hiện các bài toán dưới đây.

Bài 1. Giải hệ phương trình bậc nhất

ax + by = c

dx + ey = f

Hàm có sáu đối vào là a, b, c, d, e, f và hai đối ra là x, y.

Bài 2. Tính đa thức cấp n

f(x) = a0 + a1x + ... + an-1xn-1 + anxn

Hàm có hai đối là biến nguyên n và mảng thực a.

Bài 3. Tính cực đại và cực tiểu của một dãy số.

Bài 4. Tính giá trị trung bình và độ lệch tiêu chuẩn của một đại lượng ngẫu nhiên theo công thức

s x xn

n=+ +1 ...

nsxsx

d n22

12 )(...)( −++−=

Trong đó x1, ..., xn là dãy quan sát nhận được.

Bài 5. Nhân ma trận A cấp mxn với véc tơ X cấp n.

Bài 6. Chuyển vị một ma trận chữ nhật A cho trước.

Bài 7. Xây dựng hàm h(x) là max của các hàm f(x) và g(x) trên đoạn [a, b].

Bài 8. Tìm tọa độ giao điểm của hai đường thẳng AB và CD khi biết tọa độ của các điểm A, B, C, D.

Bài 9. Xây dựng 3 hàm số sau đây bằng phương pháp đệ qui

f(x,n) = xn

s(n) = (2n)!!

p(n) = 13 + 23 + . . . + n3

Bài 10. Tìm một nghiệm của phương trình f(x)=0 trên đoạn [a,b]. Giả thiết hàm f(x) liên tục trên [a,b] và f(a)*f(b) < 0.

Page 80: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

81

CHƯƠNG 5 - CẤU TRÚC

Để lưu trữ và xử lý thông tin trong máy tính ta có các biến và các mảng. Mỗi biến chứa được một giá trị. Mảng có thể xem là tập hợp nhiều biến có cùng một kiểu giá trị và được biểu thị bằng một tên. Cấu trúc có thể xem như một sự mở rộng của các khái niệm biến và mảng, nó cho phép lưu trữ và xử lý các dạng thông tin phức tạp hơn. Cấu trúc là một tập hợp các biến, các mảng và được biểu thị bởi một tên duy nhất.

Một ví dụ truyền thống về cấu trúc là phiếu ghi lương: Mỗi công nhân được miêu tả bởi một tập hợp các thuộc tính như tên, địa chỉ, ngày sinh, bậc lương,... Một vài trong các thuộc tính này lại có thể là cấu trúc: Tên có thể có nhiều thành phần, địa chỉ và thậm chí ngày sinh cũng vậy.

5.1 Định nghĩa cấu trúc và khai báo biến cấu trúc Cấu trúc là kiểu dữ liệu do người dùng tự định nghĩa. Khi định nghĩa một cấu trúc, cần

chỉ ra tên của kiểu cấu trúc và các thành phần của cấu trúc.

Để định nghĩa một cấu trúc, chúng ta dùng mẫu sau: struct <Tên> {

<Kiểu 1> <Tên thành phần 1>; <Kiểu 2> <Tên thành phần 2>; ...

};

Ví dụ, định nghĩa cấu trúc mô tả ngày tháng, như sau: struct Ngay {

int ngay; int thang; int nam;

};

Sau khi định nghĩa trên, chúng ta đã có kiểu dữ liệu mô tả ngày tháng là struct Ngay. Kiểu dữ liệu này có thể dùng để khai báo các biến cấu trúc. Ví dụ, biến ngay_sinh kiểu ngày tháng được khai báo như sau:

struct Ngay ngay_sinh;

Ta thấy việc khai báo các biến cấu trúc cũng giống như khai báo các biến kiểu dữ liệu chuẩn. Trong dòng khai báo trên, kiểu dữ liệu là struct Ngay và tên biến là ngay_sinh.

5.2 Kết hợp định nghĩa cấu trúc và khai báo biến cấu trúc Trong phần 5.1, chúng ta đã biết định nghĩa một cấu trúc và sử dụng kiểu dữ liệu đó để

khai báo các biến. Có thể kết hợp cả định nghĩa cấu trúc và khai báo biến vào một lệnh duy nhất theo mẫu sau:

struct [Tên] {

<Kiểu 1> <Tên thành phần 1>; <Kiểu 2> <Tên thành phần 2>; ...

} <danh sách biến>;

Với cách này, các biến sẽ có kiểu là cấu trúc có các thành phần như được khai báo trong cặp ngoặc nhọn {}. Tên cấu trúc trong trường hợp này có thể có, có thể không.

Page 81: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

82

Ví dụ, định nghĩa cấu trúc mô tả ngày tháng đồng thời khai báo biến tu_ngay, den_ngay, ta có thể dùng một trong hai cách sau:

Cách 1: có tên cấu trúc: struct Ngay {

int ngay; int thang; int nam;

} tu_ngay, den_ngay;

Cách 2: không có tên cấu trúc: struct {

int ngay; int thang; int nam;

} tu_ngay, den_ngay;

Sự khác nhau của hai cách này đó là, cách 1 vừa định nghĩa cấu trúc tên là Ngay và các biến cấu trúc tu_ngay, den_ngay. Sau định nghĩa này, ta có thể dùng kiểu struct Ngay để khai báo các biến khác.

Cách 2 định nghĩa các biến tu_ngay, den_ngay có kiểu là một cấu trúc gồm ba trường: ngay, thang và nam. Vì không đặt tên cho cấu trúc, nên sau định nghĩa ngày chúng ta không thể sử dụng kiểu dữ liệu này được nữa, do đó không thể định nghĩa các biến cùng kiểu với các biến tu_ngay, den_ngay.

5.3 Sử dụng typedef để định nghĩa kiểu dữ liệu cấu trúc

5.3.1 Định nghĩa kiểu bằng typedef

Sử dụng từ khoá typedef, chúng ta có thể định nghĩa các kiểu dữ liệu mới dựa trên các kiểu dữ liệu đã có. Mẫu chung cho việc định nghĩa kiểu dữ liệu bằng typedef như nhau:

typedef <kiểu> <danh sách tên>;

Ví dụ, như chúng ta đã biết trong C không định nghĩa kiểu dữ liệu logic, mà kiểu dữ liệu này được biểu diễn thông qua bất cứ kiểu dữ liệu nào. Trong ví dụ này, chúng ta sẽ sử dụng kiểu số nguyên để biểu diễn kiểu logic, định nghĩa như sau:

typedef int BOOL, BIT;

Sau định nghĩa này, chúng ta đã có các kiểu dữ liệu mới là BOOL, BIT, mà thực chất là kiểu int. Kiểu BOOL, BIT có thể dùng để khai báo các biến như sau:

BOOL tiep_tuc; BIT ket_qua;

Đoạn lệnh trên khai báo các biến tiep_tuc kiểu BOOL và ket_qua kiểu BIT. Về mặt bản chất, các biến này có kiểu nguyên, tuy nhiên ta đã coi các biến này có kiểu logic nên các biến này chỉ nên nhận hai giá trị là 0 (biểu diễn giá trị sai) và 1 (biểu diễn giá trị đúng).

5.3.2 Sử dụng typedef để định nghĩa kiểu cấu trúc Chúng ta có thể dùng từ khoá typedef để định nghĩa kiểu cấu trúc, cho phép viết ngắn

gọn hơn.

Giả sử chúng ta đã định nghĩa kiểu struct Ngay, chúng ta có thể định nghĩa kiểu dữ liệu mới tương đương kiểu dữ liệu này như sau:

typdef struct Ngay KieuNgay;

Page 82: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

83

Sau khi định nghĩa kiểu KieuNgay, có thể dùng kiểu dữ liệu này để khai báo các biến một cách ngắn gọn như sau:

KieuNgay ngay_batdau, ngay_kethuc;

Chúng ta có thể kết hợp định nghĩa cấu trúc với từ khoá typedef để định nghĩa kiểu dữ liệu cấu trúc theo mẫu sau:

typdef struct [Tên] {

<Kiểu 1> <Tên thành phần 1>; <Kiểu 2> <Tên thành phần 2>; ...

} <danh sách tên kiểu>;

Với cách này, tên cấu trúc có thể có, có thể không. Ví dụ sau định nghĩa kiểu KieuNgay kết hợp với định nghĩa cấu trúc theo hai cách:

Cách 1: có tên cấu trúc: typedef struct Ngay {

int ngay; int thang; int nam;

} KieuNgay;

Cách 2: không có tên cấu trúc: typedef struct {

int ngay; int thang; int nam;

} KieuNgay;

Khác biệt của hai cách này là ở chỗ: với cách 1, chúng ta có thể sử dụng kiểu dữ liệu là struct Ngay hoặc KieuNgay, còn với cách 2 thì chúng ta chỉ có kiểu dữ liêu KieuNgay.

5.4 Truy cập các thành phần của cấu trúc Với một biến kiểu nguyên hay kiểu thực, thì nội dung biến chỉ có thể mang một giá trị

kiểu tương ứng. Một biến cấu trúc mang trong nó nhiều thành phần khác nhau, và chúng ta có thể làm việc với từng thành phần này.

Việc truy cập các thành phần của một biến cấu trúc có thể thực hiện bằng toán tử chấm (.). Toán tử này cho phép truy cập đến một thành phần cấu trúc khi biết tên biến cấu trúc và tên thành phần. Cú pháp như sau:

<biến cấu trúc>.<tên thành phần>

Trong trường hợp thành phần của cấu trúc là một cấu trúc, khi đó có thể áp dụng toán tử này cho thành phần đó để truy cập vào các thành phần sâu hơn.

Nếu chúng ta làm việc với biến cấu trúc thông qua con trỏ, khi đó toán tử để truy cập đến các thành phần cấu trúc là toán tử ->.

5.5 Ví dụ minh hoạ

5.5.1 Ví dụ 1 Nhập toạ độ của N điểm trong mặt phẳng. Tính tổng độ dài đường gấp khúc đi qua các

điểm này theo thứ tự nhập vào.

Page 83: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

84

Với ví dụ này, chúng ta có thể dùng 2 mảng số thực để lưu các toạ độ x và y của các điểm. Một cách khác là dùng một cấu trúc mô tả điểm, trong đó x và y là các thành phần của cấu trúc này. Mảng các điểm là một mảng cấu trúc.

#include <stdio.h> #include <math.h> typedef struct { float x; float y; } DIEM, *PDIEM; // Khai bao cac nguyen mau ham void NhapDiem(PDIEM, int); float TinhDoDai(PDIEM, int); void main() { DIEM day[100]; int n; printf("Nhap so diem: "); scanf("%d", &n); NhapDiem(day, n); printf("Do dai duong gap khuc la: %.3f", TinhDoDai(day, n)); } void NhapDiem(PDIEM pDiem, int n) { DIEM diem; int i; for (i = 0; i < n; i++) { printf("x[%d] = ", i + 1); scanf("%f", &diem.x); printf("y[%d] = ", i + 1); scanf("%f", &diem.y); pDiem[i] = diem; } } float TinhDoDai(PDIEM pDiem, int n) { float do_dai, dx, dy; int i; do_dai = 0; for (i = 0; i < n - 1; i++) { dx = (pDiem[i + 1].x - pDiem[i].x); dy = (pDiem[i + 1].y - pDiem[i].y); do_dai+= sqrt(dx*dx + dy*dy); } return do_dai; }

5.5.2 Ví dụ 2

Nhập một danh sách gồm n thí sinh dự thi đại học, mỗi thí sinh là một cấu trúc gồm các trường: Họ và tên, Quê, Điểm toán, Điểm lý, Điểm hoá

Yêu cầu:

Page 84: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

85

- Nhập điểm chuẩn sau đó tìm và in ra màn hình danh sách các thí sinh đỗ đại học có quê ở “Ha Noi” (Thí sinh đỗ đại học nếu có tổng điểm không dưới điểm chuẩn).

- Tìm và in ra màn hình danh sách các thí sinh có điểm toán cao nhất.

- In ra màn hình toàn bộ thông tin của n thí sinh.. #include <stdio.h> #include <string.h> // Dinh nghia kieu Ho so sinh vien typedef struct { char HoTen[30]; char Que[50]; float DiemToan; float DiemLy; float DiemHoa; } HSSV, *PHSSV; // khai bao nguyen mau void NhapHSSV(PHSSV, int); void InHSSV(PHSSV, int); void main() { HSSV day[50]; int n, i; float chuan, max; printf("Nhap so sinh vien: "); scanf("%d", &n); // Nhap ds sinh vien NhapHSSV(day, n); // In ds sinh vien vua nhap InHSSV(day, n); // Tim kiem cac sinh vien do que o Ha Noi printf("Nhap diem chuan: "); scanf("%f", &chuan); printf("\nDanh sach sinh vien do, que o Ha Noi:\n"); printf("%4s %20s %20s %6s %6s %6s\n", "STT", "Ho ten", "Que quan", "Toan", "Ly", "Hoa"); for (i = 0; i < n; i++) if ((day[i].DiemToan + day[i].DiemLy + day[i].DiemHoa >= chuan)&& (strcmpi(day[i].Que, "Ha Noi") == 0)) printf("%4d %20s %20s %6.1f %6.1f %6.1f\n", i + 1, day[i].HoTen, day[i].Que, day[i].DiemToan, day[i].DiemLy, day[i].DiemHoa); // Tim diem toan cao nhat max = day[0].DiemToan; for (i = 1; i < n; i++) if (max < day[i].DiemToan) max = day[i].DiemToan; // In ra danh sach sinh vien diem toan cao nhat printf("\nDanh sach sinh vien diem toan cao nhat:\n"); printf("%4s %20s %20s %6s %6s %6s\n", "STT", "Ho ten", "Que quan", "Toan", "Ly", "Hoa");

Page 85: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

86

for (i = 0; i < n; i++) if (day[i].DiemToan == max) printf("%4d %20s %20s %6.1f %6.1f %6.1f\n", i + 1, day[i].HoTen, day[i].Que, day[i].DiemToan, day[i].DiemLy, day[i].DiemHoa); } void NhapHSSV(PHSSV pSv, int n) { HSSV sv; int i; for (i = 0; i < n; i++) { printf("Ten sinh vien %d: ", i + 1); fflush(stdin); gets(sv.HoTen); printf("Que sinh vien %d: ", i + 1); fflush(stdin); gets(sv.Que); printf("Diem toan, ly, hoa sinh vien %d: ", i + 1); scanf("%f%f%f", &sv.DiemToan, &sv.DiemLy, &sv.DiemHoa); pSv[i] = sv; } } void InHSSV(PHSSV pSv, int n) { int i; printf("%4s %20s %20s %6s %6s %6s\n", "STT", "Ho ten", "Que quan", "Toan", "Ly", "Hoa"); for (i = 0; i < n; i++) printf("%4d %20s %20s %6.1f %6.1f %6.1f\n", i + 1, pSv[i].HoTen, pSv[i].Que, pSv[i].DiemToan, pSv[i].DiemLy, pSv[i].DiemHoa); }

BÀI TẬP CHƯƠNG 5 Bài 1. Xây dựng một cấu trúc (ứng với phiếu điểm của thí sinh) gồm các thành phần:

- Họ tên

- Quê quán

- Trường

- Tuổi

- Số báo danh

- Điểm thi

trong đó Họ tên lại là một cấu trúc gồm ba thành phần: Họ, tên đệm và tên. Quê quán cũng là một cấu trúc gồm ba thành phần: xã, huyện và tỉnh. Điểm thi là một cấu trúc gồm ba thành phần: toán, lý, hóa (điểm chấm chính xác đến 1/4).

Đọc số liệu từ một phiếu điểm cụ thể và lưu trữ vào các thành phần của cấu trúc nói trên, sau đó in các số liệu ra màn hình.

Bài 2. Sử dụng định nghĩa cấu trúc ở bài 1 :

Nhập số liệu của 20 phiếu điểm và lưu trữ vào mảng cấu trúc nói trên.

Page 86: Bai Giang Tin DC - nttoan.sitenttoan.site/wp-content/uploads/2019/01/Bai_Giang_Tin_DC_Lap_Trinh_C.pdf2 mỤc lỤc phẦn 1 .....4

87

Tìm kiếm và in ra các thí sinh có tổng số điểm ba môn lớn hơn 15.

Bài 3. Giả sử đã nhập số liệu của 20 phiếu điểm theo như yêu cầu của bài 2. Hãy lập chương trình sắp xếp lại các phần tử của mảng cấu trúc theo thứ tự giảm dần của tổng số điểm, sau đó in danh sách thí sinh (theo thứ tự nói trên). Mỗi thí sinh sẽ in trên một dòng gồm các thông tin:

- Họ tên

- Quê quán

- Số báo danh

- Điểm toán, lý, hóa.

Bài 4. Nhập danh sách n học sinh với các thuộc tính: họ tên, năm sinh và tổng điểm. Sắp xếp danh sách theo thứ tự giảm của tổng điểm. Khi tổng điểm như nhau thì học sinh có năm sinh nhỏ hơn được xếp trước. In danh sách học sinh đã sắp xếp sao cho tất cả các chữ cái của họ tên chuyển thành chữ hoa.

Bài 5. Định nghĩa kiểu cấu trúc mô tả đa thức, sau đó viết các hàm vào đa thức, in đa thức, cộng đa thức và nhân đa thức. áp dụng trong hàm main() để thực hiện các việc:

Vào từ bàn phím ba đa thức P1, P2 và P3. Tính đa thức P theo công thức:

P = (P1 + P2)2 + P3

In P1, P2, P3 và P.

Vào từ bàn phím một dẫy n đa thức, sau đó in chúng lên màn hình theo thứ tự giảm của bậc.