Bài giảng môn học Cơ sở lập trình

pdf 157 trang huongle 420
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng môn học Cơ sở lập trình", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên

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

  • pdfbai_giang_mon_hoc_co_so_lap_trinh.pdf

Nội dung text: Bài giảng môn học Cơ sở lập trình

  1. TRƯỜNG ĐẠI HỌC PHẠM VĂN ĐỒNG KHOA CÔNG NGHỆ THÔNG TIN TRẦN TẤN TỪ BÀI GIẢNG C” S” LAP TRÀNH (Dùng cho sinh viên các lớp đại học Công nghệ thông tin, đại học Sư phạm tin học) - Tài liệu lưu hành nội bộ -
  2. LỜI NÓI ĐẦU Cơ sở lập trình là học phần giúp cho sinh viên nắm được kiến thức cơ bản để cài đặt thành công một thuật toán thành chương trình bằng ngôn ngữ lập trình C. Qua đó, trang bị cho sinh viên kiến thức nền để tiếp cận và học tập tốt các ngôn ngữ lập trình khác trong các học kỳ tiếp theo. Bài giảng được biên soạn và giảng dạy cho sinh viên năm thứ nhất, bậc đại học ngành Công nghệ thông tin và ngành Sư phạm tin học kể từ năm 2008, theo hình thức đào tạo niên chế. Hiện nay chương trình đào tạo tại Trường Đại học Phạm Văn Đồng được chuyển đổi sang đào tạo theo học chế tín chỉ. Chính vì vậy, bài giảng được chỉnh sửa, bổ sung cho phù hợp với hình thức đào tạo theo học chế tín chỉ. Cũng nhân đây tôi xin chân thành cám ơn hội đồng chuyên môn khoa Công nghệ thông tin, Th.S Huỳnh Triệu Vỹ và Th.S Võ Đức Lân đã dành thời gian đọc và đóng góp nhiều ý kiến quý báu để bài giảng được hoàn chỉnh hơn, đáp ứng nhu cầu học tập của sinh viên Khoa Công nghệ thông tin - Trường Đại học Phạm Văn Đồng. Bài giảng không sao tránh khỏi những thiếu sót, mong các bạn đồng nghiệp đóng góp ý kiến để bài giảng hoàn thiện hơn trong các lần chỉnh sửa sau. Xin chân thành cám ơn quý thầy cô, các bạn đồng nghiệp ! Quảng Ngãi, ngày 25/12/2013 TRẦN TẤN TỪ
  3. Bài giảng Cơ sở lập trình -1- CHƯƠNG 1: CÁC THÀNH PHẦN CƠ BẢN Mục tiêu Kết thúc chương, sinh viên có thể:  Nắm được các thành phần cơ bản của ngôn ngữ lập trình C: bộ ký hiệu, từ khóa, tên và cách đặt tên, cách ghi lời chú thích.  Nắm được cấu trúc chung của một chương trình C.  Hiểu và vận dụng được các phép toán, các hàm đã được xây dựng cho các kiểu dữ liệu cơ sở: kiểu số nguyên, kiểu số thực, kiểu ký tự, kiểu boolean. 1.1 Bộ ký hiệu và từ khóa 1.1.1 Bộ ký hiệu - 26 chữ cái la tinh hoa: A, B, , Z. - 26 chữ cái la tinh thường: a, b, , z. - 10 chữ số thập phân: 0,1, ,9. - Các ký hiệu toán học: +, -, *, /, = , (, ). - Các ký hiệu đặc biệt: . , ; “ ‘ _ @ # $ ! ^ [ ] { } - Dấu cách hay khoảng trống. 1.1.2 Từ khóa Là các từ dùng riêng của ngôn ngữ lập trình C và mỗi từ khóa có một ý nghĩa và tác dụng cụ thể. * Chú ý: - Không thể định nghĩa lại từ khóa. - Các từ khóa trong C được viết dưới dạng chữ thường. Một số từ khóa thông dụng hay dùng trong ngôn ngữ lập trình C auto break case char continue default do double else extern float for goto if int long register return short sizeof static struct switch typedef union usnigned void volatile while asm . 1.1.3 Tên và cách đặt tên Trong chương trình, người lập trình có thể dùng rất nhiều tên: tên chương trình, tên biến, tên hằng, tên hàm, Mọi tên đều phải khai báo trước khi sử dụng. Qui tắc đặt tên: - Tên bao gồm dãy các ký tự liền nhau như các chữ cái a, ,z, A, Z, các chữ số 0, , 9 và dấu gạch nối dưới. Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  4. Bài giảng Cơ sở lập trình -2- - Tên không được bắt đầu bằng chữ số. - Tên không được chứa các ký tự đặc biệt như dấu cách, dấu chấm câu, Số ký tự tối đa trong tên của Turbo C là 32. - Tên không được trùng với từ khóa. - C là ngôn ngữ lập trình phân biệt chữ hoa và chữ thường, vì vậy tên NGHIEM sẽ khác với các tên: Nghiem, nghiem, . - Không được đặt tên bằng tiếng Việt (C xem cách làm đó là sai cú pháp) . - Các ví dụ về đặt tên: + Một số tên đặt đúng: Gia_tri, _DX, pi, . + Một số tên đặt sai: 3X, PI$, Bien 1, 1.1.4 Chú thích Khi viết chương trình bạn nên thêm vào các lời chú thích để cho chương trình sáng sủa và dễ hiểu. Trình biên dịch sẽ không biên dịch các chú thích để tạo ra mã chương trình mà nó có tác dụng thuyết minh thêm cho dễ hiểu. Phần văn bản nằm giữa cặp ký hiệu mở /* và đóng */ chính là phần chú thích. Phần chú thích có thể nằm trên nhiều dòng, miễn là nằm trong cặp dấu mở và đóng nêu trên. Lưu ý: Trong C++ lời chú thích nằm sau cặp dấu // và viết trên một dòng. 1.2 Cấu trúc chung của một chương trình C Cấu trúc tổng thể của một chương trình C thường có các khối thông dụng sau: #include /* để gọi các tập tin tiền xử lý */ #define /* định nghĩa các hằng số */ typedefs /* định nghĩa kiểu dữ liệu */ Function prototype /* khai báo nguyên mẫu hàm gồm tên và tham số */ Khai báo các biến ngoài . main() /* chương trình C bắt buộc phải có hàm main */ { Khai báo các biến cục bộ, các hằng của hàm main Các câu lệnh thực hiện của hàm main return } Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  5. Bài giảng Cơ sở lập trình -3- Function prototype /* định nghĩa nội dung tường minh của hàm */ { Khai báo các biến, hằng của hàm. Các câu lệnh thực hiện của hàm. } Như vậy, một chương trình C thường bao gồm các thành phần: các chỉ tiền xử lý, các định nghĩa: kiểu, hằng, khai báo biến ngoài, các hàm tự tạo, hàm main. Trong đó: + #include /* để gọi các tập tin tiền xử lý */ Ví dụ 1.1: #include + #define /* định nghĩa các hằng số */ Ví dụ 1.2: #define MAX 100 + typedef /* định nghĩa kiểu dữ liệu */ Ví dụ 1.3: typedef int Songuyen; + Function prototype /* khai báo nguyên mẫu hàm gồm tên và tham số */ Trong phần khai báo nguyên mẫu hàm, bạn chỉ ra kiểu giá trị trả về của hàm, tên hàm, tham số hình thức của hàm. Ví dụ 1.4: Khai báo nguyên mẫu hàm tính diện tích hình tròn float Tinh_dien_tich(float radius); + Khai báo các biến ngoài (biến toàn cục): Là nơi khai báo các biến có tầm tác dụng trong cả chương trình. Ví dụ 1.5: int n; + Trong chương trình C có thể có nhiều hàm, trong đó hàm main là hàm chính, bắt buộc phải có và các câu lệnh được thực hiện tuần tự từ trên xuống dưới. Về nguyên tắc hàm phải trả lại một giá trị cho tên hàm, nhưng nếu không muốn sử dụng giá trị trả về, bạn có thể viết như sau: void main(). Từ khóa void để chỉ hàm không có giá trị riêng của nó (tức hàm không mang một giá trị cụ thể nào khi thực hiện xong hàm) + /* định nghĩa nội dung tường minh của hàm */ Ví dụ 1.6: Định nghĩa nội dung hàm tính diện tích hình tròn với tham số là radius (bán kính của hình tròn). float Tinh_dien_tich(float radius) #define PI 3.14 Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  6. Bài giảng Cơ sở lập trình -4- { float dientich; dientich = PI*radius*radius; return(dientich); } Lưu ý: Định nghĩa của hàm Tinh_dien_tich sẽ được viết phía dưới hàm main. * Một số ví dụ: Ví dụ 1.7: Chương trình in ra màn hình chữ “Chao cac ban” và “Hen gap lai” Giải #include main() { printf(“Chao cac ban\n”); printf(“Hen gap lai\n”); getch(); } Giải thích chương trình ví dụ 1.7 F #include : Khai báo tập tin tiền xử lý stdio.h (viết tắt của từ standard input/output) là tập tin tiền xử lý chứa các hàm vào/ra chuẩn. Trong chương trình có sử dụng hàm printf (hàm ra chuẩn) được định nghĩa trong tập tin stdio.h. F Hàm printf là hàm cho in ra màn hình nội dung nằm trong cặp dấu “ ” F Ký tự \n là ký tự điều khiển xuống dòng mới. F Phần thân của chương trình bao gồm đoạn chương trình: main() { . } F getch(); Khi chương trình viết ra màn hình 2 câu “Chao cac ban” và “Hen gap lai” thì dừng lại cho người sử dụng xem. Nếu không có lệnh này thì chương trình trở về màn hình văn bản chương trình, người sử dụng sẽ không xem được kết quả, lúc đó phải bấm tổ hợp phím Alt + F5 mới xem được kết quả. Ví dụ 1.8: Chương trình tính diện tích hình tròn. Giải Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  7. Bài giảng Cơ sở lập trình -5- #include main() { float R,Dien_tich; printf(“Nhap ban kinh R = “); scanf(“%f”,&R); Dien_tich = 3.14*R*R; printf(“Dien tich hinh tron co ban kinh %f là %f”,R,Dien_tich); getch(); } Giải thích chương trình ví dụ 1.8 F float R, Dien_tich; Khai báo biến R và Dien_tich có kiểu số thực. F printf(“Nhap ban kinh R = “); in ra màn hình dòng: Nhap ban kinh R = F scanf(“%f”,&R); Hàm đọc giá trị từ bàn phím vào cho biến R. %f là mã định dạng để qui định đọc giá trị vào cho biến R có kiểu số thực, &R được hiểu là đọc giá trị vào cho ô nhớ của biến R. F Dòng lệnh printf(“Dien tich hinh tron co ban kinh %f là %f”,R,Dien_tich); In ra giá trị của biến R và biến Dien_tich với qui cách in là số thực. Ví dụ 1.9: Chương trình tính diện tích hình tròn có sử dụng chương trình con. Giải #include main() float Tinh_dien_tich(float radius); main() { float R; pritnf(“Nhap ban kinh R = “); scanf(“%f”,&R); printf(“Dien tich hinh tron = %f “,Tinh_dien_tich(R)); getch(); } float Tinh_dien_tich(float radius) #define PI 3.14 { float dientich; dientich = PI*radius*radius; Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  8. Bài giảng Cơ sở lập trình -6- return(dientich); } Giải thích chương trình ví dụ 1.9 F #define PI 3.14. Đây là khối ghép định nghĩa một macro. Với định nghĩa này, khi ngôn ngữ lập trình C dịch chương trình, bất cứ chỗ nào trong chương trình xuất hiện tên PI sẽ được thay thế bằng 3.14. F Việc tính diện tích được thực hiện bằng hàm Tinh_dien_tich với tham số là radius. Nguyên mẫu hàm Tinh_dien_tich được khai náo trước hàm main() và định nghĩa tường minh nội dung của hàm ở sau hàm main. 1.3 Kiểu dữ liệu cơ sở 1.3.1 Kiểu dữ liệu Dữ liệu là dạng biểu diễn vật lý của thông tin. Những dạng dữ liệu cơ bản được xử lý trong máy tính điện tử gồm: Các ký tự, hình ảnh, âm thanh, tri thức, sự kiện, luật dẫn. Theo nghĩa rộng, dữ liệu thô là các số, ký tự, hình ảnh hay các kết quả khác của các thiết bị chuyển đổi các lượng vật lý thành các ký hiệu. Các dữ liệu loại này thường được xử lý tiếp bởi con người hoặc đưa vào máy tính. Trong máy tính, dữ liệu được lưu trữ và xử lý tại đó hoặc chuyển cho một người hay một máy tính khác. Dữ liệu thô là một thuật ngữ tương đối, bởi vì dữ liệu đã được xử lý tại bước này có thể là dữ liệu thô ở bước tiếp theo. Trong máy tính điện tử, dữ liệu được biểu diễn bằng chuỗi các ký hiệu của một bảng chữ cái nào đó, mà phổ biến nhất là bảng chữ cái nhị phân (gồm 2 ký hiệu “0” và “1”). Một chương trình máy tính là một tập hợp dữ liệu được hiểu là các lệnh. Kiểu dữ liệu là một tập hợp các giá trị mà một biến thuộc kiểu đó có thể nhận được và trên đó xác định một số phép toán. Các kiểu dữ liệu này thường được quy định bởi ngôn ngữ lập trình, hay nói cách khác mỗi ngôn ngữ lập trình có một tập các kiểu dữ liệu khác nhau. Trong các ngôn ngữ lập trình, mỗi kiểu dữ liệu chỉ biểu diễn được một miền giá trị xác định nào đó, sự giới hạn này là do phụ thuộc vào kích thước của vùng nhớ biểu diễn số đó. Vì vậy, các thông tin đặc trưng của một kiểu dữ liệu bao gồm: + Tên kiểu dữ liệu. + Kích thước vùng nhớ biểu diễn nó (tức miền giá trị). + Các phép toán sử dụng trên kiểu dữ liệu đó. 1.3.2 Kiểu số nguyên Là tập hợp các số nguyên có thể biểu diễn được trong máy tính và được định nghĩa với một số từ khóa. Mỗi từ khóa tương ứng với một kiểu số nguyên có dải biểu diễn giá trị trong phạm vi nhất định. Nhưng kiểu số nguyên cơ bản trong ngôn Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  9. Bài giảng Cơ sở lập trình -7- ngữ lập trình C là kiểu số nguyên có dấu, được định nghĩa với từ khóa int chiếm 2 byte. Bảng các từ khóa số nguyên và phạm vi biểu diễn Kiểu biến Từ khóa Số byte Phạm vi biểu diễn Character char 1 -128 +127 Integer int 2 -32768 +32767 Short Integer short 2 -32768 +32767 Unsigned character unsigned char 1 0 255 Unsigned Integer unsigned int 2 0 65535 Unsigned Short Integer unsigned short 2 0 65535 Long Integer long 4 -2147483648 +2147483647 Unsigned Long Integer Unsigned long 0 4294967295 Lưu ý: Kiểu char thực chất là kiểu ký tự, song C cho phép dùng các ký tự như là số nguyên. Vì vậy, khi tính toán trong biểu thưc số học thì kiểu char được sử dụng như là số nguyên (chỉ mã ASCII tương ứng của ký tự đó) nhưng khi tính toán trong biểu thức ký tự thì nó được hiểu là ký tự. Đây chính là sự mềm dẻo của ngôn ngữ lập trình C. Có nhiều phép tính được định nghĩa cho số nguyên: phép tính số học, phép tính quan hệ, phép tính logic số học. Bảng liệt kê các phép tính số học đối với kiểu số nguyên Phép toán Ký hiệu Ví dụ Cộng + a + b Trừ - a - b Nhân * a * b Chia lấy phần / a / b nguyên Chia lấy số dư % a % b Về nguyên tắc phép chia 2 số nguyên cho kết quả là số nguyên. Muốn nhận được kết quả là số thực, bạn phái viết (float) a / b. Ví dụ 1.10: a = 15; b = 2; Vậy kết quả a/b sẽ là 15/2 = 7. Bạn muốn nhận kết quả của phép chia là số thực phải viết: (float) a/b; Lúc đó 15/2 = 7.5 Để khởi tạo một biến có kiểu nguyên ta viết: int i; i = 10; Hoặc viết int i = 10; Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  10. Bài giảng Cơ sở lập trình -8- Hằng số nguyên có định kiểu trước: Để ghi hằng số nguyên với kiểu định trước bạn ghi thêm một ký tự vào cuối dãy số: L cho kiểu long, U cho kiểu Unsigned Integer, UL cho kiểu Unsigned Long. Ví dụ 1.11: 20000U là hằng số nguyên theo kiểu Unsigned Integer; * Cách biểu diễn số nguyên dưới dạng số Hecxa: + Ngoài cách viết theo dạng số thập phân, C còn quy ước cho phép viết số nguyên dưới dạng số Hecxa, ký tự bắt đầu 0x hoặc 0X. Chẳng hạn số 65 trong hệ thập phân được viết dưới dạng số Hecxa là 0X41. + Nếu viết số nguyên dưới dạng số ở hệ cơ số 8 thì ký tự bắt đầu 0. Chẳng hạn số 65 trong hệ thập phân được viết dưới dạng số ở hệ cơ số 8 là: 0101. Hai cách viết trên rất thuận lợi cho những người lập trình hệ thống. Lúc đó, một byte có thể biểu diễn hai chữ số Hecxa vì một số Hecxa được biểu diễn bằng một cụm số nhị phân 4 bít. Chẳng hạn: số 255 trong hệ thập phân, biểu diễn trong hệ Hecxa là 0xFF. Ví dụ 1.12: Chương trình tính tổng 2 số nguyên. Giải #include main() { int m=5,n=10; long tong; tong = m+n; getch(); } 1.3.3 Kiểu số thực Là tập hợp các số thực có thể biểu diễn được trong máy tính và được định nghĩa bởi một số từ khóa: float, double, long double. Trong máy tính số thực được biểu diễn dưới 2 dạng: dạng bình thường và dạng có phần mũ (dạng số khoa học). + Dạng bình thường: 3.14, 5.0 + Dạng số khoa học: 1.254567E+02 tương đương với 1.254567*102 = 125.4567 Phạm vi biểu diễn và độ chính xác của số thực lớn hơn nhiều so với số nguyên nên số thực thích hợp với những đại lượng cần giá trị lớn và độ chính xác cao. Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  11. Bài giảng Cơ sở lập trình -9- Bảng các từ khóa của số thực và phạm vi biểu diễn Kiểu biến Từ khóa Số Phạm vi biểu diễn byte Số thực với độ chính xác đơn float 4 3.4e-38 3.4e38 Single-precision floating-point độ chính xác 7 chữ số Số thực với độ chính xác kép double 8 1.7e-308 1.7e308 Double-precision floating-point độ chính xác 15 chữ số Số thực với độ chính xác kép (độ long 10 3.4e-4832 1.1e4932 dài lớn) double độ chính xác 19 chữ số Long double-precision floating- point Cách viết hằng số thực: + Không cần phần lẻ sau dấu chấm: 7. + Không cần dấu chấm ở phần định trị nếu có phần mũ: 2E-8 + Viết dạng bình thường: 5.6 + Không cần số 0 đầu tiên: .1512 + Chấp nhận dùng chữ e: 0.07e-3 Các phép tính số học đối với kiểu thực: Cộng, trừ, nhân, chia. Khác với kiểu số nguyên, phép chia (/) cho kết quả là số thực và không tồn tại phép toán % cho kiểu số thực. Khởi tạo biến số thực ta viết: float x; x = 7.43; Hoặc viết float x = 7.43; Hằng số thực định trước kiểu: Ta có thể viết hằng số thực với kiểu được định trước bằng cách ghi thêm ký tự vào cuối dãy số (F cho kiểu float, L cho kiểu Long). Ví dụ 1.13: 0.1234567E-33L là hằng số thực kiểu long. Các hàm số học dùng cho kiểu số nguyên và số thực Các hàm số học dùng cho kiểu số nguyên và kiểu số thực được định nghĩa trong tập tin tiền xử lý math.h và được sử dụng với các đối số là số nguyên hoặc số thực. Nếu ký hiệu i là tham số nguyên, f là tham số thực. Ta có bảng biểu diễn như sau: Hàm Kiểu giá trị trả về Tác dụng abs(i) Int Trả về giá trị tuyệt đối của số nguyên i fabs(d) Double Trả về giá trị tuyệt đối của số thực d sin(d) Double Trả về giá trị hàm sin cos(d) Double Trả về giá trị hàm cos Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  12. Bài giảng Cơ sở lập trình -10- cosh(d) Double Trả về giá trị hàm cosh tan(d) Double Trả về giá trị hàm tang exp(d) Double Trả về giá trị e mũ x log(d) Double Trả về giá trị hàm loga cơ số tự nhiên d pow(d1,d2) Double Trả về giá trị d1 mũ d2 floor(d) Double Hàm cắt tròn số ceil(d) Double Hàm làm tròn số fmod(d1,d2) Double Hàm lấy phần dư của phép chia d1/d2 sqrt(d) Double Hàm khai căn bậc 2 srand(d) void Khởi tạo bộ số ngẫu nhiên, không có giá trị trả về Lưu ý: Các hàm số học chứa trong tập tin tiền xử lý math.h và bạn phải khai báo ở đầu chương trình theo cú pháp: #include Ví dụ 1.14: floor(3.146) = 3 floor(3.746) = 3 ceil(56.678) = 57 ceil(-56,678) = -57 1.3.4 Kiểu ký tự Được định nghĩa với từ khóa char, bao gồm tất cả các ký tự thường dùng: + Chữ cái a, b, c. + Chữ số 0, ,9. + Các dấu chấm phân đoạn câu: , ! Một hằng ký tự được viết trong cặp dấu nháy đơn. Chẳng hạn: ‘a’; ‘0’; và mỗi hằng ký tự được lưu trữ trong một byte ô nhớ. Một giá trị kiểu ký tự là 1 phần tử của một tập hữu hạn các ký tự được sắp xếp có thứ tự. Có nhiều cách sắp xếp bộ chữ khác nhau (không tồn tại 1 bộ chữ chuẩn cho tất cả các máy tính). Tuy vậy, bộ mã các ký tự được dùng rộng rãi và phổ biến để trao đổi thông tin giữa các máy vi tính là bộ mã ASCII (American Standard Code for Information Interchange). Ở đây ta quan tâm tới 128 ký tự đầu của bảng mã ASCII (phần chuẩn để xây dựng bộ ký tự cho các ngôn ngữ lập trình) Khi thực hiện chương trình, một số ký tự không nhìn thấy được trên màn hình, cụ thể được trình bày trong bảng sau: Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  13. Bài giảng Cơ sở lập trình -11- Bảng mã hóa các ký tự không nhìn thấy được Giá trị trong bảng mã ASCII Ký tự Dãy mã Hexa-Decimal Decimal Đỗ chuông (BEL) \a 0x07 7 Xóa trái (BackSpace) \b 0x08 8 Nhảy cách ngang (HT) \t 0x09 9 Xuống dòng mới (LF) \n 0x0A 10 Nhảy cách đứng (VT) \v 0x0B 11 Xuống dưới (FF) \f 0x0C 12 Về đầu dòng (CR) \r 0x0D 13 Dấu “ \“ 0x22 34 Dấu ‘ \‘ 0x2C 39 Dấu ? \? 0x3F 63 Dấu \ \\ 0x5C 92 Mã null \0 0x00 00 Ví dụ 1.15: Muốn in ra màn hình chữ “Chao ban” với tiếng chuông phát ra trước và sau khi viết ra chữ “Chao ban” thì bạn viết lệnh: printf(“\a Chao ban\a”); Ngoài ra bạn cũng có thể sử dụng cách viết dưới dạng hệ cơ số 16 hay hệ cơ số 8. Chẳng hạn ký tự ‘A’ có thể được viết \x41 hay \101. Cách viết này thường được áp dụng cho nữa sau của bảng mã ASCII (vì nữa sau của bảng mã ASCII có hình dạng và vị trí khó nhớ). Khởi tạo giá trị cho biến ký tự: const char RC = ‘\r’; LF = ‘\n’; ESC = ‘0x1B’; Các hàm xử lý ký tự nằm trong tập tin tiền xử lý ctype.h. Một số hàm xử lý ký tự Hàm Kiểu giá trị trả về Tác dụng Trả về mã ASCII của ký tự toASCII(c) int chứa trong biến ký tự c Trả về ký tự thường của ký tolower(c) int tự chứa trong biến ký tự c Trả về ký tự hoa của ký tự toupper(c) int chứa trong biến ký tự c Ví dụ 1.16: Chương trình đọc từ bàn phím một ký tự thường, chuyển thành ký tự hoa và in ra màn hình. Giải: Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  14. Bài giảng Cơ sở lập trình -12- #include #include main() { char kytu_thuong, kytu_hoa; kytu_thuong = getchar(); kytu_hoa = toupper(kytu_thuong); putchar(kytu_hoa); } Trong chương trình ở ví dụ 1.16, hàm getchar() để nhận một ký tự từ bàn phím và hàm putchar() viết một ký tự lên màn hình. Các hàm này nằm trong tập tin ctype.h. 1.3.5 Kiểu dữ liệu Boolean Trong thực tế ta thường gặp loại đại lượng chỉ nhận một trong hai giá trị: đúng (TRUE) hoặc sai (FALSE). Nhưng trong C kiểu dữ liệu boolean không được định nghĩa một cách tường minh, nó ẩn núp dưới dạng số nguyên. Trong C, những kết quả tính toán và trả về là số nguyên giá trị bằng 0 sẽ được hiểu là giá trị FALSE, còn kết quả trả về khác 0 (thông thường là 1) được hiểu là TRUE. Các phép toán của kiểu boolean Toán tử logic Phép toán logic Ý nghĩa && AND Phép “và” logic || OR Phép “hoặc” logic ! NOT Phép “đảo” hay “phủ định” logic Bảng chân trị của các phép toán logic X Y X && Y X || Y !X 0 0 0 0 1 0 Số khác 0 0 1 1 Số khác 0 0 0 1 0 Số khác 0 Số khác 0 1 1 0 Ví dụ 1.17: Kết quả của câu lệnh printf(“%d”,0&&3); là 0 trên màn hình. 1.4 Câu hỏi và bài tập chương 1 1. Tên dùng để làm gì ? Quy tắc đặt tên trong ngôn ngữ lập trình C ? 2. Chương trình nguồn là gì ? Có mấy loại chương trình dịch ? 3. Kiểu dữ liệu là gì ? Các thông tin đặc trưng của kiểu dữ liệu ? 4. Trình bày các kiểu dữ liệu cơ sở trong ngôn ngữ lập tình C. Với mỗi kiểu nêu khái niệm, từ khóa, số byte biểu diễn, phạm vi biểu diễn ? Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  15. Bài giảng Cơ sở lập trình -13- CHƯƠNG 2: TIỀN XỬ LÝ - HẰNG - BIẾN - TOÁN TỬ BIỂU THỨC - CÂU LỆNH Mục tiêu Kết thúc chương, sinh viên có thể:  Hiểu được ý nghĩa và cách sử dụng của các tập tin tiền xử lý thông dụng.  Nắm được các khái niệm: hằng, biến, toán tử, biểu thức, câu lệnh và cách sử dụng. 2.1 Tiền xử lý Để thực hiện một chương trình trong C, chương trình nguồn của bạn cần được dịch sang ngôn ngữ máy bằng chương trình dịch (compiler), nhưng trước tiên phải trải qua một bước liên kết với các đối tượng cần thiết khác, công việc này được thực hiện bởi bộ tiền xử lý. Thật vậy, khi viết một chương trình C, bạn sẽ không viết tất cả mà chỉ viết những gì liên quan trực tiếp đến các công việc của bạn, phần còn lại thường là rắc rối thì C đã viết sẵn và bạn chỉ sử dụng nó như là tài nguyên. Bộ tiền xử lý giúp bạn tìm và liên kết chương trình nguồn với các tài nguyên này. Lúc biên dịch thành công, bạn sẽ thấy trên đĩa ngoài tập nguồn do bạn viết, bạn thấy có vài tập tin khác cùng tên nhưng có đuôi .obj, .exe. Các lệnh C mà bạn sẽ dùng là rất nhiều, vì vậy để thuận lợi cho quá trình viết chương trình, các nhà phát triển ngôn ngữ C đã viết các lệnh này vào trong các tập tin tiền xử lý theo một tiêu chí phục vụ nào đó. Chẳng hạn, bộ các lệnh nhập, bộ các lệnh xuất, bộ các hàm toán học, bộ các lệnh xử lý chuỗi ký tự, bộ các lệnh tương tác màn hình, bộ các lệnh máy in, bộ các lệnh cho các thuật toán kinh điển, Tuy nhiên, khi viết chương trình, không phải lúc nào bạn cũng sử dụng tất cả các bộ lệnh này mà bạn dùng bộ lệnh nào thì chỉ cần chỉ ra tập tin chứa bộ lệnh đó theo cú pháp: #include hoặc là #include “Tên tập tin cần liên kết” Hai cách viết này chỉ khác nhau ở cách tìm kiếm bộ tiền xử lý: Cách viết đầu tìm kiếm rộng hơn, trong cả thư mục C; Cách viết thứ nhì chỉ thực hiện tìm kiếm trong thư mục làm việc của C, khi tập tin tìm kiếm không có ở đó, chương trình sẽ báo lỗi. Trong chương trình, nếu có nhiều tập tin cần liên kết, bạn viết chúng lần lượt mỗi tập tin trên một dòng và được đặt ở đầu chương trình nguồn. Chẳng hạn: #include #include Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  16. Bài giảng Cơ sở lập trình -14- Các dòng khai báo trên không phải là lệnh nên không có dấu chẩm phẩy ở cuối câu. Tập tin tiền xử lý có đuôi .h (header) chứa các định nghĩa macro, các hàm thông dụng được định nghĩa trước. Tóm lại: Trong ngôn ngữ lập trình C, việc dịch một tập tin nguồn thành tập tin thực thi được tiến hành qua 2 bước độc lập nhau: Tiền xử lý (Preprocessor) và biên dịch (Tranlation). Hai bước này được nối tiếp nhau một cách tự động theo cách thức mà bạn có ấn tượng rằng nó đã thực hiện như là một xử lý duy nhất. Sự giống và khác nhau của 2 chỉ thị #include và #define: + Chỉ thị #include được sử dụng nhằm gộp vào nội dung của các tập tin cần có (header file), không thể thiếu trong việc sử dụng các hàm thư viện chuẩn. + Chỉ thị #define hay được sử dụng trong các tập tin tiền xử lý đã được định nghĩa trước đó và thường được các lập trình viên khai thác khi định nghĩa các ký hiệu, chẳng hạn: #define SIZE 20 CÁC TẬP TIN TIỀN XỬ LÝ THÔNG DỤNG F stdio.h: Tập tin định nghĩa các hàm vào ra chuẩn (standard input/output) như: printf(), scanf(), getc(), putc(), gets(), puts(), fflush(), fopen(), fclose(), fread(), fwrite(), getchar(), putchar(), F conio.h: Tập tin chứa các định nghĩa vào/ra trong chế độ DOS console như: clrscr(), getch(), getche(), getpass(), cgets(), cputs(), putch(),clreol(), kbhit(), F math.h: Tập tin định nghĩa các hàm tính toán như: abs(), sqrt(), log(), log10(), sin(), cos(), acos(), asin(), atan(), pow(), exp(), F alloc.h: Tập tin định nghĩa các hàm liên quan đến việc cấp phát và quản lý bộ nhớ, như: calloc(), realloc(), malloc(), free(); farmalloc(), farcalloc(), farfree(), F io.h: Tập tin định nghĩa các hàm vào/ra cấp thấp, như: open(), _open(), read(), _read(), close(), _close(), creat(), _creat(), creatnew(), eof(), filelength(), lock(), F ctype.h: Tập tin định nghĩa các hàm xử lý ký tự, như: toASCII(), tolower(), toupper(), F stdlib.h: Tập tin định nghĩa các hàm liên quan đến cấp phát bộ nhớ. F string.h: Tập tin định nghĩa các hàm xử lý xâu ký tự. F dos.h: Tập tin định nghĩa các hàm để đọc và xác lập thời gian, ngày tháng năm. F graphics.h: Tập tin định nghĩa các hàm liên quan đến đồ họa, như: initgraph(), line(), circle(), putpixel(), getpixel(), setcolor(), Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  17. Bài giảng Cơ sở lập trình -15- 2.2 Hằng (Constant) 2.2.1 Khái niệm: Là đại lượng có giá trị không đổi trong suốt thời gian sử dụng trong chương trình. Hằng được lưu trữ trong bộ nhớ và có tên để dễ sử dụng. 2.2.2 Định nghĩa hằng: - Dùng chỉ thị #define: + Cú pháp: #define + Tác dụng: Tên_hằng được thay thế bởi Giá_trị_hằng. Với cách này có thể định nghĩa lại được giá trị của hằng. + Ví dụ 2.1: #define MAX 100 Trong chương trình chỗ nào gặp MAX sẽ được thay bằng giá trị 100 + Chú ý: Không có dấu chấm phẩy ở cuối câu định nghĩa hằng. - Sử dụng từ khóa const: + Cú pháp: const = ; const = ; + Tác dụng: Định nghĩa một hằng có tên là tên_hằng có giá trị bằng giá_trị_hằng và sau này không thể định nghĩa lại (sửa đổi) giá trị của hằng. + Ví dụ 2.2: const long double PI = 3,141592653589793; Const d = 7; /* hằng d kiểu integer, có giá trị bằng 7 */ + Lưu ý: Trong kiểu định nghĩa thứ 2, chương trình tự động ấn định kiểu của hằng là kiểu ngầm định, với turbo C hằng có kiểu ngầm định là int. * Sự khác nhau giữa khai báo hằng số bằng define và const ở chỗ là: + Với const, đây là hằng số cố định, một hằng số thực sự, không thể định nghĩa lại. + Khi gặp hằng định nghĩa bằng #define thì chương trình dịch sẽ lắp giá trị hằng số này vào trong biểu thức cần tính. Điều đó, có nghĩa là khi gặp tên hằng, thì máy sẽ dành ra số ô nhớ đủ để chứa giá trị hằng vào đó. Loại hằng này không thể định nghĩa lại trong quá trình sử dụng. Nó được áp dụng cho loại hằng số, hằng xâu ký tự, hằng logic, Thực chất của define là sẽ được thay thế tượng trưng cho đoạn văn bản, đó là . Khi dịch, chương trình sẽ thay thế bằng . 2.2.3 Các loại hằng: F Hằng int: Là số nguyên có kiểu int. F Hằng long: Biểu diễn thêm L hay l vào sau hằng int. F Hằng usigned: Biểu diễn thêm u vào sau hằng int. Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  18. Bài giảng Cơ sở lập trình -16- F Hằng int hệ 8 hoặc hệ 16: Các hằng số trong C được ngầm hiểu là ở hệ 10, nhưng bạn hoàn toàn có thể viết hằng trong hệ cơ số 8 (bắt đầu bằng 0) hay cơ số hệ 16 (bắt đầu bằng 0X). Ví dụ 2.3 : 025, 057, 0x24, 0x41, F Hằng ký tự: Là một ký tự được viết trong cặp dấu nháy đơn, Ví dụ 2.4: ‘A’, ‘3’, ‘+’, Trình biên dịch C sẽ lưu trữ các hằng này bằng cách dùng mã ASCII ở hệ cơ số 10. C lưu các hằng này thông qua mã ASCII của nó (trong hệ 10). Với ví dụ 2.4, các giá trị được lưu trữ tương ứng: 97, 43, 51 F Đối với các hằng ký tự đặc biệt, C quy định cách viết: ‘\’’ biểu diễn cho hằng ’ ‘\”’ biểu diễn cho hằng ” ‘\\’ biểu diễn cho hằng \ ‘\n’ biểu diễn ký tự xuống dòng ‘\0’ biểu diễn cho hằng 0 ‘\t’ biểu diễn ký tự tab ‘\r’ biểu diễn về đầu dòng ‘\b’ biểu diễn ký tự backspace ‘\f’ biểu diễn sang trang F Hằng xâu ký tự (chuỗi ký tự): Giá trị của hằng là dãy các ký tự được bao trong hai dấu nháy kép. Ví dụ 2.5: “Truong Dai hoc”; * Chú ý: Các hằng có thể được định nghĩa ngoài mọi hàm, trong hàm hoặc trong một khối lệnh. Với C chuẩn, khi định nghĩa trong một khối thì dòng lệnh định nghĩa phải ở các dòng đầu tiên của khối, tức là trước tất cả các lệnh khác của khối lệnh. Trong C++ bạn có thể đặt định nghĩa hằng ở bất kỳ vị trí nào. 2.3 Biến (Variable) - Khái niệm: Là đại lượng có giá trị thuộc một kiểu nào đó của ngôn ngữ lập trình, giá trị của biến có thể được thay đổi trong thời gian tồn tại của biến. Biến được lưu trữ trong bộ nhớ trong và có tên để dễ sử dụng. Chương trình có thể truy xuất đến ô nhớ được cấp phát cho biến để lấy hoặc ghi giá trị thông qua tên biến. Muốn sử dụng biến bạn phải khai báo trước khi sử dụng. - Cú pháp khai báo biến: ; = ; Trong đó: + : Là tên một kiểu dữ liệu tồn tại trong ngôn ngữ lập trình, có thể là kiểu dữ liệu chuẩn hoặc kiểu dữ liệu được định nghĩa bởi người lập trình. + : Tên các biến cùng kiểu, đặt cách nhau bởi dấu phẩy. + : Giá trị khởi tạo cho biến. Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  19. Bài giảng Cơ sở lập trình -17- Như vậy, đặc trưng của biến gồm: tên biến, kiểu dữ liệu của biến, giá trị nó đang lưu giữ. Trong ngôn ngữ lập trình C biến có thể có thể có kiểu void (kiểu không xác định). Tên của biến trong C được đặt theo nguyên tắc đặt tên của ngôn ngữ lập trình C (đã trình bày trong phần 1.1.3 trang 1) - Ví dụ 2.6: Cách khai báo các biến có kiểu số nguyên, số thực, ký tự main() { int m = 5, n = 10; /* Khai báo biến số nguyên m, n và khởi tạo giá trị*/ float x,y; /* Khai báo biến số thực */ char kt = ‘A’; /* Khai báo biến ký tự và khởi tạo giá trị*/ } Lưu ý: Khi gặp các lệnh định nghĩa biến, chương trình dịch sẽ cấp phát vùng nhớ có kích thước phù hợp với kiểu dữ liệu của biến, nếu có thành phần khởi tạo thì chương trình sẽ gán giá trị khởi tạo vào vùng nhớ của biến. Địa chỉ của byte đầu tiên trong vùng nhớ được cấp phát cho biến, chính là địa chỉ của biến. Để lấy địa chỉ của biến, bạn dùng cú pháp: & ; 2.4 Biểu thức và toán tử 2.4.1 Biểu thức (Expression) - Khái niệm: Biểu thức là một tập hợp gồm các hằng, hàm, biến, toán tử Biểu thức được tính toán theo một nguyên tắc toán học nào đó để cho ra một giá trị. Trong một biểu thức có 2 thành phần chính: Toán tử (operator) được viết ra bằng dấu phép toán; Toán hạng (operand) có thể là hằng, hàm, biến. - Ví dụ 2.7: 15 + sin(x); Dấu + là toán tử, 15 và sin(x) là các toán hạng. - Các loại biểu thức: + Biểu thức số học là biểu thức mà kết quả tính toán cho ra giá trị bằng số (số nguyên, số thực). + Biểu thức logic: Trong ngôn ngữ lập trình C biểu thức logic là biểu thức mà kết quả tính toán cho ra giá trị TRUE (giá trị khác 0 mà thường là 1) hoặc FALSE (giá trị bằng 0). + Biểu thức quan hệ là biểu thức có chứa các toán tử quan hệ ( , =, ==, != ). Các toán hạng trong biểu thức quan hệ có thể là số nguyên, số thực, ký tự và chúng không nhất thiết phải tương thích với nhau về kiểu. 2.4.2 Toán tử (Operator) 2.4.2.1 Toán tử số học Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  20. Bài giảng Cơ sở lập trình -18- - Toán tử số học được hổ trợ bởi ngôn ngữ lập trình C là: + (Cộng) - (Trừ) * (Nhân) / (Chia) % (lấy phần dư trong phép chia 2 số nguyên) - Ví dụ 2.8: int x = 15, y = 2, z; z = x % y;  Kết quả phép tính cho ra z = 1; Thứ tự thực hiện các phép toán giống như trong toán học. 2.4.2.2 Toán tử thao tác bít - Trong ngôn ngữ lập trình C có nhóm các toán tử mà thao tác của nó thực hiện trên từng bít của các toán hạng, được gọi là toán tử thao tác bít. Các toán hạng tham gia vào biểu thức có toán tử thao tác bít phải có kiểu số nguyên. Các phép tính này liên quan đến biểu diễn nhị phân trong máy tính. - Toán tử & (phép AND theo bít) + Cú pháp: & + Chức năng: Thực hiện phép AND trên từng bít của 2 toán hạng và trả về kết quả có cùng kích thước với 2 toán hạng. + Bảng chân trị của phép & & 0 1 0 0 0 1 0 1 + Ví dụ 2.9: int a = 7, b= 14, c; c = a & b;  Kết quả cho ra c = 6. - Toán tử | (phép OR theo bít) + Cú pháp: | + Chức năng: Thực hiện phép OR trên từng bít của 2 toán hạng và trả về kết quả có cùng kích thước với 2 toán hạng. Các bít trả về được tính bằng kết quả phép tuyển giữa 2 bít tương ứng của toán hạng 1 và toán hạng 2. + Bảng chân trị của phép | Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  21. Bài giảng Cơ sở lập trình -19- | 0 1 0 0 1 1 1 1 + Ví dụ 2.10: int a = 7, b= 14, c; c = a | b; Kết quả cho ra c = 15. - Toán tử ~ (phép đảo bít) + Cú pháp: ~ ; + Chức năng: Toán tử ~ là toán tử một ngôi, thực hiện đảo các bít của toán hạng: bít 1 trở thành 0, bít 0 trở thành 1. + Ví dụ 2.11: int a = 3; b = ~a; Kết quả cho ra b = 252. - Toán tử ^ (phép tuyển loại trừ XOR) + Cú pháp: ^ ; + Chức năng: Thực hiện phép XOR trên từng bít của 2 toán hạng và kết quả trả về là số nguyên có cùng kích thước với 2 toán hạng. Các bít trả về được tính bằng kết quả của phép XOR giữa 2 bít tương ứng của toán hạng 1 và toán hạng 2. + Bảng chân trị của phép ^ ^ 0 1 0 0 1 1 1 0 + Ví dụ 2.12: int a = 3, b= 10,c; c = a^b; Kết quả cho ra c = 9. - Toán tử ; + Chức năng: Dịch chuyển tuần tự các bít của Toán_hạng_1 sang trái, số lần dịch chuyển bằng giá trị của Toán_hạng_2. Với mỗi lần dịch chuyển thì bít trái nhất sẽ bị loại bỏ, các bít bên phải sẽ được tuần tự dịch sang trái 1 vị trí, bít bên phải nhất sẽ được lấp bằng giá trị 0. + Ví dụ 2.13: int a = 12, b; b = a << 1; Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  22. Bài giảng Cơ sở lập trình -20- Kết quả cho ra b = 24. Như vậy, khi dịch trái số a với số lần dịch là k, nếu chưa xảy ra các bít có giá trị 1 của a bị mất, thì kết quả thu được là a*2k. Tuy nhiên, khi dịch trái k bít, có khả năng một số bít cao nhất có giá trị 1 của a bị loại bỏ, lúc đó kết quả phép dịch là a*2k %2L (L là số bít 1 bị loại bỏ) - Toán tử >> (phép dịch phải) + Cú pháp: >> ; + Chức năng: Dịch chuyển tuần tự các bít của Toán_hạng_1 sang phải, số lần dịch chuyển bằng giá trị của Toán_hạng_2. Với mỗi lần dịch chuyển thì bít bên phải nhất sẽ bị loại bỏ, các bít bên trái được tuần tự dịch sang phải 1 vị trí, bít bên trái nhất sẽ được lấp bằng giá trị 0. + Ví dụ 2.14: int a = 12, b; b = a >> 1; Kết quả cho ra b = 6. Như vậy, khi dịch trải số a với số lần dịch là k thì thu được kết quả a/2k; F Toán tử > là 2 toán tử được dùng trong một số phép tính đặc biệt (nhân hay chia số nguyên với một số lũy thừa của 2) nhằm nâng cao tốc độ tính toán mặc dù khi viết ra có thể dài dòng. Ví dụ 2.15: Trong một đoạn chương trình có thực hiện phép tính I*80, để tối ưu cho việc tính toán nhằm nâng cao tốc độ tính toán, bạn nên viết phép tính dưới dạng: (I = So sánh lớn hơn hoặc bằng So sánh lớn hơn < So sánh nhỏ hơn Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  23. Bài giảng Cơ sở lập trình -21- - Lưu ý: + Toán tử == (hai dấu bằng) là toán tử quan hệ dùng để so sánh 2 biểu thức có bằng nhau hay không. Dấu = (một dấu bằng) là toán tử gán dùng để gán biểu thức bên phải cho biến ở vế bên trái. + Hai vế của biểu thức so sánh phải cùng kiểu (trừ kiểu thực và kiểu nguyên) và chúng có thể là kiểu số nguyên, số thực, char - Ví dụ 2.16: Kết quả của phép tính (7==5) là 0 Kết quả của phép tính (6 >= 6) là 1 2.4.2.5 Toán tử điều kiện 3 ngôi - Cú pháp: ? : ; Trong đó: Biểu_thức, Giá_trị_1, Giá_trị_2 là các biểu thức. - Tác dụng: Toán tử điều kiện 3 ngôi sẽ tính toán Biểu_thức và ước lượng giá trị của nó, nếu Biểu_thức có giá trị đúng thì biểu thức Giá_trị_1 được tính toán và trở thành giá trị của biểu thức, nếu Biểu_thức có giá trị sai thì biểu thức Giá_trị_2 được tính toán và trở thành giá trị của biểu thức. - Ví dụ 2.17: int x = 5, y = 7, z; z = x > y? x:y; Kết quả phép tính z = 7; 2.4.2.6 Các toán tử khác - Toán tử tăng (++) và toán tử giảm ( ): Giúp cho chương trình tăng hoặc giảm giá trị chứa trong một biến đi 1 đơn vị. Chúng tương đương với +=1 hoặc -=1. Vì vậy, các dòng lệnh sau là tương đương: A++; A+=1; A = A + 1; Tính chất của toán tử này có thể là tiền tố hoặc hậu tố, nghĩa là toán tử ++, có thể viết trước tên biến (++A) hoặc viết sau tên biến (A++). Trong những trường hợp đơn giản, hai cách viết trên có cùng ý nghĩa, nhưng trong các thao tác khác, khi mà kết của việc tăng hay giảm được sử dụng trong một biểu thức thì chúng có thể có một ý nghĩa khác biệt quan trọng về mặt ý nghĩa. + Ví dụ 2.18: B = 3; A = ++B;  Kết quả xuất ra A = 4, B = 4. Nhưng nếu thực hiện đoạn lệnh sau: Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  24. Bài giảng Cơ sở lập trình -22- B = 3; A = B++;  Kết quả xuất ra A = 3, B = 4. Như vậy, trong trường hợp toán tử được sử dụng như là tiền tố, giá trị được tăng trước khi biểu thức được tính và giá trị đã tăng được sử dụng trong biểu thức. Trong trường hợp ngược lại, toán tử được sử dụng như là hậu tố, giá trị trong biến chỉ được tăng sau khi đã tham gia tính toán trong biểu thức. - Toán tử dấu phẩy (,): Mỗi câu lệnh của C được kết thúc bằng dấu chấm phẩy, song nó có thể chứa một dãy lệnh (dãy biểu thức tính toán độc lập) chứ không phải chỉ có một biểu thức tính một giá trị. Trong trường hợp đó, C cung cấp cho bạn toán tử dấu phẩy (,) được sử dụng để kết hợp các biểu thức lại với nhau. Bên trái toán tử dấu phẩy luôn được xem là kiểu void. Điều đó, có nghĩa là biểu thức bên phải trở thành giá trị của tổng các biểu thức được phân cách nhau bởi dấu phẩy. Ví dụ 2.19: x = (y=3,y+1); Cách tính toán của biểu thức trên: trước hết gán giá trị 3 cho y, rồi thực hiện tính y + 1 = 4, sau đó gán 4 cho biến x. Cặp dấu ngoặc đơn là cần thiết vì toán tử dấu phẩy có độ ưu tiên thấp hơn toán tử gán. - Toán tử sizeof (cho biết kích thước của kiểu dữ liệu, đối tượng dữ liệu) + Cú pháp: sizeof( ); sizeof( ); + Tác dụng: Cho biết kích thước (tính theo byte) của kiểu dữ liệu cũng như của đối tượng dữ liệu. + Ví dụ 2.20: int n,x; x = sizeof(n);  Kết quả của phép gán x = 2. - Toán tử & (lấy địa chỉ) + Cú pháp: & ; & ; + Tác dụng: Trả lại địa chỉ của một biến, hằng đã được cấp phát trong bộ nhớ trong. + Ví dụ 2.21: int x; printf(“%p”,&x);  In ra địa chỉ của biến x đã được cấp phát ở bộ nhớ trong. - Toán tử * (truy xuất giá trị qua con trỏ) + Cú pháp: * ; Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  25. Bài giảng Cơ sở lập trình -23- + Tác dụng: Truy xuất gián tiếp giá trị của biến thông qua con trỏ quản lý nó. + Ví dụ 2.22: int x = 5; int *p; p = &x; printf(“%d”,*p);  Kết quả in ra nội dung của biến x được quản lý bởi con trỏ p (tức in ra màn hình giá trị 5). 2.4.2.7 Độ ưu tiên của các toán tử Thứ tự ưu tiên của các toán tử được trình bày trong bảng sau (từ cao xuống thấp, trong mỗi mức thì ưu tiên từ trái sang phải) Thứ tự ưu tiên các phép toán Chiều tính toán ( ) [ ] -> Từ trái qua phải ! ~ & *(truy xuất gián tiếp) - (đổi dấu) Từ phải qua trái ++ (ép kiểu) sizeof * (phép nhân) / % Từ trái qua phải + - (phép trừ) Từ trái qua phải > (các phép dịch bít) trái qua phải , >= Từ trái qua phải == != Từ trái qua phải & (phép AND trên bít) ^ (phép XOR trên bít) | (phép OR trên bít) && || ?: = += -= *= /= %= >= &= Từ phải qua trái \+ ^= |= (dấu phẩy) Ví dụ 2.22: (100 > 76) && (‘B’ < ‘A’) 1 && 0 0 2.4.2.8 Chuyển đổi kiểu C cho phép trộn lẫn kiểu giá trị với nhau trong cùng biểu thức tính toán. Đồng thời mỗi loại kiểu dữ liệu phản ứng khác nhau đối với một phép toán. Trong Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  26. Bài giảng Cơ sở lập trình -24- một biểu thức có thể tồn tại nhiều toán hạng với kiểu số học khác nhau (số nguyên, số thực). Nguyên tắc là C sẽ tự động chuyển kiểu đơn giản lên kiểu cao hơn để tính toán và qui đổi ra kiểu kết quả. Chiều cấp bậc tăng dần được sắp xếp như sau: int  long  float  double  long double Ví dụ 2.23: short p1 = 2, p2 = 3, p3 = 3; float x = 15.2;  Kiểu của biểu thức (p1*p2 + p3*x) sẽ là kiểu số thực. Trong một số trường hợp bạn cũng có thể cố ý ra lệnh cho máy chuyển đổi kiểu dữ liệu để nhận được kết quả theo mong muốn. Ví dụ 2.24: int m = 15, n = 2; float x; x = m/n; /* Phép chia cho kết quả là phần nguyên 7 */ x = (float) m/n; /* Phép chia cho kết quả là số thực 7.5 */ 2.5 Câu lệnh (statement) 2.5.1 Khái niệm và phân loại - Khái niệm: Một câu lệnh xác định một công việc mà chương trình phải thực hiện để xử lý dữ liệu đã được mô tả và khai báo. Các câu lệnh được ngăn cách nhau bởi dấu chấm phẩy (;) - Phân loại: Có 2 loại câu lệnh: Câu lệnh đơn và câu lệnh có cấu trúc. + Câu lệnh đơn là câu lệnh không chứa các lệnh khác. Các loại câu lệnh đơn gồm: Câu lệnh gán, câu lệnh nhập dữ liệu, câu lệnh xuất dữ liệu, + Câu lệnh có cấu trúc là câu lệnh trong đó có chứa các lệnh khác. Câu lệnh có cấu trúc bao gồm: câu lệnh điều kiện rẽ nhánh, câu lệnh điều kiện lựa chọn, câu lệnh lặp, câu lệnh hợp thành (một nhóm bao gồm nhiều lệnh được gom vào trong cặp dấu { và } ). 2.5.2 Câu lệnh gán - Dùng để gán giá trị một biểu thức cho một biến. + Cú pháp: = ; + Tác dụng: Gán biến có tên ở vế trái nhận giá trị của biểu thức ở vế phải có kiểu phù hợp với biến. Lưu ý: Luôn thực hiện từ trái sang phải và không bao giờ đảo ngược. Chẳng hạn: bạn gán a = b; thì chương trình thực hiện gán giá trị của biến a bằng giá trị đang có trong biến b. Sau đó, biến b có thể thay đổi giá trị thì cũng không ảnh hưởng đến giá trị của biến a. + Ví dụ 2.25: int x,y; Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  27. Bài giảng Cơ sở lập trình -25- x = 10; y = x + 20; + Lưu ý: Một thuộc tính của toán tử gán trong C làm cho nó vượt lên các ngôn ngữ lập trình khác là: cho phép vế phải có thể chứa các phép gán khác. + Ví dụ 2.26: int a,b; a = 2 + (b = 5); Hai câu lệnh trên tương đương với: int a,b; b = 5; a = 2 + b; - Ngoài ra, trong C có thể gán giá trị một biểu thức cho nhiều biến + Cú pháp: = = = ; + Tác dụng: Sẽ lần lượt gán cho các biến từ phải qua trái. - Phép gán mở rộng (phép gán tích lũy) + Cú pháp: = ; Trong đó: : Là một biến thuộc kiểu số nguyên hoặc số thực, là một giá trị phù hợp, là dấu phép toán số học hay trên bít (hai ngôi): +, -, *, /, %, >, &, |, ^ + Tác dụng: = = ; + Các phép toán mở rộng gồm: x += y  x = x + y x -= y  x = x - y x *= y  x = x * y x /= y  x = x / y x %= y  x = x % y x >>= y  x = x >> y x <<= y  x = x << y x &= y  x = x & y x |= y  x = x | y x ^= y  x = x ^ y 2.6 Câu hỏi và bài tập chương 2 1. Hãy cho biết giá trị của t ? Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  28. Bài giảng Cơ sở lập trình -26- int a = 10; float b = 15; float t; t = b/a; 2. Cho biết kết quả của biểu thức sau ? (200 > 97) && (‘D’ > ‘A’) Giả sử trong biểu thức trên, ta bỏ dấu ngoặc thì về mặt ngữ pháp có đúng không? Giải thích vì sao? 3. Cho khai báo sau: int a = 2, b = 3, c = 4; Cho biết giá trị của a sau mỗi lệnh trong mỗi trường hợp sau: a. ++a; b. –a; c. a *= b; d. a = b % c; 4. Nếu a = 1 thì giá trị của b sau mỗi lệnh trong các trường hợp sau là bao nhiêu ? a. b = a >> 1; b. b = a n; q4 = n*(p>n>n:p); q5 = n*(p<n?p:p); x1 = p/n; x2 = (float) p/n; Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  29. Bài giảng Cơ sở lập trình -27- x3 = (p +0.5)/n; x4 = (int) (p + 0.5)/n; 6. Trong một chương trình, giả sử đã có khai báo các biến kiểu nguyên như sau: int n = 10, p = 5, q = 10, r; a. Cho biết kết quả của các biến n, p, q sau khi đã thực hiện lệnh: n = p = q = 5; n += p += q; b. Cho biết kết quả của các biến n, p, q sau khi đã thực hiện lệnh: q = n p?n++:p++; 7. Giả sử đã có khai báo biến: int n, p, q; Kết quả của biến n, p, q là mấy sau khi thực hiện các lệnh: a. n = 5; p = 2; q = (n++>p) || (p++ !3); b. n = 5; p = 2; q = (++n==3) && (++p == 3); c. n = 5; p = 2; q = (++n==6) && (++p == 3); Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  30. Bài giảng Cơ sở lập trình -28- CHƯƠNG 3: NHẬP VÀ XUẤT DỮ LIỆU Mục tiêu Kết thúc chương, sinh viên có thể:  Nắm được cú pháp và cách sử dụng các lệnh nhập, xuất dữ liệu trong C.  Biết cách xuất kết quả tại vị trí và màu sắc theo ý muốn. 3.1 Câu lệnh nhập dữ liệu 3.1.1 Nhập dữ liệu bằng hàm scanf Hàm nhập dữ liệu scanf được sử dụng phổ biến nhất trong C. Hàm scanf cho phép chúng ta nhập nhiều loại dữ liệu có các kiểu khác nhau. Khi dùng hàm này bạn phải rõ địa chỉ của biến lưu dữ liệu và kiểu của dữ liệu cần nhập. - Cú pháp: scanf(“Chuỗi_các_định_dạng”, Dãy_địa_chỉ_các_biến); - Chức năng: Hàm cho phép nhập dữ liệu từ bàn phím theo khuôn dạng được xác định trong chuỗi định dạng, dữ liệu nhập vào được lưu vào các biến có địa chỉ tương ứng được chỉ ra trong Dãy_địa_chỉ_các_biến. Các địa chỉ biến trong Dãy_địa_chỉ_các_biến được viết cách nhau bởi dấu phẩy. - Lưu ý: F Số các đặc tả trong Chuỗi_các_định_dạng phải tương ứng với số biến trong Dãy_địa_chỉ_các_biến. F Ký tự định kiểu trong đặc tả phải phù hợp với kiểu của biến tương ứng. F Dữ liệu nhập từ bàn phím phải phù hợp với các đặc tả. F Hàm scanf trả về số nguyên là số các trường hợp được nhập dữ liệu. - Ví dụ 3.1: int a,b; float x,y; printf(“Nhap cac gia trị ” ); scanf(“%d %d %f %f”,&a, &b, &x, &y); Chuỗi các định dạng Địa chỉ các biến - Trong Chuỗi_các_định_dạng gồm các đặc tả tương ứng với các biến trong Dãy_địa_chỉ_các_biến, có bao nhiêu địa chỉ biến thì cần bấy nhiêu các đặc tả. Mỗi đặc tả có dạng %[*][n] . + [n] là số nguyên dương quy định độ dài tối đa tính theo số ký tự được nhập cho thành phần tương ứng. + : Là ký tự quy định kiểu dữ liệu cần nhập. Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  31. Bài giảng Cơ sở lập trình -29- + [*] là thành phần tùy chọn, nếu có sẽ bỏ qua một thành phần dữ liệu được xác định bởi đặc tả này, tức là không có đối tượng tương ứng với đặc tả này. Ví dụ 3.2: int x,y; printf(“Nhap cac gia trị ” ); scanf(“%d %*c %d”, &x, &y); Với ví dụ 3.2 sẽ thực hiện nhập giá trị thực cho biến x, sau đó bỏ qua một thành phần là ký tự, tiếp tục nhập giá trị thực cho biến y. Bảng các ký tự định kiểu dùng cho hàm scanf Chuỗi các Ý nghĩa định dạng %c Đọc vào ký tự được cho biến khai báo kiểu char %d Đọc vào số nguyên cho biến khai báo kiểu int %u Đọc vào số nguyên cho biến khai báo kiểu unsigned int %hd Đọc vào số nguyên cho biến khai báo kiểu short int %hu Đọc vào số nguyên cho biến khai báo kiểu unsigned int %ld Đọc vào số nguyên cho biến khai báo kiểu long int %lu Đọc số nguyên cho biến khai báo kiểu unsigned long %f Đọc vào số thực float cho biến khai báo kiểu float (có thể nhập số theo kiểu viết thông thường hoặc kiểu viết theo số mũ) %e Giống như mã định dạng %f %lf hoặc %lu Đọc vào số thực cho biến khai báo kiểu Double %s Đọc xâu ký tự không chứa dấu cách, dùng với địa chỉ xâu %o Đọc vào số nguyên cho biến dưới dạng mã octal (hệ cơ số 8) %x Đọc vào số nguyên cho biến dưới dạng mã hexa (hệ cơ số 6)  Nguyên tắc đọc dữ liệu trong C: F Khi chúng ta nhập dữ liệu từ bàn phím, việc kết thúc nhập dữ liệu được xác định bằng phím enter. Lúc đó, những dữ liệu nhập từ bàn phím được lưu trong vùng đệm nhập dữ liệu gọi là dòng vào (stdin). Dòng vào này sẽ được cắt tuần tự từ trái qua phải thành từng trường và gán cho các biến, các phần đã được cắt ra sẽ bị loại bỏ khỏi dòng vào. F Trước khi tách một trường thì khoảng trắng phía trước của trường sẽ bị loại bỏ. Nếu trong đặc tả không có thành phần n quy định độ dài tối ta của một trường thì đọ dài của trường được xác định cho đến khi gặp dấu cách, tab, enter hoặc khi gặp ký tự không phù hợp với đặc tả (nếu có đặc tả cho dữ liệu nhập vào) Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  32. Bài giảng Cơ sở lập trình -30- F Nếu dòng vào có nhiều hơn các thành phần yêu cầu trong hàm nhập thì các thành phần chưa được cắt bỏ (chưa được nhận) vẫn còn lưu trên dòng vào. - Ví dụ 3.3: int a,b; float x; scanf(“%d %d %f”,&a,&b,&x); Giả sử lúc thực hiện chương trình, dữ liệu nhập trên dòng vào là: ∪228∪∪679∪58∪ ↵ (∪ thể hiện cho dấu cách) Lúc đó, việc đọc giá trị vào cho các biến được thực hiện như sau: F Khoảng trắng đầu tiên bị loại bỏ. F 228 là trường thứ nhất được tách ra và gán cho biến a. F Hai khoảng trắng tiếp theo bị loại bỏ. F 679 là trường thứ 2 được tách ra và gán cho biến b. F Một khoảng trắng tiếp theo bị loại bỏ. F 58 là trường cuối cùng được tách ra và gán cho biến x. - Ví dụ 3.4: int a,b; float x; scanf(“%d %2d %3f”,&a,&b,&x); Giả sử lúc thực hiện chương trình, dữ liệu nhập trên dòng vào là: ∪140∪638∪8∪58↵ (∪ thể hiện cho dấu cách) Lúc đó, việc đọc giá trị vào cho các biến được thực hiện như sau: F Khoảng trắng đầu tiên bị loại bỏ. F 140 là trường thứ nhất được tách ra và gán cho biến a. F Một khoảng trắng tiếp theo bị loại bỏ. F 63 là trường thứ 2 được tách ra và gán cho biến b. F Một khoảng trắng tiếp theo bị loại bỏ. F 8 là trường thứ 3 được tách ra và gán cho biến x. F Một khoảng trắng tiếp theo bị loại bỏ. F dòng vào còn chứa ∪58. - Lưu ý: Chỉ dùng hàm scanf với đặc tả %s để nhập liệu cho các biến chứa dữ liệu chuỗi là các ký tự liền nhau (không có khoảng trắng). Nếu muốn nhập chuỗi chứa cả khoảng trắng bằng hàm scanf thì bạn dùng đặc tả %[\n] thay thế cho mã định dạng %s. Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  33. Bài giảng Cơ sở lập trình -31- - Ví dụ 3.5: Giải #include main() { int chuoi[20]; clrscr(); printf(“Nhap chuoi ky tu “); scanf(“%[\n]”,chuoi); printf(“%s”,chuoi); getch(); } 3.1.2 Nhập dữ liệu với hàm getchar() và getch() - Hàm getchar() + Cú pháp: int getchar(); + Chức năng: Hàm không có đối số, thực hiện đọc một ký tự từ bàn phím vào cho biến có kiểu ký tự và kết thúc nhập bằng phím enter. + Ví dụ 3.7: Giải #include main() { char c; clrscr(); printf(“Nhap ky tu “); c = getchar(); printf(“Ky tu vua nhap %c”,c); getch(); } - Hàm getch() và getche(): + Cú pháp: int getch(); int getche(); + Chức năng: Hai hàm này đọc thẳng ký tự từ bàn phím, không qua bộ nhớ đệm bàn phím, nghĩa là đọc một ký tự từ bàn phím không chờ bấm phím enter để kết thúc. Hàm trả về số nguyên là mã ASCII của ký tự vừa được nhập. Trong đó: Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  34. Bài giảng Cơ sở lập trình -32- hàm getche() hiện ký tự lên màn hình, còn hàm getch() không hiện ký tự nhập vào lên màn hình. Trường hợp ký tự nhập vào thuộc phần mã mở rộng thì hệ thống sẽ đẩy vào bộ đệm nhập liệu 2 byte: byte thứ nhất có giá trị không, byte thứ 2 là mã mở rộng của ký tự đó. + Ví dụ 3.8: Giải #include main() { char c; clrscr(); printf(“Nhap ky tu “); c = getch(); printf(“ma ASCII cua ky tu vua nhap %d”,c); getch(); } + Lưu ý: Người ta thường ứng dụng hàm getch() để viết đoạn chương trình gõ password hay đặt lệnh ở cuối chương trình chờ người dùng xem kết quả. 3.2 Câu lệnh xuất dữ liệu 3.2.1 Xuất dữ liệu bằng hàm printf - Chức năng: Hàm printf (nằm trong thư viện stdio.h) dùng để xuất các giá trị của các biểu thức lên màn hình. - Cú pháp: printf(“Chuỗi định dạng”[, “Danh sách các biểu thức”]); Trong đó: + Chuỗi định dạng: Dùng để qui định kiểu dữ liệu, cách biểu diễn, độ rộng, số chữ số thập phân Có 3 loại chuỗi định dạng: F Ký tự điều khiển: Là các ký tự đặc biệt, bắt đầu bằng dấu \ sau đó là ký tự dùng để điều khiển, chẳng hạn chuỗi định dạng của một số ký tự điều khiển \n chuyển con trỏ màn hình xuống đầu dòng mới \t chuyển con trỏ đi một tab \b xóa lùi một ký tự (xóa ký tự đứng trước con trỏ hiện tại) F Các ký tự thường: Là những ký tự không thuộc loại điều khiển, các ký tự này được in ra đúng như nó xuất hiện trong chuỗi định dạng. Ngoài ra, có một số ký tự đặc biệt bạn muốn in ra màn hình thì phải đặt ký tự đó sau dấu \ Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  35. Bài giảng Cơ sở lập trình -33- \\ để in ra màn hình dấu \ \’ để in ra màn hình dấu ’ \” để in ra màn hình dấu ” F Các ký tự đặc tả: Ký tự đặc tả có dạng %[-][n.[m]] Trong đó: [n.[m]] quy định độ rộng của kiểu dữ liệu, với m là chữ số thập phân (dùng cho số thực). Nếu độ rộng của dữ liệu cần in nhỏ hơn độ rộng dành cho nó (n) thì các dấu trống được thêm vào bên phải hoặc bên trái tùy theo sự có mặt của thành phần [-] hay không. Nếu thay n bằng dấu *, khi đó dữ liệu được in ra theo đúng độ rộng thực sự của nó. Ví dụ 3.9: int x; x = 65; printf(“Ma ASCII cua ky tu %c là %d\n”,x,x); Ký tự Ký tự Ký tự thường đặc tả điều khiển Ví dụ 3.10: Giải #include main() { int a; a = 25; printf(“Gia tri cua a = %*d ”,a); }  Kết quả in ra a = ^^^^^^^^^^^^^^25 Bảng các ký tự dùng trong chuỗi định dạng Dãy mã qui cách Ý nghĩa %c In ra ký tự kiểu char, có thể dùng cho kiểu short và int %d In ra số nguyên int, có thể dùng cho kiểu char %u In ra kiểu số nguyên không dấu unsigned int, có thể dùng cho unsigned char, unsigned short. %ld Long Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  36. Bài giảng Cơ sở lập trình -34- %lu unsigned long %x, %X In ra kiểu số nguyên viết dưới dạng số Hecxa %o In ra kiểu số nguyên viết dưới dạng số octal (hệ đếm 8) %f In ra kiểu số thực viết dưới dạng bình thường với phần thập phân có 6 chữ số, dùng cho kiểu float, double %e, %E In ra kiểu số thực dưới dạng số mũ, tức dạng khoa học x.xxxxxxEyyy với phần định trị có 6 chữ số thập phân, dùng cho kiểu float, double.Dấu e hay E sẽ cho kết quả số in ra đi với chữ e hay E tương ứng. %g, %G In ra hoặc theo kiểu %f hoặc theo kiểu %e tùy cái nào ngắn hơn %s In ra xâu ký tự. + Danh sách các biểu thức: là phần tùy chọn, nếu có thì đó là các biểu thức mà chúng ta cần xuất giá trị của nó lên màn hình, mỗi biểu thức phân cách nhau bởi dấu phẩy. Lưu ý: Danh sách các biểu thức có thể nhiều hơn số các đặc tả trong chuỗi định dạng, khi đó các biểu thức cuối (không có đặc tả tương ứng) sẽ bị bỏ qua. Ví dụ 3.11: x = 3.57; printf(“%6.1f”,x);  Kết quả in ra 5 . 7 printf(“%-6.1f”,x);  Kết quả in ra 5 . 7 3.2.2 Xuất dữ liệu bằng hàm putch - Cú pháp: int putch(int ch); - Chức năng: Hàm in ra ký tự có mã ASCII là ch lên màn hình tại vị trí hiện thời của con trỏ, chuyển con trỏ sang phải một ký tự. Hàm trả về số nguyên chính là mã ký tự in ra. - Ví dụ 3.12: Giải #include main() { a = 97; Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  37. Bài giảng Cơ sở lập trình -35- printf(“a = %d\n”,a); printf(“a = \n”); putch(a); a = 400; printf(“a = %d\n”,a); printf(“a = \n”); putch(a); getch(); } - Lưu ý: + Một ký tự khi lưu trữ chỉ có kích thước 1 byte, nhưng hàm putch lại có đối số int chiếm 2 byte bộ nhớ. Vì vậy, trong trường hợp ch có giá trị lớn hơn 255 thì ký tự in ra sẽ có mã là ch%255. + Tương tự hàm printf, một số ký tự đặc biệt được coi là ký tự điều khiển chứ không phải là ký tự in ra màn hình. 3.2.3 Các lệnh trình bày màn hình - Để xuất các ký tự ra màn hình theo đúng vị trí và màu sắc mong muốn, bạn phải sử dụng các lệnh trình bày màn hình. C cung cấp cho bạn các lệnh làm công việc này (nằm trong tập tin conio.h). Màn hình trong chế độ văn bản có 25 dòng, 80 cột, tọa độ điểm đầu tiên (dòng 1, cột 1) ở góc trên bên trái màn hình, tọa độ điểm cuối cùng (dòng 25, cột 80) ở góc dưới bên phải của màn hình. - Các hàm trình bày lệnh xuất dữ liệu trên màn hình: F gotoxy(int y, int x) : Đặt con trỏ tại điểm có hoành độ x, tung độ y. F clrscr() : Lau sạch màn hình, đưa con trỏ về vị trí góc trên, bên trái màn hình. F clreol(): Xóa các ký tự nằm bên phải con trỏ. F void textcolor(int color): Đặt màu chữ văn bản. + color: màu của ký tự, nhận giá trị từ 0 đến 15. + Bạn có thể tạo cho dòng chữ nhấp nháy bằng cách cộng thêm tham số BLINK. + Dùng lệnh cprintf thay cho lệnh printf để xuất ra văn bản có màu chữ. F void textbackground(int color): Đặt màu nền văn bản. + color: màu của nền văn bản, color là biểu thức nguyên nhận giá trị từ 0 đến 7, tương ứng với 1 trong 8 hằng số màu đầu tiên của bảng các hằng số màu. Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  38. Bài giảng Cơ sở lập trình -36- Bảng các hằng số màu Hằng Màu thể hiện Giá trị BLACK Đen 0 BLUE Xanh lơ 1 GREEN Xanh lá cây 2 CYAN Xanh cẩm thạch 3 RED Đỏ 4 MAGENTA Tía 5 BROWN Nâu 6 LIGHTGRAY Xám nhạt 7 DARKGRAY Xám đậm 8 LIGHTBLUE Xanh nhạt 9 LIGHTGREEN Xanh lá cây 10 LIGHTCYAN Xanh cẩm thạch nhạt 11 LIGHTRED Đỏ nhạt 12 LIGHTMAGENTA Tía nhạt 13 YELLOW Vàng 14 WHITE Trắng 15 BLINK Nhấp nháy 128 - Ví dụ 3.14: Viết chương trình xuất dòng chữ “Truong Dai hoc Pham Van Dong” có màu vàng, tại dòng 20 cột 12 của màn hình trong chế độ văn bản. Giải #include #include main() { textcolor(YELLOW); gotoxy(20,12); cprintf(“Truong Dai hoc Pham Van Dong”); getch(); } 3.3 Bài tập thực hành 1. Xem đoạn chương trình C sau có đúng không ? Giải thích ? #include Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  39. Bài giảng Cơ sở lập trình -37- int a; main() { a = a*a; printf(“Gia tri cua a la %d\n”,a); } 2. Cho biết kết quả của chương trình sau: #include main() { int chu; chu = ‘d’; printf(“Ma ASCII cua %c la %d “,chu,chu); } 3. Cho biết kết quả in ra màn hình của chương trình sau: #include main() { int a = 11, b = 2; float tbc; tbc = (float) a/b; printf(“Trung bình cong = %f”,tbc); getch(); } 4. Cho biết kết quả in ra màn hình của chương trình sau: #include main() { int a, b; float tbc; printf(“Kich thuoc cua bien a = %d”,sizeof(a)); printf(“Kich thuoc cua bien tbc = %d”,sizeof(tbc)); getch(); } 5. Cho biết kết quả in ra màn hình của chương trình sau: #include main() { int a,kq; a = 5; kq = ((a > 2); printf(“Ket qua = %d”,kq ); Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  40. Bài giảng Cơ sở lập trình -38- getch(); } 6. Cho biết kết quả in ra màn hình của chương trình sau: #include main() { int a=5,kq; kq = ((a > 2); printf(“Ket qua = %d”,kq ); getch(); } 7. Đoạn mã trong chương trình sau là đúng hay sai ? Giải thích vì sao ? #include main() { float a = 15.0, b = 2.0; printf(“Ket qua = %d”,a%b); getch(); } 8. Viết chương trình nhập diện tích s của một mặt cầu. Tính và in ra màn hình thể tích V của hình cầu này. Biết rằng: S = 4.π .R 2   4 π = 3.141593 V = π R 3  3 9. Viết chương trình nhập vào tọa độ 2 điểm A(Xa,Ya) và B(Xb,Yb). Tính và in ra màn hình khoảng cách AB. Biết rằng: AB = (Xb − Xa) 2 + (Yb−Ya) 2 10. Viết chương trình tính và in ra màn hình chu vi và diện tích của hình tròn với bán kính R được nhập từ bàn phím. Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  41. Bài giảng Cơ sở lập trình -39- CHƯƠNG 4: CẤU TRÚC ĐIỀU KHIỂN Mục tiêu Kết thúc chương, sinh viên có thể:  Nắm được các cấu trúc điều khiển thường dùng trong ngôn ngữ lập trình C, từ đó vận dụng để tiếp thu kiến thức được học tập trong các ngôn ngữ lập trình, ở các học kỳ tiếp theo.  Rèn luyện kỹ năng lập trình thông qua các bài tập thực hành. 4.1 Câu lệnh điều kiện 4.1.1 Câu lệnh if - Cú pháp: + Dạng 1: if ( ) Lệnh1; else Lệnh2; + Dạng 2: if ( ) Lệnh; - Chức năng: Nếu có giá trị khác 0 (tức có giá trị đúng) thì thực hiện Lệnh1, ngược lại nếu có giá trị bằng 0 (tức có giá trị sai) thì thực hiện Lệnh2. Đối với dạng 2, nếu có giá trị sai thì câu lệnh if không làm gì cả. - Sơ đồ khối: F F T T Lệnh1 Lệnh2 Lệnh1 Dạng 1 Dạng 2 - Lưu ý: + : Biểu thức điều kiện, kết quả tính toán phải cho ra giá trị 0 hoặc khác 0. + Lệnh1, Lệnh2 là câu lệnh đơn và kết thúc bằng dấu chấm phẩy. Nếu sau hoặc sau else là câu lệnh phức, lúc đó các câu lệnh của câu lệnh phức phải được đặt trong cặp dấu { và } - Ví dụ 4.1: Viết chương trình nhập vào 2 số nguyên từ bàn phím, in ra màn hình số lớn trong 2 số vừa nhập. Giải: Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  42. Bài giảng Cơ sở lập trình -40- #include main() { int a,b; printf(“Nhap so nguyen thu nhat ”);scanf(“%d”,&a); printf(“Nhap so nguyen thu hai ”);scanf(“%d”,&b); if (a>b) printf(“So lon trong 2 so la %d”,a); else printf(“So lon trong 2 so la %d”,b); getch(); } - Ví dụ 4.2: Viết chương trình nhập vào 3 số thực từ bàn phím là số đo 3 đoạn thẳng. Yêu cầu: Kiểm tra xem số đo 3 đoạn thẳng vừa nhập có thỏa mãn là độ dài 3 cạnh của một tam giác không? Nếu thỏa mãn tạo thành tam giác thì tính và in ra màn hình chu vi và diện tích của tam giác. Nếu không thỏa mãn thì thông báo “Khng ton tai tam giac”. Giải: #include #include #include main() { float a,b,c,p,q,s; printf(“Nhap so do 3 doan thang ”); printf(“\n So do doan thang thu nhat: ”);scanf(“%f”,&a); printf(“\n So do doan thang thu hai: ”);scanf(“%f”,&b); printf(“\n So do doan thang thu ba: ”);scanf(“%f”,&c); if ((a+b>c) && (b+c>a) && (a+c>b)) { p = (a+b+c)/2; S = sqrt(p*(p-a)*(p-b)*(p-c)); printf(“\n Chu vi: %5.2f, dien tich: %5.2f”,p*2,s); } else printf(“\n Khong ton tai tam giac”); getch(); } Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  43. Bài giảng Cơ sở lập trình -41- - Cấu trúc if lồng nhau: if (a : Lệnh1; case : Lệnh2; case : Lệnhk; case : Lệnhn; [default: Lệnh0;] } Trong đó: + biểu_thức phải cho ra kết quả là số nguyên hoặc ký tự. + bt1, bt2, , btn là các biểu thức hằng, nguyên hoặc ký tự và chúng phải khác nhau. + Lệnh1, Lệnh2, , Lệnhn, Lệnh0 là các lệnh trong thân của switch. - Chức năng: Trước tiên biểu_thức được tính, sau đó so sánh giá trị của biểu thức với các bt1, bt2, , btn; Nếu giá trị của btk nào đó trong các bt1, bt2, , btn bằng với giá trị của biểu_thức thì chương trình bắt đầu thực hiện các lệnh từ Lệnhk và tiếp tục các lệnh phía dưới cho đến khi gặp câu lệnh break hoặc dấu móc } kết thúc switch. Nếu giá trị của biểu_thức không trùng với giá trị nào trong danh sách bt1, bt2, , btn thì Lệnh0 được thực hiện nếu có thành phần default. - Sơ đồ khối: Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  44. Bài giảng Cơ sở lập trình -42- T Lệnh1 T Lệnh1 = bt1 = bt1 F F T T = bt2 Lệnh2 Lệnh2 = bt2 F F F F T Lệnhn = btn T Lệnhn = btn F F Lệnh0 Dạng 1 Dạng 2 - Ví dụ 4.3: Viết chương trình nhập số nguyên dương trong phạm vi từ 0 đến 10 và dịch sang từ tiếng anh tương ứng với số vừa nhập. Nếu người sử dụng nhập ngoài phạm vi trên thì thông báo “So nhap vao nam ngoai pham vi dich cua chuong trinh”. Giải: #include main() { int n; printf(“ Hay nhap mot so nguyen “); scanf(“%d”, &n); switch (n) { case 0 : printf(“ Zero\n“); break; case 1 : printf(“ One\n“); break; case 2 : printf(“ Two\n“); break; Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  45. Bài giảng Cơ sở lập trình -43- case 3 : printf(“ Three\n“); break; case 4 : printf(“ Four\n“); break; case 5 : printf(“ Five\n“); break; case 6 : printf(“ Six\n“); break; case 7 : printf(“ Seven\n“); break; case 8 : printf(“ Eight\n“); break; case 9 : printf(“ Nine\n“); break; case 10 : printf(“ Ten\n“); break; default: printf(“So nhap vao nam ngoai pham vi dich cua chuong trinh”); } } - Lưu ý: + Lệnh break là để nhảy ra khỏi lệnh switch, nếu không có lệnh này cấu trúc switch sẽ duyệt cả các trường hợp phía dưới cho đến khi gặp dấu đóng switch (vì chưa gặp break xem như chưa ra khỏi lệnh switch). + Khi sử dụng lệnh switch có thể xảy ra nhiều giá trị trả về cho một trường hợp (một khả năng xảy ra của biểu thức). - Ví dụ 4.4: Viết chương trình nhập vào một số nguyên, nếu: ● Số nhập vào là 0 thì thông báo : Zero. ● Số nhập vào là 1,2 thì thông báo : Số nhỏ. ● Số nhập vào là 3,4,5 thông báo : Số trung bình. ● Số nhập vào lớn hơn 5 thông báo : Số lớn. Giải: #include main() Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  46. Bài giảng Cơ sở lập trình -44- { int n; printf(“ Hay nhap mot so nguyen “); scanf(“%d”, &n); switch (n) { case 0 : printf(“ Zero\n“); break; case 1 : case 2 : printf(“ Số nhỏ\n“); break; case 3 : case 4 : case 5 : printf(“ Số trung bình\n“); break; default: printf(“ Số lớn.\n”); } printf(“ Tạm biệt !\n”); } - Ví dụ 4.5: Viết chương trình nhập vào một ký tự thường, chương trình thông báo ký tự vừa nhập là nguyên âm hay không phải nguyên âm. Giải: #include main() { char ch; printf(“Nhap vao mot ky tu “);scanf(“%c”,&ch); switch (ch) { case ‘a’ : case ‘o’ : case ‘e’ : case ‘u’ : case ‘y’ : Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  47. Bài giảng Cơ sở lập trình -45- case ‘i’ : printf(“Đây là nguyên âm\n”); break; default : printf(“ Không phải là nguyên âm.\n”); } 4.2 Câu lệnh lặp 4.2.1 Câu lệnh while Câu lệnh while là cấu trúc điều khiển lặp để thực hiện một lệnh hay một khối các lệnh với số lần lặp chưa được xác định trước. Với cấu trúc này điều kiện lặp được kiểm tra trước khi thực hiện thân của vòng lặp. - Cú pháp: while ( ) Lệnh; Trong đó: + biểu_thức: Biểu thức để xác định điều kiện lặp. + Lệnh: Là thân của vòng while. - Chức năng: Đầu tiên vòng while tính giá trị của biểu thức: Nếu giá trị của biểu thức là 0 (tức False) thì vòng while kết thúc. Nếu giá trị của biểu thức khác 0 (tức True) thì thực hiện lệnh trong thân của vòng lặp, sau đó quây lại kiểm tra giá trị của biểu_thức để tiếp tục thực hiện hoặc kết thúc vòng while. - Lưu ý: + Nếu thân của vòng lặp là một khối các lệnh thì các lệnh được gói trong cặp dấu { và } + Cấu trúc while kiểm tra điều kiện trước, do vậy nếu biểu_thức điều kiện có giá trị False ngay từ đầu thì thân vòng while không được thực hiện lần nào. + Trong thân vòng while phải có lệnh làm thay đổi giá trị của biểu_thức điều kiện để đảm bảo sau một số lần hữu hạn thực hiện thì giá trị của biểu_thức điều kiện sẽ có giá trị False. Trường hợp, biểu_thức luôn luôn có giá trị True (không có lệnh làm thay đổi giá trị biểu thức) thì thân vòng while phải có lệnh break để chấm dứt vòng lặp. - Sơ đồ khối: F biểu_thức T Lệnh Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  48. Bài giảng Cơ sở lập trình -46- - Ví dụ 4.6: Viết chương trình nhập vào các số nguyên và tính tổng các số nguyên đã nhập cho đến chừng nào tổng còn nhỏ hơn 100. Giải: #include main() { int n, tong = 0; while (tong main() { int a,b,x,y; printf(“Nhap 2 so nguyen duong “); scanf(“%d %d”,&a,&b); while ((a y) x -= y; else y -= x; printf(“Uoc so chung lon nhat cua %d va %d la %d”,a,b,x); getch(); } - Ví dụ 4.8: Viết chương trình nhập vào số nguyên dương n (0 < n <= 10), tính và in ra màn hình n! Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  49. Bài giảng Cơ sở lập trình -47- Biết rằng: 0! = 1. n! = 1*2*3* *(n-1)*n. Giải: #include const int max = 10; main() { int n,i; long giaithua; clrscr(); printf("\n Nhap n = ");scanf("%d",&n); i = 1; while ((n max)) { printf("\n Nhap lai (0 ); Trong đó: + biểu_thức: Biểu thức để xác định điều kiện lặp. + Lệnh: Là thân của cấu trúc do while. Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  50. Bài giảng Cơ sở lập trình -48- - Chức năng: Đầu tiên cấu trúc lặp do while thực hiện lệnh trong thân vòng lặp, sau đó kiểm tra giá trị của biểu_thức: Nếu giá trị của biểu thức là khác 0 (tức True) thì tiếp tục thực hiện các lệnh trong thân vòng lặp. Nếu giá trị của biểu thức bằng 0 (tức False) thì kết thúc vòng lặp. - Lưu ý: Cấu trúc while kiểm tra điều kiện sau, do vậy thân của vòng lặp ít nhất được thực hiện một lần, sau đó tùy theo giá trị của biểu thức, chương trình sẽ tiếp tục thực hiện một số lần lặp tiếp theo hoặc thoát ra khỏi trạng thái lặp. - Sơ đồ khối: Lệnh T biểu_thức F - Ví dụ 4.9: Viết chương trình cho phép người dùng nhập một ký tự từ bàn phím, sau đó chương trình in ra ký tự đó và mã ASCII của nó ra màn hình. Chương trình tiếp tục lặp lại các công việc trên cho đến chừng nào phím bấm vào là ESC thì kết thúc. Giải: #include const int ESC = 27; main() { int ch; clrscr(); do { printf("\n Nhap mot ky tu "); ch = getch(); printf("\n Ky tu %c co ma ASCII la %d",ch,ch); } while (ch != ESC); getch(); } - Ví dụ 4.10: Viết chương trình nhập vào số nguyên dương n từ bàn phím. Tìm và in ra màn hình số nguyên m lớn nhất sao cho: s = 1 + 2 + 3 + + m < n. Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  51. Bài giảng Cơ sở lập trình -49- Yêu cầu kỹ thuật: Chương trình phải kiểm tra và yêu cầu người dùng nhập vào n >= 0. Giải: #include main() { int m,n,s; do { printf("Nhap n = "); scanf("%d",&n); } while (n = 0")); s = m = 0; while ((s + m) 0) printf(" = %d ; Trong đó: + [biểuthức1]: Biểu thức tính ra giá trị khởi đầu cho biến của for. + [biểuthức2]: Biểu thức tính ra giá trị điều kiện lặp của for. + [biểuthức3]:Bước nhảy của biến sau mỗi lần lặp. + : Là lệnh thực hiện trong thân của vòng lặp for. Nếu trong thân của vòng lặp không phải lệnh đơn mà là khối các lệnh thì các lệnh đó phải được đặt trong cặp dấu { và } Lưu ý: Các biểu thức có thể vắng mặt trong cấu trúc của for nhưng các dấu chấm phẩy vẫn phải có. Mỗi biểu thức trong cấu trúc for có thể là một hoặc nhiều biểu thức đơn. Nếu trong biểu thức có nhiều biểu thức đơn thì các biểu thức đơn được viết cách nhau bởi dấu phẩy. Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  52. Bài giảng Cơ sở lập trình -50- - Chức năng: + Đầu tiên biểuthức1 được thực hiện. Sau đó tiếp tục tính giá trị của biểuthức2 để xác định điều kiện lặp có được thỏa mãn hay không, nếu điều kiện lặp không thỏa mãn thì kết thúc lặp, nếu điều kiện lặp thỏa mãn thì thực hiện các câu lệnh trong thân vòng lặp. + Sau mỗi lần lặp, chuyển sang tính giá trị của biểuthức3 (biến của vòng lặp for tăng đối với dạng 1, biến của vòng lặp for giảm đối với dạng 2). Sau đó, quây về tính giá trị của biểuthức2 để kiểm tra điều kiện lặp, từ đó mà tiếp tục thực hiện thân vòng lặp hay chấm dứt vòng lặp. - Sơ đồ khối: BT=biểuthức1 BT=biểuthức1 BT = F biểuthức2 biểuthức2 T T Lệnh Lệnh biểuthức3 biểuthức3 Dạng 1 Dạng 2 - Ví dụ 4.11: Viết chương trình nhập vào dãy n số nguyên từ bàn phím. Tính và in ra màn hình trung bình cộng của số n số nguyên đã nhập. Giải: #include main() { int n,x,dem,tong=0; float tbc; printf(“Cho biet so luong so nhap vao n = ”);scanf(“%d”,&n); for (dem = 1; dem <=n;++dem) { printf(“Nhap so thu %d”,dem); scanf(“%d”,&x); Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  53. Bài giảng Cơ sở lập trình -51- tong += x; } tbc = (float) tong/n; printf(“\n Trung binh cong = %5.2f ”,tbc); getch(); } - Ví dụ 4.12: Viết chương trình in ra 20 số nguyên dương đầu tiên ra màn hình. Giải: #include main() { int i; for (i=1; i main() { int dem = 0; clrscr(); for (;dem<=5;) { printf(“\n %d”,dem); Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  54. Bài giảng Cơ sở lập trình -52- dem += 1; if (dem==3) break; } getch(); } Trường hợp có nhiều biểu thức đơn cách nhau bởi dấu phẩy thì các biểu thức đơn đó được thực hiện từ trái qua phải. Riêng trường hợp biểuthức2 có nhiều biểu thức đơn thì biểu thức bên phải nhất quyết định vòng lặp có được tiếp tục hay không. - Ví dụ 4.14: Giải #include main() { int i,j; clrscr(); for (i=0, j=i+3; i<1, j<8; i++, j++) printf(“\n i = %d, j = %d); getch(); } Kết quả thực hiện đoạn chương trình trên: i = 0, j = 3; i = 1, j = 4; i = 2, j = 5; i = 3, j = 6; i = 4, j = 7; Trong chương trình trên vòng lặp for dừng theo điều kiện j <8. Trường hợp trong cấu trúc của lệnh for vắng mặt cả 3 biểu thức, lúc đó thân của vòng lặp được thực hiện liên tục. Lúc đó, trong thân của vòng for phải có lệnh để thoát ra ngoài vòng for. - Ví dụ 4.16: Viết chương trình hiện lên màn hình bảng chọn có 3 chức năng: 1. Nhap 2. Xem 3. Thoat Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  55. Bài giảng Cơ sở lập trình -53- Yêu cầu kỹ thuật: Sử dụng câu lệnh for để tạo bảng chọn. Người dùng bấm 1 thì hiện ra màn hình “Nhap”, bấm 2 thì hiện ra màn hình “Xem”, bấm 3 thì thoát. Giải #include #include main() { int so; for (;;) { printf(“\n 1. Nhap”); printf(“\n 2. Xem”); printf(“\n 3. Thoat”); do { printf(“\n Bam so de chon (1/2/3)“); scanf(“%d”,&so); } while (so 3); switch (so) { case 1: printf(“Ban chon chuc nang nhap”); break; case 2: printf(“Ban chon chuc nang xem”); break; case 3: exit(0); } } } Rõ ràng trong chương trình trên thân của vòng for liên tục được thực hiện, chỉ khi nào tại dòng “Bam so de chon” bạn bấm số 3 thì câu lệnh switch trong thân vòng for mới điều khiển thoát khỏi vòng for bằng lệnh exit. 4.3 Các câu lệnh rẽ nhánh vô điều kiện 4.3.1 Câu lệnh break - Như trong phần 4.1.2 đã trình bày, người ta dùng lệnh break để kết thúc câu lệnh rẽ nhánh switch. C cũng cho phép sử dụng câu lệnh break trong thân của các câu lệnh lặp (for, while, do while). Khi gặp câu lệnh break trong thân các câu lệnh lặp, thì câu lệnh lặp trong cùng chứa nó sẽ kết thúc, chuyển sang câu lệnh tiếp theo ngoài câu lệnh lặp vừa kết thúc. Như vậy, câu lệnh break cho phép kết thúc Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  56. Bài giảng Cơ sở lập trình -54- vòng lặp từ vị trí bên trong của vòng lặp mà không cần xét đến giá trị của biểu thức điều kiện. Tất nhiên phải có điều kiện nào đó để gọi đến câu lệnh break. - Ví dụ 4.17: Đoạn chương trình sau xuất ra màn hình chữ “Chào bạn” ba lần, mặc dù trong chương trình dùng vòng lặp for với số lần lặp là 10, nhưng sau khi lặp đủ 3 lần thì thoát khỏi chương trình. Giải: #include main() { int i; for (i=1; i main() { int i; for (i=1; i <= 5; i++) { printf(“ Lan lap %d\n”, i); if (i < 4) continue; Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  57. Bài giảng Cơ sở lập trình -55- printf(“ Chao ban\n”); } getch(); } F Kết quả khi chạy chương trình: Lan lap 1 Lan lap 2 Lan lap 3 Lan lap 4 Chao ban Lan lap 5 Chao ban 4.3.3 Câu lệnh goto - Câu lệnh nhảy goto sẽ chuyển điều khiển chương trình tới một nơi nào đó có gán một nhãn (label) để đánh dấu. - Ví dụ 4.18: Đoạn chương trình sau cho phép nhập vào số nguyên dương n, kiểm tra n có phải là số nguyên tố hay không, thông báo lên màn hình. Sau đó, người dùng nhập số 0 để dừng, số 1 để tiếp tục kiểm tra số nguyên dương khác. Giải: #include #include main() { int n,i,tl,dem=0; tiep: do { printf(“Nhap n = “); scanf(“%d ”,&n); } while (n 0”)); for (i=1; i 0) printf(“%d la hop so”,n);, else printf(“%d la so nguyen to “,n); Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  58. Bài giảng Cơ sở lập trình -56- printf(“Ban co tiep tuc kiem tra ? (Bam 0 de dung - 1 de tiep tuc)”); scanf(“%d”,&tl); if (tl==1) goto tiep; else goto dung; dung: printf(”Ket thuc kiem tra”); getch(); } 4.4 Câu hỏi và bài tập thực hành 1. Cấu trúc if và cấu trúc switch được sử dụng trong những trường hợp nào? 2. Trình bày sự giống và khác nhau giữa 2 cấu trúc lặp while và do while ? 3. Viết chương trình nhập vào: tọa độ điểm O(XO, YO) là tâm của một đường tròn, tọa độ điểm M(XM, YM) và bán kính R của đường tròn. Xác định và thông báo lên màn hình điểm M nằm trong, trên hay ngoài đường tròn đó. 4. Viết chương trình thực hiện các công việc: Nhập điểm trung bình của một học sinh từ bàn phím, sau đó chương trình thông báo lên màn hình xếp loại của học sinh đó, biết rằng: + Điểm trung bình từ 0 đến dưới 4, xếp loại kém. + Điểm trung bình từ 4 đến dưới 5, xếp loại yếu. + Điểm trung bình từ 5 đến dưới 7, xếp loại trung bình. + Điểm trung bình từ 7 đến dưới 8, xếp loại khá. + Điểm trung bình từ 8 đến dưới 9, xếp loại giỏi. + Điểm trung bình từ 9 đến 10, xếp loại xuất sắc. Sau mỗi lần thực hiện, chương trình yêu cầu bấm số 1 để tiếp tục nhập, bấm số 0 để dừng nhập. 5. Viết chương trình nhập 4 số a, b, c, d từ bàn phím, in ra màn hình số lớn nhất trong 4 số vừa nhập. 6. Viết chương trình nhập vào 3 số nguyên. Hãy in các số vừa nhập ra màn hình theo thứ tự tăng dần. Yêu cầu: Chương trình chỉ dùng tối đa một biến phụ. 7. Viết chương trình giải các phương trình sau với a, b, c là các số thực nhập từ bàn phím. a) Phương trình bậc nhất: ax + b = 0. b) Phương trình bậc hai: ax2 + bx + c = 0. 8. Viết chương trình giải hệ phương trình tuyến tính 2 ẩn số: Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  59. Bài giảng Cơ sở lập trình -57- ax + by = m  cx + dy = n a, b, c, d là các hệ số tự do được nhập từ bàn phím. 9. Viết chương trình nhập vào 3 số thực là số đo của 3 đoạn thẳng a, b, c. Chương trình kiểm tra và cho biết 3 đoạn thẳng đó có thể tạo thành tam giác hay không ? - Nếu 3 đoạn thẳng đó tạo thành tam giác thì tính diện tích của tam giác, biết rằng: Khi biết số đo 3 cạnh a, b, c thì diện tích tam giác được tính theo công thức: (a + b + c) S = p (* p − a (*) p − b (*) p − c) trong đó p = 2 Chương trình tiếp tục kiểm tra và thông báo cho biết tam giác đó là tam giác gì (tam giác đều, tam giác cân, tam giác vuông, tam giác thường). - Nếu 3 đoạn thẳng đó không thể tạo thành tam giác thì thông báo: “Khong ton tai tam giac”. 10. Viết chương trình nhập vào tọa độ các đỉnh của tam giác ABC và tọa độ điểm M. Xác định điểm M nằm trong, trên các cạnh hay nằm ngoài tam giác ABC. Biết rằng diện tích tam giác tính theo tọa độ 3 đỉnh của nó bằng công thức: X Y 1 A A Y 1 X 1 X Y = 1 = 1 B − B + B B S ABC X B YB 1 X A YB 2 2 YC 1 X C 1 X C YC X C YC 1 1 = X (Y − Y ) − Y (X − X ) + (X Y − X Y ) 2 A B C A B C BC CB 11. Viết chương trình thực hiện các công việc: nhập vào số nguyên dương n, tính và in ra màn hình tổng S = 12 + 22 + + n2 12. Viết chương trình in ra màn hình tất cả các phương án để có được 10000 đồng từ các tờ giấy bạc 500 đồng, 200 đồng, 100 đồng. 13. Viết chương trình thực hiện các công việc: nhập vào số nguyên dương n, n 1 tính và in ra màn hình Fn. Biết rằng: Fn = ∑ 2 i=1 n + i 14. Viết chương trình liệt kê bảng mã ASCII ra màn hình theo yêu cầu: Liệt kê theo từng trang màn hình, khi bấm phím enter thì chương trình cho xem tiếp, khi bấm phím ESC thì kết thúc việc liệt kê bảng mã ASCII. 15. Viết chương trình tính sin(x) với độ chính xác 10-4, biết rằng hàm sin(x) được triển khai theo chuỗi Taylor như sau: x 3 x 5 x 2n+ 1 sin(x) = x − + + + (− 1) n !3 !5 2( n +1)! Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  60. Bài giảng Cơ sở lập trình -58- 16. Viết chương trình thực hiện các công việc: nhập từ bàn phím số nguyên dương n (1 ≤ n ≤ 16), in ra màn hình cây thông theo hình dạng sau: * chiều cao tán lá có n dòng * chiều cao thân cây có n/2 dòng * 17. Viết chương trình thực hiện các công việc: nhập vào số thực R (R> 0), tìm và in ra màn hình số nguyên dương n nhỏ nhất sao cho: 1 1 1 1 S = + + + + 1 2 3 n 18. Viết chương trình thực hiện các công việc: nhập vào số nguyên dương n 1 1 1 1 (n > 0), tính và in ra màn hình tổng S = + + + + !1 !2 !3 n! 19. Số tự nhiên có n chữ số là số Amstrong nếu tổng các lũy thừa bậc n của các chữ số có trong số đó bằng chính nó. Hãy tìm tất cả các số Amstrong có 3 hoặc 4 chữ số. Ví dụ: Số 153 là số Amstrong vì 153 = 13 + 53 + 33 20. Viết chương trình tính tổ hợp chập k của n (k < n < 25). Biết rằng: n! C k = và C 0 =C n = 1 n k (! n − k !) n n 21. Viết chương trình thực hiện các công việc: nhập vào số nguyên dương n, kiểm tra và thông báo lên màn hình n là số nguyên tố hay là hợp số. Biết rằng: Số nguyên tố là số chỉ chia chẳn cho 1 và chính nó. 22. Viết chương trình thực hiện các công việc: nhập vào số nguyên dương n, in ra màn hình các số nguyên tố nhỏ hơn hoặc bằng n. 23. Viết chương trình thực hiện các công việc: nhập vào số nguyên dương n, kiểm tra và thông báo lên màn hình n có phải là số chính phương hay không ? Biết rằng: Số chính phương là số bằng bình phương đúng của một số nguyên. 24. Viết chương trình thực hiện các công việc: nhập vào số nguyên dương n, kiểm tra và thông báo lên màn hình n có phải là số hoàn hảo hay không ? Biết rằng: Số hoàn hảo là số có tổng các ước số thực sự của nó bằng chính nó. 25. Viết chương trình thực hiện các công việc: nhập vào số nguyên dương biểu thị cho năm dương lịch, thông báo lên màn hình năm âm lịch tương ứng. Biết rằng: Năm âm lịch là do ghép CAN và CHI. Cách tính CAN, CHI như sau: Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  61. Bài giảng Cơ sở lập trình -59- - Lấy năm dương lịch chia cho 10 sẽ được số dư và CAN tương ứng là: Số dư CAN Số dư CAN 0 Canh 5 Ất 1 Tân 6 Bính 2 Nhâm 7 Đinh 3 Quý 8 Mậu 4 Giáp 9 Kỷ - Lấy năm dương lịch chia cho 10 sẽ được số dư và CAN tương ứng là: Số dư CHI Số dư CHI 0 Thân 6 Dần 1 Dậu 7 Mẹo 2 Tuất 8 Thìn 3 Hợi 9 Tỵ 4 Tý 10 Ngọ 5 Sửu 11 Mùi 26. Viết chương trình thực hiện các công việc: - Nhập vào một ký tự từ bàn phím. - In ra màn hình ký tự đó và ký tự thường tương ứng nếu ký tự nhập vào là ký tự hoa. - In ra màn hình ký tự đó và ký tự hoa tương ứng nếu ký tự nhập vào là ký tự thường. - In ra màn hình chính nó nếu ký tự nhập vào là ký số từ ‘0’ đến ‘9’. 27. Viết chương trình thực hiện các công việc: nhập vào 2 số nguyên dương từ bàn phím, tìm và in ra màn hình ước số chung lớn nhất của 2 số nguyên dương vừa nhập. 28. Viết chương trình nhập vào 2 số nguyên dương từ bàn phím, tìm và in ra màn hình bội số chung nhỏ nhất của 2 số nguyên dương vừa nhập. 29. Viết chương trình thực hiện các công việc: nhập vào số nguyên dương n, in ra màn hình số hạng Fibonacy thứ n. Biết rằng: Dãy số Fibonacy là dãy số có tính chất: U1 = 1, U2 = 1, Un = Un-1 + Un-2 (n>2) 30. Viết chương trình thực hiện các công việc: nhập vào số nguyên dương n, tính và in ra màn hình tổng S, nếu: - n chẳn: S = 2 + 4 + 6 + + n - n lẻ: S = 1 + 3 + 5 + + n Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  62. Bài giảng Cơ sở lập trình -60- CHƯƠNG 5: KIỂU DỮ LIỆU MẢNG - KIỂU DỮ LIỆU CON TRỎ Mục tiêu Kết thúc chương, sinh viên có thể:  Nắm vững khái niệm mảng một chiều, mảng hai chiều, cách truy xuất và các thao tác cơ bản trên mảng.  Hiểu được ý nghĩa của kiểu dữ liệu con trỏ và cách sử dụng.  Sử dụng mối quan hệ giữa mảng và con trỏ để giải quyết bài tập thực hành. 5.1 Kiểu dữ liệu mảng 5.1.1 Khái niệm mảng - Đối với các kiểu dữ liệu đơn giản là kiểu vô hướng như kiểu: số nguyên, số thực, ký tự, tại một thời điểm chỉ có thể biểu diễn được một giá trị. Để có thể lưu trữ được một dãy các giá trị cùng kiểu, chẳng hạn như các thành phần của một vector trong không gian n chiều Lúc đó, chúng ta cần khai báo n biến (a1, a2, ,an), như vậy sẽ rất cồng kềnh và bất tiện trong khai báo, nhất là khi n lớn và không cố định. Các ngôn ngữ lập trình nói chung, ngôn ngữ lập trình C nói riêng, đưa ra khái niệm mảng để giải quyết vấn đề này. - Mảng là kiểu dữ liệu có cấu trúc gồm một hợp cố định các phần tử có cùng kiểu dữ liệu, các phần tử của mảng cùng tên và phân biệt nhau bởi chỉ số. Mỗi phần tử của mảng được sử dụng như một biến đơn, kiểu của mảng chính là kiểu của phần tử. Như vậy, với một mảng ta cần quan tâm: + Các thông tin liên quan đến mảng: tên mảng, số phần tử của mảng, kiểu phần tử của mảng. Trong ngôn ngữ lập trình C, mảng cũng giống như biến đơn, nó phải được khai báo để được cấp phát bộ nhớ trước khi sử dụng. + Số chiều của mảng: Nếu mảng chỉ có một chỉ số để lưu trữ các giá trị vào trong các biến thành phần của mảng được gọi là mảng một chiều. Nếu mảng có 2 chỉ số để lưu trữ các giá trị (chẳng hạn các giá trị của một bảng có m dòng, n cột) được gọi là mảng 2 chiều. Tương tự, ta có mảng 3 chiều, 4 chiều, , n chiều. 5.1.2 Mảng một chiều 5.1.2.1 Định nghĩa mảng 1 chiều - Cú pháp: Tên_mảng[Số_phần_tử_của_mảng]; Trong đó: + Kiểu_mảng: Tên một kiểu dữ liệu của mảng đã tồn tại, có thể là kiểu dữ liệu chuẩn hoặc kiểu dữ liệu do người lập trình tự định nghĩa. + Tên_mảng: Tên của mảng, do người lập trình đặt theo quy tắc về đặt tên trong C. Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  63. Bài giảng Cơ sở lập trình -61- + Số_phần_tử_của_mảng: Số phần tử của mảng, có thể là hằng số (hoặc biểu thức hằng) nguyên dương. - Chức năng: Khi gặp dòng lệnh định nghĩa một mảng, chương trình dịch sẽ cấp phát một vùng nhớ đủ chứa các phần tử liên tiếp của mảng. - Ví dụ 5.1: + int vector[20]; /* Mảng có tên vector, gồm 20 phần tử có kiểu int */ + float ST[10]; /* Mảng có tên ST gồm 10 phần tử có kiểu float */ + char KT[5]; /* Mảng có tên KT gồm 5 phần tử có kiểu ký tự */ - Khởi tạo giá trị của mảng: Giá trị các phần tử của mảng có thể được khởi tạo ngay khi khai báo. - Ví dụ 5.2: + int A[3] = {7,4,5}; 5.1.2.2 Truy xuất các phần tử của mảng một chiều - Cú pháp: Tên_mảng[Chỉ_số_phần_tử]; Trong đó: + Chỉ_số_phần_tử: Là số thứ tự của phần tử trong mảng, các phần tử của mảng được đánh chỉ số bắt đầu từ 0. Như vậy, mảng có n phần tử thì các phần tử của nó có chỉ số lần lượt là 0, 1, 2, , n-1. - Ví dụ 5.3: Thực hiện đoạn chương trình sau: #include main() { int SO[3] = {4,5,6}; char KT[5] = {‘A’,’B’,’C’,’D’,’E’}; printf(“\n So thu %d trong mang SO là %d“,2,SO[2]); printf(“\n Ky tu thu %d trong mang KT là %c“,0,SO[0]); getch(); } Kết quả trên màn hình khi thực hiện đoạn chương trình trên: So thu 2 trong mang SO là 6 Ky tu thu 0 mang KT là A - Lưu ý: + Các chương trình dịch của C không bắt lỗi khi người dùng truy xuất phần tử của mảng vượt ra ngoài phạm vi của mảng, tức có chỉ số nhỏ hơn 0 hoặc lớn hơn Số_phần_tử_của_mảng trừ 1. Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  64. Bài giảng Cơ sở lập trình -62- + Trường hợp người lập trình không xác định số phần tử của mảng khi khai báo thì chương trình dịch sẽ tự động xác định kích thước (số phần tử của mảng) theo số lượng các giá trị có trong phần khởi tạo giá trị cho mảng. - Ví dụ 5.4: Giả sử có khai báo int A[] = {1,3,4}; thì A là mảng có 3 phần tử, giá trị của A[0] = 1, A[1] = 3, A[2] = 4. 5.1.2.3 Một số thao tác đối với mảng một chiều F Thao tác gán giá trị cho phần tử cuả mảng: Cho A và B là các biến mảng có cùng kiểu và giả sử các phần tử của biến mảng A đã có giá trị, khi đó bạn có thể sử dụng lệnh gán một phần tử của A cho một phần tử của mảng B. - Ví dụ 5.5: Giả sử có khai báo int A[5] = {1,2,3,4,5}; int B[3]; thì ta có thể gán B[2] = A[4]; Lúc đó, giá trị của B[2] = 5; F Sắp xếp các phần tử của mảng: - Ví dụ 5.6: Viết chương trình thực hiện các công việc: + Nhập liệu cho mảng A có n phần tử nguyên (n > 0) từ bàn phím. + Sắp xếp mảng số đã nhập tăng dần theo giá trị của các phần tử có trong mảng. + In ra màn hình mảng số ban đầu và mảng đã sắp xếp theo thứ tự tăng dần. Yêu cầu kỹ thuật: Chương trình phải kiểm tra n nhập vào (n ≥ 2 và n ≤ MAX-1, MAX là số phần tử tối đa của mảng) Giải: #include #define max 10 main() { int n,i,j,A[max],tam; clrscr(); do { printf("Nhap so phan tu cua mang "); scanf("%d",&n); } while (n max-1); printf("\n Nhap gia tri cho cac phan tu cua mang \n"); Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  65. Bài giảng Cơ sở lập trình -63- for (i=0;i<n;i++) { printf("A[%d] = ",i); scanf("%d",&A[i]); } printf("\n Mang ban dau \n"); for (i=0;i<n;i++) printf("\n A[%d] = %d",i,A[i]); for (i=0;i<n-1;i++) for (j=i+1;j<=n-1;j++) if (A[j] < A[i]) { tam = A[i]; A[i] = A[j]; A[j] = tam; } printf("\n Mang sau khi sap xep \n"); for (i=0;i<n;i++) printf("\n A[%d] = %d",i,A[i]); getch(); } * Giải thích đoạn chương trình sắp xếp trong ví dụ 5.6: for (i=0;i<n-1;i++) for (j=i+1;j<=n-1;j++) if (A[j] < A[i]) { tam = A[i]; A[i] = A[j]; A[j] = tam; } Với cách sắp xếp như trên gọi là phương pháp lựa chọn trực tiếp. Ý tưởng cơ bản của phương pháp này là ở lượt thứ i (i = 0, 1, 2, , n-2) sẽ chọn trong dãy khóa Ki, Ki+1, , Kn-1 khóa nhỏ nhất và đổi chỗ với Ki. - Ví dụ 5.7: Sắp xếp mảng số như ví dụ 5.6 nhưng dùng phương pháp nổi bọt. Ý tưởng chính của phương pháp này là mảng các khóa sẽ được duyệt từ đáy lên đỉnh. Trên đường duyệt, nếu gặp hai khóa kế cận ngược thứ tự thì đổi chỗ chúng cho nhau. Do đó, trong lượt đầu, khóa có giá trị nhỏ nhất sẽ được chuyển lên đỉnh. Lượt chạy thứ 2, khóa có giá trị nhỏ thứ 2 được chuyển lên vị trí 2 Và cứ tiếp tục như thế cho đến khi toàn bộ mảng các khóa đã được sắp xếp. Giải Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  66. Bài giảng Cơ sở lập trình -64- #include #define max 10 main() { int n,i,j,A[max],tam; clrscr(); do { printf("Nhap so phan tu cua mang "); scanf("%d",&n); } while (n max-1); printf("\n Nhap gia tri cho cac phan tu cua mang \n"); for (i=0;i 1;j ) if (A[j] < A[j-1]) { tam = A[j]; A[j] = A[j-1]; A[j-1] = tam; } printf("\n Mang sau khi sap xep \n"); for (i=0;i<n;i++) printf("\n A[%d] = %d",i,A[i]); getch(); } Ngoài ra còn nhiều thuật toán sắp xếp khác, bạn sẽ được học trong học phần cấu trúc dữ liệu và giải thuật ở năm thứ 2. F Tìm kiếm phần tử của mảng theo một điều kiện cho trước: - Ví dụ 5.8: Viết chương trình thực hiện các công việc: Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  67. Bài giảng Cơ sở lập trình -65- + Nhập liệu cho mảng có n phần tử nguyên (n > 0) từ bàn phím. + Nhập số nguyên k từ bàn phím. + Tìm kiếm phần tử đầu tiên trong mảng có giá trị bằng k và thông báo lên màn hình vị trí của phần tử đó; Nếu không có phần tử nào của mảng có giá trị bằng k thì thông báo “Trong mảng không có phần tử nào chứa giá trị cần tìm”. Yêu cầu kỹ thuật: Chương trình phải kiểm tra n nhập vào: nếu n số phần tử tối đa của mảng thì cho nhập lại số phần tử cho đến khi thỏa mãn điều kiện. Giải: #include #define max 10 main() { int n,i,k,A[max]; clrscr(); do { printf("Nhap so phan tu cua mang "); scanf("%d",&n); } while (n max-1); printf("\n Nhap gia tri cho cac phan tu cua mang \n"); for (i=0;i n-1) printf(“Trong mang khong co phan tu nao chua gia tri can tim”); else printf(“Phan tu dau tien co gia tri bang %d tai vi tri %d”,k,i); getch(); } Việc tìm kiếm một phần tử trong mảng như trong ví dụ 5.8 gọi là tìm kiếm tuần tự. Với cách tìm kiếm tuần tự thì trường hợp xấu nhất có đến n phép so sánh. Trong trường hợp mảng A đã được sắp xếp (tăng dần hoặc giảm dần) bạn có thể dùng giải Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  68. Bài giảng Cơ sở lập trình -66- thuật tìm kiếm nhị phân để giảm số phép so sánh (tức giảm độ phức tạp tính toán. Lúc đó sẽ có 3 khả năng xảy ra: + Gọi d và c là phạm vi tìm kiếm (lúc đầu d = 0, c = n-1), j là phần tử đứng giữa mảng (j = (d + c) div 2), nếu A[j] = k, kết luận tìm được k ở vị trí j trong mảng. + Nếu A[j] > k, lặp lại việc tìm kiếm k trong nữa đầu của mảng. + Nếu A[j] #define max 10 main() { int n,i,k,A[max]; int d,c,j; clrscr(); do { printf("Nhap so phan tu cua mang "); scanf("%d",&n); } while (n max-1); printf("\n Nhap gia tri cho cac phan tu cua mang \n"); for (i=0;i<n;i++) { printf("A[%d] = ",i); scanf("%d",&A[i]); } printf("Nhap so nguyen k can tim "); scanf("%d",&k); d = 0; c = n-1; while (d <= c) { j = (d+c)/2; if (A[j] == k) { printf(“Tim thay phan tu %d tai vi tri %d ”,j); getch(); return; } if (A[j] < k) d = j + 1; Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  69. Bài giảng Cơ sở lập trình -67- else c = j – 1; } printf(“Trong mang khong co phan tu nao chua gia tri can tim”); getch(); } - Ví dụ 5.10: Viết chương trình thực hiện các công việc: + Nhập liệu cho mảng một chiều có n phần tử nguyên (n > 0) từ bàn phím. + Kiểm tra mảng một chiều vừa nhập có đối xứng hay không ? Biết rằng: Mảng một chiều A có n phần tử là mảng đối xứng nếu mọi phần tử của mảng thỏa mãn A[i] = A[n - 1 - i ], với i = 0, , n-1 Ví dụ: Các mảng một chiều sau đây là đối xứng: A[0] = 1 A[1] = 2 A[2] = 3 A[3] = 2 A[4] = 1 B[0] = 1 B[1] = 2 B[2] = 3 B[3] = 3 B[4] = 2 B[5] = 1 Các mảng một chiều sau đây là không đối xứng: C[0] = 1 C[1] = 2 C[2] = 3 C[3] = 1 C[4] = 2 D[0] = 1 D[1] = 2 D[2] = 3 D[3] = 4 D[4] = 2 D[5] = 1 Giải: #include #define max 20 main() { int A[max]; int i, n, kt=1; clrscr(); do { printf("Nhap so phan tu cua mang "); scanf("%d",&n); } while (n max-1); printf("\n Nhap gia tri cho cac phan tu cua mang \n"); for (i=0;i<n;i++) { printf("A[%d] = ",i); scanf("%d",&A[i]); } for (i=0; i < n/2; i++) Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  70. Bài giảng Cơ sở lập trình -68- if (A[i] != A[n-1-i]) { kt = 0; break; } if (kt==0) printf("Mang mot chieu vua tao la mang khong doi xung"); else printf("Mang mot chieu vua tao la mang doi xung"); getch(); } * Giải thích ví dụ 5.10: Tư tưởng thực hiện: + Dùng biến kt để kiểm tra, giả sử ban đầu kt = 1 (xem như mảng đối xứng) + Bạn chỉ cần cho biến i của vòng lặp for chạy đến nữa dãy (từ phần tử đầu tiên đến phần tử có chỉ số n/2). + Với mỗi lần lặp, so sánh từng cặp phần tử, phần tử ở nửa dãy đầu với phần tử đối xứng với nó ở nữa dãy cuối (tức phần tử ở vị trí i so sánh với phần tử ở vị trí n-1-i). Nếu 2 phần tử ở vị trí đối xứng có giá trị không bằng nhau thì trả biến kiểm tra kt về 0 (tức nhận giá trị sai, nghĩa là mảng không đối xứng) và kết thúc lặp. + Khi ra khỏi vòng lặp căn cứ vào giá trị biến kt để kết luận: nếu kt =0 thì mảng một chiều không đối xứng, nếu kt = 1 thì mảng một chiều đối xứng. F Đếm các phần tử của mảng theo điều kiện cho trước: - Ví dụ 5.11: Viết chương trình thực hiện các công việc: + Nhập liệu cho mảng có n phần tử nguyên (n > 0) từ bàn phím. + Tính và in ra màn hình số lượng số nguyên lẻ, số lượng số nguyên chẳn trong mảng đã nhập. Yêu cầu kỹ thuật: Chương trình phải kiểm tra n nhập vào: nếu n số phần tử tối đa của mảng thì cho nhập lại số phần tử cho đến khi thỏa mãn điều kiện. Giải: #include #define max 10 main() { int n,i,A[max]; int le = 0,chan = 0; Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.
  71. Bài giảng Cơ sở lập trình -69- clrscr(); do { printf("Nhap so phan tu cua mang "); scanf("%d",&n); } while (n max-1); printf("\n Nhap gia tri cho cac phan tu cua mang \n"); for (i=0;i 0) từ bàn phím. + Nhập số nguyên k, xóa các phần tử trong mảng có giá trị bằng k. Yêu cầu kỹ thuật: Chương trình phải kiểm tra n nhập vào: nếu n số phần tử tối đa của mảng thì cho nhập lại số phần tử cho đến khi thỏa mãn điều kiện. Giải: #include #define max 10 main() { int i, n, A[max]; int c,k; clrscr(); do { printf("Nhap so phan tu cua mang "); scanf("%d",&n); } while (n max-1); printf("\n Nhap gia tri cho cac phan tu cua mang \n"); Giảng viên: Th.S Trần Tấn Từ - Khoa CNTT – Đại học Phạm Văn Đồng.