Download as pdf or txt
Download as pdf or txt
You are on page 1of 119

Phần 3: Lập trình C

Nội dung chính


• Chương 1: Tổng quan về ngôn ngữ C
• Chương 2: Kiểu dữ liệu và biểu thức trong C
TIN HỌC ĐẠI CƯƠNG • Chương 3: Vào ra dữ liệu
Phần 3: LẬP TRÌNH C • Chương 4: Cấu trúc điều khiển
Nguyễn Thị Thanh Nga • Chương 5: Mảng, con trỏ và xâu ký tự
ngantt@soict.hust.edu.vn • Chương 6: Cấu trúc
• Chương 7: Hàm
• Chương 8: Tệp dữ liệu
2

1 2

Chương 1: Tổng quan về ngôn ngữ C


Chương 1: Tổng quan về ngôn ngữ lập trình C
1.1 Lịch sử phát triển của ngôn ngữ C

Nội dung chính Sự ra đời của C


• Nhu cầu viết lại HĐH Unix cho các hệ máy
1. Lịch sử phát triển của ngôn ngữ C tính khác nhau
– Dùng Assembly
• Công việc nặng nề, phức tạp
2. Các phần tử cơ bản của ngôn ngữ C • Khó chuyển đổi chương trình giữa các hệ máy tính
khác nhau
– Cần ngôn ngữ mới
3. Cấu trúc cơ bản của chương trình C • Đơn giản việc lập trình
• Tính khả chuyển cao
4. Biên dịch chương trình C • C ra đời tại Bell Lab thuộc tập đoàn AT&T
– Tác giả Brian W. Kernighan & Dennis Ritchie
– Dựa trên nền BCPL& B
3
– Phát triển năm 1970, hoàn thành 1972 4

3 4

1
Chương 1: Tổng quan về ngôn ngữ lập trình C Chương 1: Tổng quan về ngôn ngữ lập trình C
1.1 Lịch sử phát triển của ngôn ngữ C 1.1 Lịch sử phát triển của ngôn ngữ C

Ngôn ngữ lập trình C Ngôn ngữ lập trình C


• Đặc điểm • Các phiên bản
– Ngôn ngữ lập trình hệ thống – ANSI C: C chuẩn (1989)
– Tính khả chuyển, linh hoạt cao – Các phiên bản khác xây dựng dựa trên ANSI C
– Có thế mạnh trong xử lý dữ liệu số, văn bản, cơ • Đưa thêm thư viện; Bổ sung cho thư viện chẩn
sở dữ liệu,.. của ANSI C
• Phạm vi sử dụng • Các trình biên dịch phổ biên
– Viết các chương trình hệ thống – Turbo C++ và Borland C++ của hãng Borland
• Hệ điều hành Unix có 90% mã C, 10% mã hợp ngữ Inc
– Các trình điều khiển thiết bị (device driver) – VC và MSC của Microsoft Corp
– Xử lý ảnh – GCC của GNU project
5 6

5 6

Chương 1: Tổng quan về ngôn ngữ C


Chương 1: Tổng quan về ngôn ngữ lập trình C
1.2 Các phần tử cơ bản của ngôn ngữ C

Nội dung chính Các phần tử cơ bản


1. Tập ký tự
1. Lịch sử phát triển 2. Từ khóa
3. Định danh
2. Các phần tử cơ bản của ngôn ngữ C 4. Các kiểu dữ liệu
5. Hằng
3. Cấu trúc cơ bản của chương trình C 6. Biến
7. Hàm
4. Biên dịch chương trình C 8. Biểu thức
9. Câu lệnh
10. Chú thích
7 8

7 8

2
Chương 1: Tổng quan về ngôn ngữ lập trình C Chương 1: Tổng quan về ngôn ngữ lập trình C
1.2 Các phần tử cơ bản của ngôn ngữ C 1.2 Các phần tử cơ bản của ngôn ngữ C

1. Tập ký tự 1. Tập ký tự→ Tập ký tự trong C


Ký tự là các phần tử cơ bản tạo nên chương • 26 chữ cái hoa:A B C ... X Y Z
trình
• 26 chữ cái thường:a b c … x y z.
• Chương trình: Tập các câu lệnh nhằm
• 10 chữ số: 0 1 2 3 4 5 6 7 8 9.
giải quyết nhiệm vụ đặt ra
• Câu lệnh: là các từ (từ vựng) liên kết với • Các kí hiệu toán học:+ - * / = < >
nhau theo cú pháp của ngôn ngữ lập trình • Các dấu ngăn cách: . ; , : space tab
– Ví dụ: while (i < N ) do • Các dấu ngoặc:( ) [ ] { }
• Các từ: Tổ hợp các ký tự theo nguyên tắc • Các kí hiệu đặc biệt:_ ? $ & # ^ \ ! ‘ “
xây dựng từ vựng ~ ...
– Ví dụ: TenFile, BaiTap2…
9 10

9 10

Chương 1: Tổng quan về ngôn ngữ lập trình C Chương 1: Tổng quan về ngôn ngữ lập trình C
1.2 Các phần tử cơ bản của ngôn ngữ C 1.2 Các phần tử cơ bản của ngôn ngữ C

2. Từ khóa (keyword) 2. Từ khóa→Từ khóa hay dùng trong Turbo C

• Được định nghĩa sẵn trong mỗi NNLT


break case char const continue default
• Dành riêng cho các mục đích xác định do double else enum float for

– Đặt tên cho kiểu dữ liệu: goto if int interrupt long return
short signed sizeof static struct switch
• int, float, double…
typedef union unsigned void while
– Mô tả các lệnh, các cấu trúc lập trình
• if, else, while, case, for… Lưu ý:Tất cả từ khóa trong C đều viết bằng
chữ cái thường

11 12

11 12

3
Chương 1: Tổng quan về ngôn ngữ lập trình C Chương 1: Tổng quan về ngôn ngữ lập trình C
1.2 Các phần tử cơ bản của ngôn ngữ C 1.2 Các phần tử cơ bản của ngôn ngữ C

3. Định danh (Identifier) 3. Định danh→ Quy tắc đặt tên định danh trong C
• Định danh (Tên) là một dãy các kí tự dùng • Định danh được bắt đầu bởi chữ cái hoặc
để gọi tên các đối tượng trong chương dấu gạch dưới “_” (underscore)
trình. • Các kí tự tiếp theo chỉ có thể là: chữ cái,
– Các đối tượng trong chương trình chữ số hoặc dấu gạch dưới “_”
• Biến • Định danh do người lập trình đặt không
• Hằng số được trùng với các từ khóa của C
• Hàm
• Độ dài định danh tùy thuộc phiên bản C
• Kiểu dữ liệu
– Ví dụ: Turbo C++, không giới hạn độ dài tên,
• Định danh có thể được đặt bởi nhưng trình biên dịch chỉ sử dụng 32 ký tự đầu
– Ngôn ngữ lập trình → các từ khóa
Chú ý: C là ngôn ngữ có phân biệt chữ hoa
– Người lập trình và chữ thường
13 14

13 14

Chương 1: Tổng quan về ngôn ngữ lập trình C Chương 1: Tổng quan về ngôn ngữ lập trình C
1.2 Các phần tử cơ bản của ngôn ngữ C 1.2 Các phần tử cơ bản của ngôn ngữ C

3. Định danh→Ví dụ 3. Định danh→ Một số quy ước (code convention)

• Định danh hợp lệ: • Định danh nên có tính gợi nhớ
i, x, y, a, b, _function,
• Nên sử dụng dấu gạch dưới để phân tách
các định danh gồm nhiều từ
_MY_CONSTANT, PI, gia_tri_1
– Có thể dùng cách viết hoa chữ cái đầu mỗi từ
• Định danh không hợp lệ -Ví dụ: sinh_vien, sinhVien, SinhVien
1_a, 3d, 55x (bắt đầu bằng chữ số) • Quy ước thường được sử dụng:
– Hằng số dùng chữ cái hoa
so luong, sin() (có kí tự không hợp lệ, dấu
• Ví dụ: PI, EPSILON,…
cách, dấu ngoặc..)
– Các biến, hàm, cấu trúc dùng chữ cái thường
int, char (trùng với từ khóa của C) • Biến điều khiển vòng lặp: i, j, k…
• Hàm: NhapDuLieu, TimKiem,…
• Cấu trúc: SinhVien, MatHang,…
15 16

15 16

4
Chương 1: Tổng quan về ngôn ngữ lập trình C Chương 1: Tổng quan về ngôn ngữ lập trình C
1.2 Các phần tử cơ bản của ngôn ngữ C 1.2 Các phần tử cơ bản của ngôn ngữ C

4. Các kiểu dữ liệu 4. Các kiểu dữ liệu→Ví dụ kiểu int

• Một kiểu dữ liệu là một tập hợp các giá trị Một số phép toán được định nghĩa trên kiểu
dữ liệu int của C
mà một dữ liệu thuộc kiểu dữ liệu đó có thể
nhận được. Tên phép toán Ký hiệu Ví dụ
– Ví dụ: Một đối tượng kiểu int của C sẽ là Đảo dấu -
• Một số nguyên (Số nguyên có dấu, 2 byte) Cộng;Trừ;Nhân +;-;*
• Giá trị thuộc khoảng: [-32,768 (-215) …32,767 (215-1)] Chia lấy nguyên / 17/3→5
• Trên một kiểu dữ liệu, xác định một số phép Chia lấy phần dư % 17%3→2
toán đối với các dữ liệu thuộc kiểu dữ liệu So sánh >, <, >=, <=, ==, !=
tương ứng. Logic bit: AND; OR; & ; | ; 3^17 →18
XOR;NOT, Shift,… ^ ; ~ ; <<; >> ~3 →-4
17 18

17 18

Chương 1: Tổng quan về ngôn ngữ lập trình C Chương 1: Tổng quan về ngôn ngữ lập trình C
1.2 Các phần tử cơ bản của ngôn ngữ C 1.2 Các phần tử cơ bản của ngôn ngữ C

5. Hằng 5. Hằng → Hằng số nguyên

• Hằng (constant) là đại lượng có giá trị • Trong C, hằng số nguyên có thể biểu diễn
không đổi trong chương trình. dưới các dạng
– Dạng thập phân
• Giá trị hằng do người lập trình xác định
– Dạng thập lục phân
• Các loại hằng – Dạng bát phân
– Hằng số nguyên
Giá trị Giá trị Giá trị
– Hằng số thực thập phân thập lục phân bát phân
– Hằng ký tự 2011 0x7DB 03733
– Hằng chuỗi/xâu kỹ tự
396 0x18C 0614
19 20

19 20

5
Chương 1: Tổng quan về ngôn ngữ lập trình C Chương 1: Tổng quan về ngôn ngữ lập trình C
1.2 Các phần tử cơ bản của ngôn ngữ C 1.2 Các phần tử cơ bản của ngôn ngữ C

5. Hằng → Hằng số thực 5. Hằng → Hằng ký tự


• Trong C, hằng số thực có thể biểu diễn dưới • Hằng ký tự có thể biểu diễn theo hai cách
các dạng – Đặt ký hiệu của ký tự giữa hai dấu nháy đơn
– Dạng số thực dấu phẩy tĩnh – Dùng mã ASCII của ký tự:
– Dạng số thực dấu phẩy động • Số thứ tự của ký tự đó trong bảng mã ASCII
• Là số nguyên→tuân thủ quy tắc biểu diễn số nguyên
Số thực dấu phẩy tĩnh Số thực dấu phẩy động
Ký tự Dùng nháy đơn Dùng mã ASCII
3.14159 31.4159 E-1 Chữ cái A ‘A’ 65, 0x41, 0101
123.456 12.3456 E+1 hoặc Dấu nháy đơn ‘\’’ 39, 0x27, 047
1.23456 E+2
Ký tự tab ‘\t’ 9, 0x09, 011
21 22

21 22

Chương 1: Tổng quan về ngôn ngữ lập trình C Chương 1: Tổng quan về ngôn ngữ lập trình C
1.2 Các phần tử cơ bản của ngôn ngữ C 1.2 Các phần tử cơ bản của ngôn ngữ C

5. Hằng → Hằng chuỗi/xâu kỹ tự 6. Biến (variable)


• Biến là đại lượng mà giá trị có thể thay đổi
• Hằng chuỗi/xâu kí tự được biểu diễn bởi đặt
trong chương trình.
dãy các kí tự trong xâu trong cặp dấu nháy
• Tên biến phải được đặt theo quy tắc đặt tên
kép.
– Về thực chất, biến là các ô nhớ trong bộ nhớ
• Ví dụ: máy tính dành cho 1 kiểu dữ liệu nào đó và
– “ngon ngu lap trinh C” được đặt tên để tiện tham khảo
• Ví dụ: Biến kiểu int chiếm 2 ô nhớ
– “Tin hoc dai cuong”
• Lưu ý:
– “Dai hoc Bach Khoa Ha Noi”
– Hằng số và biến được sử dụng để lưu trữ dữ
liệu trong chương trình và phải thuộc một kiểu
dữ liệu nào đó
23 24

23 24

6
Chương 1: Tổng quan về ngôn ngữ lập trình C Chương 1: Tổng quan về ngôn ngữ lập trình C
1.2 Các phần tử cơ bản của ngôn ngữ C 1.2 Các phần tử cơ bản của ngôn ngữ C

7. Hàm (function) 7. Hàm → Một số hàm toán học


• Hàm là chương trình con có chức năng Hàm Ý nghĩa Ví dụ
sqrt(x) Căn bậc 2 của x sqrt(16.0) → 4.0
– Nhận dữ liệu đầu vào (các tham số vào)
pow(x,y) X mũ y ( xy ) pow(2,3) → 8
– Thực hiện một công việc nào đó fabs(x) Trị tuyệt đối của x ( |x| ) fabs(-5.0) →5.0
– Trả về kết quả ứng với tham số truyền vào exp(x) E mũ x ( ex ) exp(1.0)→2.71828
• Ví dụ: hàm sin(x) log(x) Logarithm tự nhiên của x (ln x) Log(2.718)→0.999
– sin(3.14/2) →1.000 log10(x) Logarithm cơ số 10 của x (logx) Log10(100) →2.00
– sin(3.14/6) →0.499770 sin(x) Các hàm lượng giác
cos(x)/ tan(x)
• Hàm không trả lại một giá trị: Thủ tục ceil(x) Số nguyên nhỏ nhất không nhỏ ceil(2.5)=3
– Ví dụ: clrscr() hơn x (x) ceil(-2.5)=-2
floor(x) Số nguyên lớn nhất không lớn floor(2.5)=2
25
hơn x ( x) floor(-2.5)=-3 26

25 26

Chương 1: Tổng quan về ngôn ngữ lập trình C Chương 1: Tổng quan về ngôn ngữ lập trình C
1.2 Các phần tử cơ bản của ngôn ngữ C 1.2 Các phần tử cơ bản của ngôn ngữ C

8. Biểu thức 9. Câu lệnh (statement)


• Biểu thức là sự kết hợp các các toán hạng • Câu lệnh diễn tả một hoặc một nhóm các
(operand) bởi các toán tử (operator) theo
thao tác trong giải thuật.
một quy tắc xác định.
– Chương trình được tạo thành từ dãy các câu
• Các toán hạng có thể là biến, hằng, hàm… lệnh.
• Các toán tử rất đa dạng: cộng, trừ, nhân,
chia • Các câu lệnh trong C, được kết thúc bởi
Ví dụ dấu chấm phẩy (;)
– Thể tích hình hộp: V=Rộng*Cao*Dày – Dấu chấm phẩy (;) dùng phân cách các lệnh
• Phép nhân (*) là toán tử
Cao

• Các toán hạng Rộng, Cao, Dày


Rộng
27 28

27 28

7
Chương 1: Tổng quan về ngôn ngữ lập trình C Chương 1: Tổng quan về ngôn ngữ lập trình C
1.2 Các phần tử cơ bản của ngôn ngữ C 1.2 Các phần tử cơ bản của ngôn ngữ C

9. Câu lệnh → Phân loại 10. Chú thích (comment)

• Câu lệnh đơn: • Lời mô tả, giải thích vắn tắt cho một câu
– Những câu lệnh không chứa câu lệnh khác. lệnh, một đoạn chương trình hoặc cả
• Ví dụ: Phép gán, gọi hàm, vào/ra dữ liệu chương trình
• Các câu lệnh phức: – Giúp việc đọc hiểu chương trình dễ dàng hơn
– Những câu lệnh chứa câu lệnh khác. – Chú thích không phải là câu lệnh  không ảnh
hưởng tới chương trình
• Ví dụ: Lệnh khối (Tập các lệnh đơn nhóm lại với
nhau và đặt trong cặp ngoặc nhọn « { } ») • Khi gặp chú thích, trình biên dịch sẽ bỏ qua

– Các lệnh điều khiển cấu trúc chương trình • Cách viết chú thích
• Ví dụ: Lệnh rẽ nhánh, lệnh lặp.. – Chú thích một dòng: sử dụng « // »
– Chú thích nhiều dòng: sử dụng « /* » và « */ »
29 30

29 30

Chương 1: Tổng quan về ngôn ngữ C


Chương 1: Tổng quan về ngôn ngữ lập trình C
1.3 Cấu trúc cơ bản của chương trình C

Nội dung chính Các phần cơ bản


Khai báo các tệp tiêu đề
1. Lịch sử phát triển #include
Khai báo các đối tượng toàn cục
2. Các phần tử cơ bản của ngôn ngữ C • Định nghĩa kiểu dữ liệu mới
• Các biến, hằng
• Các hàm nguyên mẫu (prototype)
3. Cấu trúc cơ bản của chương trình C
Định nghĩa hàm main()
{
4. Biên dịch chương trình C
}
Định nghĩa các hàm đã khai báo nguyên mẫu
31 32

31 32

8
Chương 1: Tổng quan về ngôn ngữ lập trình C Chương 1: Tổng quan về ngôn ngữ lập trình C
1.3 Cấu trúc cơ bản của chương trình C 1.3 Cấu trúc cơ bản của chương trình C

1. Khai báo các tệp tiêu đề 2. Khai báo các đối tượng toàn cục
• Liệt kê danh sách thư viện sẽ được sử dụng
trong chương trình • Các đối tượng toàn cục có phạm vi sử dụng
– Các hàm của C đều thuộc một thư viện nào đó trong toàn bộ chương trình
– Không khai báo thư viện, trình biên dịch không – Các kiểu dữ liệu mới
hiểu được hàm (có thể báo lỗi)
– Các hằng, biến
• Cách thức (cú pháp) khai báo
1. #include<ThuVien.h> – Các nguyên hàm
• Thư viện phải nằm trong thư mục chứa các header file
• Thường được sử dụng • Tuân theo nguyên tắc khai báo đối tượng
• Ví dụ: #include<stdio.h>
2. #include “ThuVien.h”
• Tìm kiếm thư viện tại thư mục hiện tại
33 34

33 34

Chương 1: Tổng quan về ngôn ngữ lập trình C Chương 1: Tổng quan về ngôn ngữ lập trình C
1.3 Cấu trúc cơ bản của chương trình C 1.3 Cấu trúc cơ bản của chương trình C

2. Khai báo các đối tượng toàn cục 2. Khai báo các đối tượng toàn cục (tiếp)
Định nghĩa kiểu dữ liệu Khai báo các hàm nguyên mẫu
Cú pháp: typedef <ĐịnhNghĩaKiểu> <Tên kiểu> • Khai báo thông tin về các hàm của người
Ví dụ: typedef unsigned char byte; dùng sẽ được sử dụng trong chương trình
typedef struct {float re, im;} complex; – Tên hàm
Khai báo hằng – Danh sách các kiểu tham số sẽ truyền vào
const float PI = 3.1415; – Kiểu dữ liệu trả về
#define Max 50 • Ví dụ
float DienTichTamGiac(float a, float b, float c);
Khai báo biến
int getMax(int Arr []);
int N; Có thể bỏ tên tham số
void swap(int * a, int * b);
float Delta, x1, x2; void swap(int *, int *);
35 36

35 36

9
Chương 1: Tổng quan về ngôn ngữ lập trình C Chương 1: Tổng quan về ngôn ngữ lập trình C
1.3 Cấu trúc cơ bản của chương trình C 1.3 Cấu trúc cơ bản của chương trình C

3. Định nghĩa hàm main() 4. Định nghĩa các hàm đã khai báo
• Bắt buộc phải có • Định nghĩa các hàm đã khai báo ở phần 3
• Là hàm đặc biệt trong C, đánh dấu điểm bắt (Phần khai báo nguyên mẫu - prototype)
đầu của mọi chương trình C – Phần khai báo nguyên mẫu mới chỉ khai báo các
– Khi thực hiện một chương trình C, hệ thống sẽ thông tin cơ bản về hàm, chưa xác định rõ hàm
gọi tới hàm main đầu tiên, sau đó sẽ thực hiện hoạt động như thế nào
lần lượt các câu lệnh (bao gồm cả lời gọi tới các
hàm khác) nằm trong hàm main() • Ví dụ
• Cú pháp float DienTichTamGiac(float a, float b, float c){
void main(){….} float p = (a+b+c)/2;
void main(int argc, char * argv[ ]){….} return sqrt(p*(p-a)*(p-b)*(p-c));
int main(){….; return 0;} }
int main(int argc, char * argv[ ]){….; return 0;}
37 38

37 38

Chương 1: Tổng quan về ngôn ngữ lập trình C Chương 1: Tổng quan về ngôn ngữ lập trình C
1.3 Cấu trúc cơ bản của chương trình C 1.3 Cấu trúc cơ bản của chương trình C

Chú ý Chương trình đầu tiên: Hello world!


1. #include <stdio.h>
Các phần không bắt buộc phải theo đúng thứ tự 2. int main(){ //Không cần tham số dòng lệnh
3. printf("Hello world! \n");
• Khi định nghĩa hàm được đặt trước hàm 4. return 0; //Trả về giá trị 0
main(), không cần khai báo nguyên hàm 5. }
1. Nạp thư viện stdio.h vào, đây là thư viện vào ra chuẩn
• Nguyên tắc: (standard input output) chứa khai báo nguyên hàm cho
– Mọi đối tượng cần phải được khai báo trước khi hàm printf
2. Điểm bắt đầu thực hiện của chương trình. Máy tính thực
sử dụng
hiện các câu lệnh nằm trong cặp ngoặc {} của main()
3. Hàm printf in ra một hằng chuỗi, có kết thuc bởi dấu
xuống dòng (\n)
4. Trả về hệ điều hành một giá trị. Giá trị 0 thường dùng để
thể hiện chương trình không có lỗi
39 40

39 40

10
Chương 1: Tổng quan về ngôn ngữ C
Chương 1: Tổng quan về ngôn ngữ lập trình C
1.4 Biên dịch chương trình C

Nội dung chính Biên dịch chương trình


• Chương trình được viết bằng ngôn ngữ bậc
1. Lịch sử phát triển cao phải được dịch ra mã máy để thực thi
– Công việc dịch được thực hiện bởi trình biên
dịch (compiler)
2. Các phần tử cơ bản của ngôn ngữ C • Các giai đoạn dịch chương trình
Văn bản nguồn Tiền xử lý Dịch Mã hợp ngữ
3. Cấu trúc cơ bản của chương trình C Source code Preprocessor Compiler Assembly code

4. Biên dịch chương trình C Mã thực thi Liên kết Mã đối tượng Hợp dịch
Executable code Link Object code Asembler
Thư viện
Libraries
41 42

41 42

Chương 1: Tổng quan về ngôn ngữ lập trình C Chương 1: Tổng quan về ngôn ngữ lập trình C
1.4 Biên dịch chương trình C 1.4 Biên dịch chương trình C

Các trình biên dịch C Cài đặt Dev-Cpp


Tồn tại nhiều trình biên dịch cho ngôn ngữ C • Tải Dev-C++
• Turbo C++ của Borland Inc (Ví dụ Turbo C++3.0) – Google  Dev-C++
– Cho phép biên dịch cả C và C++ – Tìm đến phiên bản thích hợp, thực hiện tải về
– Gọn nhẹ, đủ tính năng và dễ sử dụng • Dev-Cpp 5.11 TDM-GCC 4.9.2 Setup.exe
– Hệ điều hành DOS (16bit), không phù hợp với Win64 bit • Devcpp_v4_9_9_2_setup.exe
• MSC của Microsoft,
• GCC của GNU
– Trên môi trường Linux
• Thực thi file tải về, làm theo hướng dẫn
• Dev-C, C-free, Codeblocks…
Dev-Cpp Ver 4.9.9.2 hoặc Dev-Cpp 5.1.1
43 44

43 44

11
Chương 1: Tổng quan về ngôn ngữ lập trình C Chương 1: Tổng quan về ngôn ngữ lập trình C
1.4 Biên dịch chương trình C 1.4 Biên dịch chương trình C

Cài đặt Dev-Cpp Màn hình giao diện DEV-C++

45 46

45 46

Chương 1: Tổng quan về ngôn ngữ lập trình C Chương 1: Tổng quan về ngôn ngữ lập trình C
1.4 Biên dịch chương trình C 1.4 Biên dịch chương trình C

Màn hình giao diện DEV-C++ Cài đặt Turbo C++ 3.0
B1: Chuẩn bị bộ cài của Turbo C++ 3.0
• Bộ cài tải trên mạng, kích thước khoảng 4M
• Copy bộ cài này vào máy (giả sử C:\TC_Setup)
B2: Cài đặt Turbo C
• Tìm đến thư mục chứa bộ cài (C:\TC_Setup)
• Kích hoạt file INSTALL.EXE
• Chương trình sẽ yêu cầu chỉ ra ổ đĩa chứa bộ cài TC
• Enter the SOURCE drive to use
• Nhập tên ổ đĩa (ổ C nếu đặt bộ cài tại C:\TC_Setup).
• Enter the SOURCE Path: Nhập đường dẫn tới thư mục
chứa các file của bộ cài TC
• Thông thường chương trình sẽ tự động tìm ra chỉ cần ấn
Enter để chuyển sang bước tiếp theo.
47 48

47 48

12
Chương 1: Tổng quan về ngôn ngữ lập trình C Chương 1: Tổng quan về ngôn ngữ lập trình C
1.4 Biên dịch chương trình C 1.4 Biên dịch chương trình C

Cài đặt Turbo C++ 3.0 Màn hình giao diện Turbo C++ 3.0
B3: Xác định thư mục cài đặt. Thư mục này sẽ chứa
các file của TC được sử dụng về sau.

Dùng các phím  và  để di chuyển hộp sáng đến phần


Start Installation và ấn Enter. Chương trình sẽ tự động
thực hiện và hoàn tất quá trình cài đặt
– Thư mục cài đặt mặc định sẽ là \TC nằm trên thư mục
gốc của ổ đĩa chứa bộ cài.
– Nếu muốn thay đổi thư mục cài đặt, dùng các phím  và
 để di chuyển hộp sáng đến Directories, gõ Enter và
nhập đường dẫn mới, sau đó ấn phím Esc để trở về
Lưu ý: Có thể copy toàn bộ thư mục TC để sử dụng 49 50

49 50

Chương 1: Tổng quan về ngôn ngữ lập trình C Chương 1: Tổng quan về ngôn ngữ lập trình C
1.4 Biên dịch chương trình C 1.4 Biên dịch chương trình C

Sử dụng Turbo C++ 3.0 Chương trình Hello world!


• Khởi động chương trình:
– Tìm đến thư mục BIN trong thư mục cài đặt
– Chạy file TC.EXE
• Tạo cửa sổ soạn thảo mới
– Chọn menu File (hoặc ấn Alt+F)→ chọn New
• Soạn thảo chương trình
– Gõ chương trình nguồn vào cửa số soạn thảo
• Mở chương trình đã có: Alt+F → Open (F3)
• Lưu chương trình: Alt+F → Save (F2)
– Nếu chưa có tên, sẽ được nhắc nhập tên file
• Biên dịch chương trình: Bấm phím F9
• Chạy chương trình: Ctrl + F9
• Xem lại kết quả thực hiện: Alt+F5 51 52

51 52

13
Chương 1: Tổng quan về ngôn ngữ C Phần 3: Lập trình C
Tóm tắt Nội dung chính

1. Lịch sử phát triển của ngôn ngữ C • Chương 1: Tổng quan về ngôn ngữ C
• Chương 2: Kiểu dữ liệu và biểu thức trong C
2. Các phần tử cơ bản của ngôn ngữ C
– 10 phần tử cơ bản • Chương 3: Vào ra dữ liệu

3. Cấu trúc cơ bản của chương trình C • Chương 4: Cấu trúc điều khiển

– 4 phần • Chương 5: Mảng, con trỏ và xâu ký tự

4. Thực hiện chương trình C với Dev-C++ • Chương 6: Cấu trúc


• Chương 7: Hàm
• Chương 8: Tệp dữ liệu
53 54

53 54

Chương 2: Kiểu dữ liệu và biểu thức trong C


Chương 2: Kiểu dữ liệu và biểu thức trong C
2.1 Các kiểu dữ liệu chuẩn trong C

Nội dung chính Các kiểu đơn

Kiểu dữ liệu Ý nghĩa Kích thước Miền dữ liệu


1. Các kiểu dữ liệu chuẩn trong C char Kí tự; 1 byte -128  127
Số nguyên có dấu

2. Biểu thức trong C int Số nguyên 2 byte -32.76832.767


có dấu
short int
3. Các toán tử trong C long Số nguyên có dấu 4 byte -2,147,483,648
 2,147,483,647
long int
Số thực dấu phẩy  3.4E-38 
4. Một số toán tử đặc trưng float
động,
4 byte
 3.4E+38
độ chính xác đơn
double Số thực dấu phẩy 8 byte 1.7E-308 
động,  1.7E+308
độ chính xác kép
55 56

55 56

14
Chương 2: Kiểu dữ liệu và biểu thức trong C Chương 2: Kiểu dữ liệu và biểu thức trong C
2.1 Các kiểu dữ liệu chuẩn trong C 2.1 Các kiểu dữ liệu chuẩn trong C

Các kiểu kết hợp Biểu diễn hằng số


Với số nguyên, thêm từ khóa unsigned để chỉ ra số không dấu
Kiểu dữ liệu Ví dụ Ý nghĩa
Kiểu dữ liệu Ý nghĩa Kích thước Miền dữ liệu Số nguyên 123, -12 Số thập phân
unsigned char Số nguyên 1 byte 0  255 012, 03777 Số bát phân
không dấu
0x7F, 0x3fe15 Số hệ 16
unsigned short Số nguyên 2 byte 065.535 39u 0267u, 0xFFu Số không dấu
không dấu
unsigned Số nguyên lớn 12L, 07723L
unsigned int 0xFFL, -10L
unsigned long Số nguyên 4 byte 0  4,294,967,295
không dấu 0xFFUL,0xFFLU
unsigned long int
Số thực 3.1415 -12.3, .327
long double Số thực dấu 10 byte 3.4E-4932 
phẩy động, 1.1E+4932 10e-12, -15.3E12
void Là kiểu rỗng, kích thước không 3.1415F, -12.F
57 58

57 58

Chương 2: Kiểu dữ liệu và biểu thức trong C Chương 2: Kiểu dữ liệu và biểu thức trong C
2.1 Các kiểu dữ liệu chuẩn trong C 2.1 Các kiểu dữ liệu chuẩn trong C

Khai báo biến Khai báo biến


• Một biến phải được khai báo trước khi sử dụng • Sau khi khai báo, biến chưa có giá trị xác định.
• Cú pháp khai báo: int n; m = 2 * n;  m=?
KieuDuLieu TenBien; – Biến cần được gán giá trị trước khi sử dụng
KieuDuLieu TenBien1, …, TenBien_N; • C cho phép kết hợp khai báo và khởi tạo biến
• Ví dụ: KieuDuLieu TenBien = GiaTriBanDau;
//Khai báo biến x là một số nguyên 2 byte có dấu KieuDuLieu Bien1=GiaTri1, BienN=Gia_TriN;
int x; • Ví dụ:
//Khai báo các biến y, z là các số thực 4 byte //Khai báo biến nguyên a và khởi tạo gia tri bằng 3

float y,z; int a = 3;


//Khai báo biến thực x,y và khởi tạo giá tri bằng 5.0 và 7.6
//Sau khi khai báo, có thể sử dụng
float x = 5.0, y = 7.6;
x = 3; y = x + 1;
59 60

59 60

15
Chương 2: Kiểu dữ liệu và biểu thức trong C Chương 2: Kiểu dữ liệu và biểu thức trong C
2.1 Các kiểu dữ liệu chuẩn trong C 2.1 Các kiểu dữ liệu chuẩn trong C

Khai báo hằng Khai báo hằng

Dùng từ khóa const


Dùng chỉ thị #define Không có dấu
chấm phây (;)
• Cú pháp:
• Cú pháp:
# define Tên_hằng Giá_trị const Kiểu Tên_hằng = giá_trị;

• Ví dụ: • Ví dụ:
#define MAX_SINH_VIEN 50 const int MAX_SINH_VIEN = 50;

#define CNTT “Cong nghe thong tin” const char CNTT[20] = “Cong nghe thong tin”;

#define DIEM_CHUAN 23.5 const float DIEM_CHUAN = 23.5;

61 62

61 62

Chương 2: Kiểu dữ liệu và biểu thức trong C


Chương 2: Kiểu dữ liệu và biểu thức trong C
2.1 Các kiểu dữ liệu chuẩn trong C

Khai báo hằng Nội dung chính

Chú ý:
1. Các kiểu dữ liệu chuẩn trong C
• Giá trị của các hằng phải được xác định ngay
khi khai báo. 2. Biểu thức trong C
• Trong chương trình, KHÔNG thể thay đổi
được giá trị của hằng. 3. Các toán tử trong C
• #define là chỉ thị tiền xử lý
– Dễ đọc, dễ thay đổi 4. Một số toán tử đặc trưng
– Dễ chuyển đổi giữa các nền tảng phần cứng hơn
– Tốc độ nhanh hơn
63 64

63 64

16
Chương 2: Kiểu dữ liệu và biểu thức trong C Chương 2: Kiểu dữ liệu và biểu thức trong C
2.2 Biểu thức trong C 2.2 Biểu thức trong C

Mục đích sử dụng Tính toán giá trị biểu thức


• Các toán hạng được thay thế bởi giá trị tương ứng
• Làm vế phải của lệnh gán.
• Các phép tính được thực hiên
• Làm toán hạng trong các biểu thức khác.
Ví dụ (alpha = 10, beta = 81)
• Làm tham số thực sự trong lời gọi hàm.
Biểu thức: alpha + sqrt(beta)
• Làm biểu thức kiểm tra trong các cấu trúc : alpha + sqrt(81)
điều khiển : alpha + 9.0
– Cấu trúc lặp: for, while, do while. : 10 + 9.0
– Cấu trúc rẽ nhánh: if, switch. : 19.0
65 66

65 66

Chương 2: Kiểu dữ liệu và biểu thức trong C Chương 2: Kiểu dữ liệu và biểu thức trong C
2.2 Biểu thức trong C 2.2 Biểu thức trong C

Các loại biểu thức Biểu thức số học


• Là biểu thức mà giá trị của nó là các đại
• Biểu thứ số học lượng số học (số nguyên, số thực).
– Sử dụng các toán tử là các phép toán số học
(cộng, trừ, nhân, chia…),
• Biểu thức quan hệ – Các toán hạng là các đại lượng số học (hằng số,
biến, biểu thức khác).

• Biểu thức logic • Ví dụ: a, b, c là các biến thuộc kiểu số thực.


3 * 3.7
8 + 6/3
a + b – c
67 68

67 68

17
Chương 2: Kiểu dữ liệu và biểu thức trong C Chương 2: Kiểu dữ liệu và biểu thức trong C
2.2 Biểu thức trong C 2.2 Biểu thức trong C

Biểu thức quan hệ Biểu thức logic


• Là những biểu thức có sử dụng các toán tử • Là biểu thức trả về các giá trị logic Đúng/Sai
quan hệ như lớn hơn, nhỏ hơn, khác nhau… – Các phép toán logic gồm có
• Chỉ có thể trả về một trong 2 giá trị logic AND VÀ logic, sử dụng toán tử &&
OR HOẶC logic, sử dụng toán tử ||
Đúng (TRUE) hoặc Sai (FALSE)
NOT PHỦ ĐỊNH, sử dụng toán tử !
Ví dụ
– Biểu thức quan hệ là trường hợp riêng của biểu
thức logic.
• Ngôn ngữ C coi các giá trị nguyên khác 0 (2,
8, -5,..) là giá trị logic đúng (TRUE), giá trị 0
là giá trị logic sai (FALSE)
69
– Biểu thức logic cũng trả về một giá trị số học 0/170

69 70

Chương 2: Kiểu dữ liệu và biểu thức trong C


Chương 2: Kiểu dữ liệu và biểu thức trong C
2.2 Biểu thức trong C

Biểu thức logic →Ví dụ Nội dung chính

1. Các kiểu dữ liệu chuẩn trong C

2. Biểu thức trong C

3. Các toán tử trong C

4. Một số toán tử đặc trưng

5 * (12 > 6) →?
71 72

71 72

18
Chương 2: Kiểu dữ liệu và biểu thức trong C Chương 2: Kiểu dữ liệu và biểu thức trong C
2.3 Các toán tử trong C 2.3 Các phép tử trong C

Các toán tử chính Các toán tử số học


Toán Ý nghĩa Kiểu dữ liệu của Ví dụ
Các toán tử cho phép tạo nên các biểu tử toán hạng (int a = 12; float x=3.0)
thức từ các hằng và biến - Đảo dấu float, double, int, long,..
(Số nguyên hoặc thực)
-12, -12.34, - a, - x
- -a →12, --a →?
12 + -x → 9.0
• Toán tử số học + Cộng float, double, int, long,..

Trừ float, double, int, long,.. 12.0 - -3 →15.0


-
• Toán tử quan hệ Nhân float, double, int, long,.. 12 * 3.0 →36.0
*
12 * 3 → 36
• Toán tử logic Chia
(Số nguyên hoặc thực)
Nếu có ít nhất 1 toán 17.0/3.0 →5.666667
/ hạng là số thực 17/3.0 →5.666667
• Toán tử logic bit 17.0/3 →5.666667
Chia lấy nguyên Số nguyên int, long,..
• Toán tử gán / 17/3→5

% Chia lấy dư Số nguyên: int, long,.. 17%3 →2


73 74

73 74

Chương 2: Kiểu dữ liệu và biểu thức trong C Chương 2: Kiểu dữ liệu và biểu thức trong C
2.3 Các toán tử trong C 2.3 Các toán tử trong C

Các toán tử quan hệ Các toán tử logic


<, >, <=, >=, ==, != Sử dụng để xây dựng các biểu thức logic
• Dùng cho phép so sánh giá trị 2 toán hạng • Biểu thức logic có kết quả logic đúng
• Kết quả phép so sánh là một số nguyên → Trả về giá trị 1
1 nếu quan hệ có kết quả là đúng, • Biểu thức logic có kết quả logic sai
0 nếu quan hệ có kết quả sai → Trả về giá trị 0
Ví dụ: Các toán tử
6 > 4 → Trả về giá trị 1
Và logic: Op1 && Op2
6 < 4 → Trả về giá trị 0
int b =(x !=y); Hoặc logic: Op1 || Op2
Nếu x và y khác nhau, biểu thức đúng và b mang giá trị 1.
Ngược lại biểu thức sai và b mang giá trị 0
Phủ định logic: ! Op
5 * (12 > 6) → 5 Oprand: Toán hạng
75 76

75 76

19
Chương 2: Kiểu dữ liệu và biểu thức trong C Chương 2: Kiểu dữ liệu và biểu thức trong C
2.3 Các toán tử trong C 2.3 Các toán tử trong C

Các toán tử logic (tiếp) Toán tử logic bit


Và logic ( && ) : Toán tử bit được sử dụng với kiểu số nguyên
– Cho kết quả đúng (trả về giá trị 1) khi cả 2 toán Và nhị phân: Op1 & Op2
hạng đều đúng (khác 0)
– Ví dụ: 3 < 5 && 4 < 6 →1; 3 < 5 && 5 > 6 → 0 Hoặc nhị phân : Op1 | Op2
Hoặc logic ( || ): Hoặc có loại trừ nhị phân: Op1 ^ Op2
– Cho kết quả sai (trả về giá trị 0) chỉ khi cả 2 toán Đảo bít nhị phân : ~ Op
hạng đều sai (bằng 0)
– Ví dụ: 4 || 5 < 3 → 1; 5 < 5 || 2 > 6 → 0 Oprand: Toán hạng
Phủ định logic ( ! ): Dịch trái: Op << n (nhân với 2n)
– Cho kết quả đúng (1) hoặc sai (0) khi toán hạng Dịch phải: Op >> n (Chia với 2n)
là sai (0) hoặc đúng (khác 0)
– Ví dụ: ! 3 → 0; !(2 > 3) → 1; Op là giá trị được dịch, n là số bit dịch
77 78

77 78

Chương 2: Kiểu dữ liệu và biểu thức trong C Chương 2: Kiểu dữ liệu và biểu thức trong C
2.3 Các toán tử trong C 2.3 Các toán tử trong C

Toán tử logic bit (tiếp) Toán tử logic bit (tiếp)


char Op1 = 83, Op2 = -38, Op = 3; char Op1 = 83, Op2 = -38, Op = 3;

char r = Op1 & Op2; char r = Op1 | Op2; char r = Op1 >> Op;
01010011 01010011 01010011
11011010 11011010 r = 0 0 0 0 1 0 1 0 → (10)
r = 0 1 0 1 0 0 1 0 → (82) r = 1 1 0 1 1 0 1 1 → (-37) char r = Op2 >> Op; unsigned char Op =218;
11011010 unsigned char r =Op >> 3;
char r = Op1 ^ Op2; char r = ~ Op2; r =1 1 1 1 1 0 1 1 → (-5) 11011010
01010011 11011010 r =0 0 0 1 1 0 1 1 → (27)
11011010 r = 0 0 1 0 0 1 0 1 → (37)
r = 1 0 0 0 1 0 0 1 → (-119) char r = Op2 << 2;
r = 0 1 1 0 1 0 0 0 →(104)
unsigned char r = Op1 | Op2; r = 1 1 0 1 1 0 1 1 → 219
79
(unsigned) int r = Op2<<2 →? 80

79 80

20
Chương 2: Kiểu dữ liệu và biểu thức trong C Chương 2: Kiểu dữ liệu và biểu thức trong C
2.3 Các toán tử trong C 2.3 Các toán tử trong C

Toán tử gán Toán tử gán


Biến = Biểu_thức; • Biểu thức gán là biểu thức nên cũng có giá trị.
– Giá trị của biểu thức gán bằng giá trị của
• Ký tự “=“ là toán tử gán
biểu_thức bên phải toán tử
– Biểu thức bên phải dấu bằng tược tính toán
– Có thể gán giá trị của biểu thức gán cho một
– Giá trị của biểu_thức được gán cho biến
biến khác
• Ví dụ:
– Có thể sử dụng như một biểu thức bình thường
int a, b, c;
a = 3; • Ví dụ:
b = a + 5; int a, b, c;
c = a * b; a = b = 2007;
c = (a = 20) * (b = 30);// c→600
81 82

81 82

Chương 2: Kiểu dữ liệu và biểu thức trong C


Chương 2: Kiểu dữ liệu và biểu thức trong C
2.3 Các toán tử trong C

Toán tử gán → Dạng kết hợp Nội dung chính


Var <op>= Exp  Var = Var <op> Exp
1. Các kiểu dữ liệu chuẩn trong C
Toán tử số học:
+= -= *= /= %=
Ví dụ: a *= b // a= a * b
2. Biểu thức trong C
Toán tử logic bit: 3. Các toán tử trong C
&= |= ^=
Ví dụ: x &= 0x3F // x = x & 0x3F
4. Một số toán tử đặc trưng
Toán tử dịch:
<<= >>=
Ví dụ: s <<= 4 // s = s << 4
83 84

83 84

21
Chương 2: Kiểu dữ liệu và biểu thức trong C Chương 2: Kiểu dữ liệu và biểu thức trong C
2.4 Một số toán tử đặc trưng 2.4 Một số toán tử đặc trưng

Các toán tử Tăng giảm tự động một đơn vị


++ Tăng tự động ++Var, Var++

• Tăng/giảm tự động một đơn vị -- Giảm tự động --Var, Var--


Variable: Biến
• Lấy địa chỉ • Tiền tố (hậu tố): biến được tăng(++)/giảm(--) trước
(sau) khi sử dụng để tính toán biểu thức
Ví dụ:
• Biểu thức điều kiện int a = 5, b, c, d, e;
b = a++; // b = 5 sau đó a = 6
• Toán tử phẩy c = ++a; // a = 7 rồi tới c = 7
d = a--; // d = 7 rồi tới a = 6
e = --a; // a = 5 sau đó e= 5
85 86

85 86

Chương 2: Kiểu dữ liệu và biểu thức trong C Chương 2: Kiểu dữ liệu và biểu thức trong C
2.4 Một số toán tử đặc trưng 2.4 Một số toán tử đặc trưng

Toán tử lấy địa chỉ Toán tử phỏng điều kiện (biểu thức điều kiện)
& Tên_biến exp1 ? exp 2 : exp3
Ký tự & là toán tử lấy địa chỉ biến expression: Biểu thức
• Biến thực chất là một vùng .
1
• Nếu exp1 ≠ 0 (giá trị đúng), biểu thức điều
nhớ của máy tính được đặt tên ..
.. kiện trả về giá trị của exp2
→ tên của biến . 157

• Mọi ô nhớ trên bộ nhớ máy a D6 158


• Nếu exp1 = 0 (giá trị sai) biểu thức điều kiện
tính đều được đánh địa chỉ. 07 159
trả về giá trị của exp3
→ Mọi biến đều có địa chỉ 160 Ví dụ:
Ví dụ: .
.
float x= 5.2, y = 3.8, z;
.
int a = 2006; z = (x < y) ? x : y;
→ z = 3.8 // z min{x, y}
&a → Địa chỉ của ô nhớ dùng
Kiểu địa chỉ?  if (x < y) z = x; else z = y;
chứa giá trị biến a 87 88

87 88

22
Chương 2: Kiểu dữ liệu và biểu thức trong C Chương 2: Kiểu dữ liệu và biểu thức trong C
2.4 Một số toán tử đặc trưng 2.4 Một số toán tử đặc trưng

Toán tử phẩy Chuyển kiểu


biểu_thức_1, biểu thức_2,.. (Kiểu) biểu thức
• Chuyển kiểu tự động
• Toán tử phẩy ( , ) cho phép sử dụng nhiều biểu
thức tại nơi chỉ cho phép viết một biểu thức – Chương trình dịch tự động chuyển đổi từ kiểu có
phạm vi biểu diễn thấp tới kiểu có phạm vi biểu
• Các biểu thức được tính toán từ trái qua phải
diễn cao
• Giá trị và kiểu của biểu thức là giá trị và kiểu của
char → int → long int → float →
biểu thức cuối cùng, bên phải
double → long double
Ví dụ:
if (i = 0, a !=b)…
• Ép kiểu
– Bằng câu lệnh tường minh trong chương trình
for(i = 0, j = 0; i < 100; i++, j++)….
– Được sử dụng khi muốn chuyển sang kiểu có
phạm vi biểu diễn thấp hơn
89 90

89 90

Chương 2: Kiểu dữ liệu và biểu thức trong C Chương 2: Kiểu dữ liệu và biểu thức trong C
2.4 Một số toán tử đặc trưng 2.4 Một số toán tử đặc trưng

Chuyển kiểu→Ví dụ Thứ tự ưu tiên các toán tử


#include <stdio.h> Mức Toán tử Chức năng Chiều
1 -> . [ ] () ++ hậu tố --hậu tố Lựa chọn, chỉ số… →
#include <conio.h> 2 ++ -- ~ ! + - * & () sizeof Toán tử 1 ngôi, ép kiểu,… 
Toán tử số học lớp nhân →
Chiều kết hợp với các toán hạng
void main(){ 3 * / %
4 + - Toán tử số học lớp cộng →
long L = 0xABCDEF; float f = 123.456;
5 >> << Dịch bit →
int i; L = 11259375; i = -12817(CDEF) 6 < <= > >= Toán tử quan hệ →
clrscr(); 7 == != Bằng, khác →
f = 123.456001; L = 123; i = 123
8 & AND nhị phân →
i = (int) L;
9 ^ XOR nhị phân →
printf(“\n L = %ld; i = %d(%X)”, L, i, i); 10 | OR nhị phân →
i = (int) f; L = (long) f; 11 && AND logic →
12 || OR logic →
printf(“\n f = %f; L = %ld; i = %d”, f, L, i);
13 ?: Toán tử phỏng điều kiện 
} 14 = *= += <<= &= ... Toán tử gán 
91 92

91 92

23
Chương 2: Kiểu dữ liệu và biểu thức trong C
Chương 2: Kiểu dữ liệu và biểu thức trong C
2.4 Một số toán tử đặc trưng

Thứ tự ưu tiên các toán tử Ví dụ


Nguyên tắc const int N=10; int a= 3, b=4, c;
• Biểu thức con trong ngoặc được tính toán trước float S= 0.0; c = a++ * ++b;
• Phép toán một ngôi đứng bên trái toán hạng được int b;
kết hợp với toán hạng đi liền nó. S = N/3 +1;
• Toán hạng đứng cạnh hai toán tử
a= ? b= ? c= ?
b=(S>4);
– Nếu hai toán tử có độ ưu tiên khác nhau thì toán tử nào
có độ ưu tiên cao hơn sẽ kết hợp với toán hạng
S= ? b = ?
– Nếu hai toán tử cùng độ ưu tiên thì dựa vào trật tự kết
hợp của các toán tử để xác định toán tử được kết hợp
với toán hạng.
Ví dụ int k ,num=30;
a < 10 && 2 * b < c  ( a < 10 ) && ( ( 2 * b ) < c ) k =num>5 ? (num <=10 ? 100 : 200): 500;
Chú ý: int x = 5, a = 5 * x++; → a = 25, x = 6 k=?
93 94

93 94

Chương 2: Kiểu dữ liệu và biểu thức trong C Chương 2: Kiểu dữ liệu và biểu thức trong C
Ví dụ Tóm tắt
const int N=10; int a= 3, b=4, c; • Kiểu dữ liệu
float S= 0.0; c = a++ * ++b; – Nguyên : char, unsigned char, int, long,
int b; unsigned int, unsigned long
S = N/3 +1; – Thực : float, double, long double
a=4 b= 5 c=15
b=(S>4); • Giá trị logic
– Đúng/TRUE : 1 (Khác 0)
S= 4 b = 0 – Sai/FALSE : 0
• Toán tử
– Một ngôi : + -; ++ --; ~ !; &; ();
int k ,num=30; – Hai ngôi : + - * / %; == != < <= > >=; << >>;
k =num>5 ? (num <=10 ? 100 : 200): 500; &, ^, |, && ||; = *= +=…
k=200 – 3 ngôi :?:
95 96

95 96

24
Phần 3: Lập trình C Chương 3: Vào ra dữ liệu
Nội dung chính Nội dung chính
• Chương 1: Tổng quan về ngôn ngữ C 1. Các hàm vào ra cơ bản:
• Chương 2: Kiểu dữ liệu và biểu thức trong C – printf()
• Chương 3: Vào ra dữ liệu – scanf()
• Chương 4: Cấu trúc điều khiển
2. Các hàm vào ra khác
• Chương 5: Mảng, con trỏ và xâu ký tự
– gets()
• Chương 6: Cấu trúc
• Chương 7: Hàm
– puts()
• Chương 8: Tệp dữ liệu – getch()
97 98

97 98

Chương 3: Vào/Ra dữ liệu Chương 3: Vào/Ra dữ liệu


3.1 Các hàm vào ra cơ bản 3.1 Các hàm vào ra cơ bản

Các hàm vào ra cơ bản Hàm đưa ra dữ liệu


• Đưa ra dữ liệu:
–printf()
• Nhập dữ liệu
–scanf()
• Cần nạp thư viện stdio.h
printf()
–khai báo tệp tiêu đề :
#include <stdio.h>

99 100

99 100

25
Chương 3: Vào/Ra dữ liệu Chương 3: Vào/Ra dữ liệu
3.1 Các hàm vào ra cơ bản → printf() 3.1 Các hàm vào ra cơ bản → printf()

Mục đích Cú pháp

• Hiển thị ra màn hình các loại dữ liệu cơ bản printf(xau_dinh_dang [, DS_tham_so]);
– Số nguyên, số thực, kí tự, xâu kí tự • Xau_dinh_dang: Là một xâu qui định cách thức
hiển thị dữ liệu ra màn hình máy tính.
• Tạo một số hiệu ứng hiển thị đặc biệt – Bao gồm các nhóm kí tự định dạng
– Xuống dòng, sang trang,… – Nhóm kí tự định dạng thứ k xác định quy cách
hiển thị tham số thứ k trong DS_tham_số
Cú pháp
• Số lượng tham số trong DS_tham_số bằng số lượng
printf(xau_dinh_dang [, DS_tham_so]); nhóm các kí tự định dạng trong xâu_định_dạng.
• DS_tham_so: Danh sách các biến/biểu thức sẽ
được hiển thị giá trị lên màn hình theo cách thức
được qui định trong xau_dinh_dang.
101 102

101 102

Chương 3: Vào/Ra dữ liệu Chương 3: Vào/Ra dữ liệu


3.1 Các hàm vào ra cơ bản → printf() 3.1 Các hàm vào ra cơ bản → printf()

Ví dụ Xâu định dạng

#include <stdio.h> • Các kí tự thông thường:


void main() – Được hiển thị ra màn hình.
{ int a = 5;
• Các kí tự điều khiển:
float x = 1.234;
– Dùng để tạo các hiệu ứng hiển thị đặc biệt như
printf(” Hien thi mot bieu thuc nguyen %d và xuống dòng (‘\n’)..
mot so thuc %f ”,2 * a, x);
} • Các nhóm kí tự định dạng:
– Xác định quy cách hiển thị các tham số trong
Kết quả: phần danh_sach_tham_so.
Hien thi mot bieu thuc nguyen 10 va mot so thuc 1.234000
103 104

103 104

26
Chương 3: Vào/Ra dữ liệu Chương 3: Vào/Ra dữ liệu
3.1 Các hàm vào ra cơ bản → printf() 3.1 Các hàm vào ra cơ bản → printf()

Nhóm ký tự định dạng Các ký tự định dạng


• Mỗi nhóm kí tự định dạng chỉ dùng cho một Ký tự Kiểu dữ liệu Kết quả
kiểu dữ liệu” %i, %d int, char Số thập phân
Ví dụ: %d dùng cho kiểu nguyên
%o int, char Số bát phân
%f dùng cho kiểu thực (không có 0 đằng trước)
• DS_tham_so phải phù hợp với các nhóm kí %x %X int, char Số hexa
tự định dạng trong xau_dinh_dang về: (chữ thường/chữ hoa)
– Số lượng; Nếu không phù hợp sẽ hiển %u unsigned int/char Số thập phân
– Thứ tự thị ra kết quả không như ý
– Kiểu dữ liệu; printf(” %d ” ,3.14); →-31457
C-Free →1374389535 !? 105 106

105 106

Chương 3: Vào/Ra dữ liệu Chương 3: Vào/Ra dữ liệu


3.1 Các hàm vào ra cơ bản → printf() 3.1 Các hàm vào ra cơ bản → printf()

Các ký tự định dạng Các ký tự định dạng


Ký tự Kiểu dữ liệu Kết quả Ký tự Kiểu dữ liệu Kết quả
%ld, %li long Số thập phân %f float/double Số thực dấu phẩy tĩnh

%lo long Số bát phân %e, %E float/double Số thực dấu phẩy động
(không có 0 đằng trước) %c int, char Kí tự đơn lẻ
%lx, %LX long Số hexa
(chữ thường/chữ hoa)
%s char [] Hiển thị xâu kí tự kết
thúc bởi ‘\0’
%lu unsigned long Số thập phân
%% Hiển thị kí tự %
Nhận xét:
Với kiểu long, thêm ký tự l ngay sau dấu %
107 108

107 108

27
Chương 3: Vào/Ra dữ liệu Chương 3: Vào/Ra dữ liệu
3.1 Các hàm vào ra cơ bản → printf() 3.1 Các hàm vào ra cơ bản → printf()

Độ rộng hiển thị → Số nguyên, Ký tự, Xâu ký tự Độ rộng hiển thị→Ví dụ

• Có dạng “%m”,
printf("\n%3d %15s %3c", 1, "nguyen van a", 'g');
– m là một giá trị nguyên, không âm.
printf("\n%3d %15s %3c", 2, "tran van b", 'k');
– m cho biết số chỗ trống dành cho hiển thị
biểu thức tương ứng
Ví dụ: 1 nguyen van a g
int a = 1234; 2 tran van b k
printf(“%5d”,a) → 1234
printf(“%5d”,34)→ 34
ký hiệu cho dấu trắng (space)
109 110

109 110

Chương 3: Vào/Ra dữ liệu Chương 3: Vào/Ra dữ liệu


3.1 Các hàm vào ra cơ bản → printf() 3.1 Các hàm vào ra cơ bản → printf()

Độ rộng hiển thị → Số thực Độ rộng hiển thị→ Chú ý


• Có dạng “%m.n”, • Nếu số chỗ cần để hiển thị dữ liệu lớn hơn
– m, n là 2 giá trị nguyên, không âm. được cung cấp trong định dạng  Tự động
– m cho biết kích thước để hiển thị số thực
cung cấp thêm chỗ mới để hiển thị đầy đủ,
– n cho biết kích thước dành cho phần thập
không cắt bớt nội dung của dữ liệu.
phân, nếu không đủ C sẽ làm tròn khi hiển thị
Ví dụ: Ví dụ:
printf("\n%f",17.346); → 17.346000 printf(“%2d”, 1234); → 1234
printf("\n%.2f",17.346); → 17.35 printf(“%6.3f”, 123.456); → 123.456
printf("\n%.2f",17.345); → 17.34 !? printf(“%12.6e”, 123.456); →1.234560e+02
printf("\n%8.2f",17.346); → 17.35 printf(“%12.3e”, 123.456); →1.235e+02
printf("\n%8.2f",17.344); → ??? C-Free →1.235e+002 112
111

111 112

28
Chương 3: Vào/Ra dữ liệu Chương 3: Vào/Ra dữ liệu
3.1 Các hàm vào ra cơ bản → printf() 3.1 Các hàm vào ra cơ bản

Căn lề trái - căn lề phải Hàm nhập dữ liệu

%-
• Khi hiển thị dữ liệu có sử dụng tham số độ
rộng, để căn lề trái cần thêm dấu trừ - vào
ngay sau dấu %:
– Ngầm định, căn lề phải
scanf()
Ví dụ:
printf("%-3d%-10s%-5.2f%-3c",5,"Hello",7.5, 'g')
→5Hello7.50g

113 114

113 114

Chương 3: Vào/Ra dữ liệu Chương 3: Vào/Ra dữ liệu


3.1 Các hàm vào ra cơ bản → scanf() 3.1 Các hàm vào ra cơ bản → scanf()

Mục đích Cú pháp


Dùng để nhập dữ liệu từ bàn phím scanf(xau_dinh_dang [, DS_dia_chi]);
• Ký tự đơn lẻ Xau_dinh_dang:
• Chuỗi ký tự • Gồm các ký tự được qui định cho từng loại
• Số nguyên dữ liệu được nhập vào.
– Ví dụ: dữ liệu định nhập kiểu nguyên thì xâu
– Thập phân, Bát phân, Hexa
định dạng là : %d
• Số thực DS_dia_chi:
– Dấu phẩy tĩnh; Dấu phẩy động • Bao gồm địa chỉ của các biến (toán tử &),
Cú pháp phân tách nhau bởi dấu phẩy (,)
scanf(xau_dinh_dang[,DS_dia_chi]); • Phải phù hợp với các kí tự định dạng trong
115
xau_dinh_dang về số lượng, kiểu, thứ tự 116

115 116

29
Chương 3: Vào/Ra dữ liệu Chương 3: Vào/Ra dữ liệu
3.1 Các hàm vào ra cơ bản → scanf() 3.1 Các hàm vào ra cơ bản → scanf()

Hoạt động Ghi chú


• Đọc các ký tự được gõ vào từ bàn phím Thông tin được gõ vào từ bàn phím, được lưu
ở vùng đệm trước khi được xử lý bởi hàm
• Căn cứ vào xâu định dạng, chuyển thông scanf()→Hàm scanf() đọc từ vùng đệm
tin đã nhập sang kiểu dữ liệu phù hợp #include <stdio.h>
• Gán những giá trị vừa nhập vào các biến int main(){
int a, b;
tương ứng trong DS_dia_chi
scanf("%d",&a);
Ví dụ: scanf("%d",&b);
int a; printf ("%d %d", a, b);
scanf(“%d”,&a); →1234_ → a = 1234 return 0;
}
117 118

117 118

Chương 3: Vào/Ra dữ liệu Chương 3: Vào/Ra dữ liệu


3.1 Các hàm vào ra cơ bản → scanf() 3.1 Các hàm vào ra cơ bản → scanf()

Các ký tự định dạng Các ký tự định dạng

Kí tự Khuôn dạng dữ liệu nhập Kí tự Chú thích

%c Đọc kí tự đơn lẻ %s Đọc xâu kí tự tới khi gặp dấu phân cách

%d Đọc số thập phân %f Đọc số thực dấu phẩy tĩnh (float)


%ld Đọc số nguyên kiểu long
%o Đọc số bát phân
%lf Đọc số thực dấu phẩy tĩnh (double)
%x Đọc số hexa
%e Đọc số thực dấu phẩy động
%u Đọc số thập phân không dấu %% Đọc ký tự %

119 120

119 120

30
Chương 3: Vào/Ra dữ liệu Chương 3: Vào/Ra dữ liệu
3.1 Các hàm vào ra cơ bản → scanf() 3.1 Các hàm vào ra cơ bản → scanf()

Ví dụ Ví dụ
#include <conio.h> printf(“\nNhap vao mot xau ki tu:”);
#include <stdio.h> fflush(stdin); scanf(“%s”,str);
void main(){
// khai bao bien // Hien thi du lieu vua nhap vao
int a; float x; printf(“\nNhung du lieu vua nhap vao”);
char ch; char str[30]; printf(“\nSo nguyen : %d”,a);
// Nhap du lieu printf(“\nSo thuc : %5.2f”,x);
printf(“Nhap vao mot so nguyen:”); scanf(“%d”,&a); printf(“\nKy tu : %c”,ch);
printf(“\nNhap vao mot so thuc:”); scanf(“%f”,&x); printf(“\nXau ky tu : %s”,str);
printf(“\n Nhap vao mot ki tu:”); getch();
}
fflush(stdin); scanf(“%c”,&ch);
121 122

121 122

Chương 3: Vào/Ra dữ liệu Chương 3: Vào/Ra dữ liệu


3.1 Các hàm vào ra cơ bản → scanf() 3.1 Các hàm vào ra cơ bản → scanf()

Ví dụ→Kết quả thực hiện Các quy tắc cần lưu ý


Khi đọc số
• Hàm scanf() quan niệm rằng mọi kí tự số,
dấu chấm (‘.’) đều là kí tự hợp lệ.
– Số thực dấu phẩy động, chấp nhận ký tự e/E
• Khi gặp các dấu phân cách như tab, xuống
dòng hay dấu cách (space bar), scanf() sẽ
hiểu là kết thúc nhập dữ liệu cho một số

123 124

123 124

31
Chương 3: Vào/Ra dữ liệu Chương 3: Vào/Ra dữ liệu
3.1 Các hàm vào ra cơ bản → scanf() 3.1 Các hàm vào ra cơ bản → scanf()

Các quy tắc cần lưu ý Ví dụ: Đọc 2 số nguyên, đưa ra tổng, hiệu, tích…
Khi đọc kí tự #include <stdio.h>
int main(){
Hàm scanf() cho rằng mọi kí tự có trong bộ đệm int A, B;
của thiết bị vào chuẩn đều là hợp lệ, kể cả các kí printf("Nhap vao 2 so nguyen : "); scanf("%d %d",&A,&B);
tự tab, xuống dòng hay dấu cách printf("\n");
Khi đọc xâu kí tự: printf("Tong %d + %d = %d \n", A, B, A + B);
printf("Hieu %d - %d = %d\n", A, B, A - B);
Hàm scanf() nếu gặp các kí tự dấu trắng, dấu tab
printf("Tich %d x %d = %d\n", A, B, A * B);
hay dấu xuống dòng thì nó sẽ hiểu là kết thúc
printf("Thuong %d / %d = %.3f\n", A, B, (float)A / B);
nhập dữ liệu cho một xâu kí tự. printf("Chia nguyen %d / %d = %d\n", A, B, A / B);
Ghi chú: printf("Chia du %d %% %d = %d\n", A, B, A % B);
Trước khi nhập dữ liệu kí tự hay xâu kí tự nên printf("\n");
dùng lệnh fflush(stdin) để xóa bộ đệm. return 0;
125 } 126

125 126

Chương 3: Vào/Ra dữ liệu Chương 3: Vào/Ra dữ liệu


3.1 Các hàm vào ra cơ bản → scanf() 3.1 Các hàm vào ra cơ bản → scanf()

Ví dụ: Đọc 2 số nguyên, đưa ra tổng, hiệu, tích… Bài tập


1. Viết chương trình nhập vào từ bàn phím chiều
dài 3 cạnh của một tam giác, rồi đưa ra diện
tích và các đường cao của tam giác
2. Nhập vào từ bàn phím tọa độ 3 điểm A,B,C rồi
đưa ra độ dài các cạnh của tam giác ABC và
của đường trung tuyến AM
3. Cho hàm số: f ( x ) = x 7 + 53 x 5 + 3 x 3 + 2 + 12
Viết chương trình nhập vào 3 số thực a,b,c và đưa ra
trung bình cộng của f(a),f(b),f(c)
4. Nhập x vào từ bàn phím và tính giá trị của biểu
thức A = cos3a + 5 2 x 3 + x + 1 trongđó a = 2 x +  và b = ln(e x+1.23 + 1)
2
log7 (3 x + 2.14b)
127 128

127 128

32
Chương 3: Vào/Ra dữ liệu Chương 3: Vào/Ra dữ liệu
3.1 Các hàm vào ra cơ bản → scanf() 3.1 Các hàm vào ra cơ bản → scanf()

Ví dụ: Đọc tọa độ 3 điểm A,B,C và đưa ra d/tích ABC Ví dụ: Đọc tọa độ 3 điểm A,B,C và đưa ra d/tích ABC
#include <stdio.h>
#include <math.h>
int main(){
float Ax,Ay, Bx, By, Cx, Cy, AB, BC, CA,p;
printf("Nhap vao toa do diem A : "); scanf("%f %f",&Ax,&Ay);
printf("Nhap vao toa do diem B : "); scanf("%f %f",&Bx,&By);
printf("Nhap vao toa do diem C : "); scanf("%f %f",&Cx,&Cy);
//Tinh do dai cac canh cua tam giac
AB = sqrt((Ax-Bx)*(Ax-Bx)+(Ay-By)*(Ay-By));
BC = sqrt((Bx-Cx)*(Bx-Cx)+(By-Cy)*(By-Cy));
CA = sqrt((Cx-Ax)*(Cx-Ax)+(Cy-Ay)*(Cy-Ay));
p = (AB +BC +CA)/2;
printf("Dien tich tam giac ABC la: %f",sqrt(p*(p-AB)*(p-BC)*(p-CA)));
printf("\n");
return 0;
} 129 130

129 130

Chương 3: Vào ra dữ liệu


Chương 3: Vào/Ra dữ liệu
3.1 Các hàm vào ra cơ bản → scanf()

Bài tập tại lớp Nội dung chính


1. Viết chương trình nhập vào từ bàn phím bán 1. Các hàm vào ra cơ bản:
kính một đường tròn và đưa ra màn hình diện
tích và chu vi đường tròn – printf()
2. Viết chương trình nhập vào từ bàn phím một giá – scanf()
trị thực. Hãy đưa ra diện tích của các hình tròn,
vuông, tam giác đều có chu vi bằng giá trị vừa
nhập.
2. Các hàm vào ra khác
Ghi chú: – gets() Cần nạp thư viện
1. Giả thiết  = 3.1416. Cần khai báo hằng PI trong conio.h
chương trình. – puts()
#include <conio.h>
2.  là hằng số được khai báo trong tệp tiêu đề math.h
và có tên là M_PI
– getch()
131 132

131 132

33
Chương 3: Vào/Ra dữ liệu Chương 3: Vào/Ra dữ liệu
3.2 Các hàm vào ra khác 3.2 Các hàm vào ra khác

gets() puts()
• Mục đích: • Mục đích:
– Dùng để nhập vào từ bàn phím một xâu – Hiển thị ra màn hình nội dung xâu_kí_tự
kí tự bao gồm cả dấu cách, điều mà và sau đó đưa con trỏ xuống dòng mới
hàm scanf() không làm được.
• Cú pháp:
• Cú pháp : puts(xâu_kí_tự);
gets (xâu_kí_tự);
• Ví dụ:
• Ví dụ:
puts(“Nhap vao xau ki tu:”);
char str [40];
printf(“Nhap vao mot xau ki tu:”); Tương đương với lệnh:
fflush(stdin); printf(“%s\n”,“Nhap vao xau ki tu:“).
gets(str); 133 134

133 134

Chương 3: Vào/Ra dữ liệu Chương 3: Vào/Ra dữ liệu


3.2 Các hàm vào ra khác 3.2 Các hàm vào ra khác

getch() Ví dụ
• Mục đích #include <conio.h>
#include <stdio.h>
– Đợi đọc một ký tự bàn phím
void main(){
– Thường dùng để chờ người sử dụng char ten[30], lop[10]; //Kieu chuoi, mang ky tu
ấn một phím bất kì trước khi kết thúc puts("Hay cho biet ten ban : ");
chương trình. fflush(stdin); gets(ten);
puts("Hay cho biet lop ban hoc : ");
• Cú pháp fflush(stdin); gets(lop);
getch(); printf("\nChao ban %s, sinh viên lop %s\n",ten,lop);
puts("Chuc ban thi qua mon Tin Hoc Dai Cuong");
getch();
135
} 136

135 136

34
Chương 3: Vào ra dữ liệu
Chương 3: Vào/Ra dữ liệu
3.2 Các hàm vào ra khác

Ví dụ → Kết quả thực hiện Tóm tắt


• Các hàm cơ bản (stdio.h)
– printf()/ scanf ()
– Xâu định dạng:
%[flags][width][.precision][l][t]
• flags (+/-,#): Xác định sự căn lề
• l (l/L): Biến ở dạng long
• t (d/i/o/u/x/X/f/e/E/g/G/c/s/%): kiểu hiện thị
• Các hàm khác (conio.h)
– puts() / gets() / getch()
• Tìm hiểu thêm
– fprintf() / fscanf()  Vào/ra từ file
137
– sprintf(f) / sscanf()  Vào ra từ xâu ký tự 138

137 138

Phần 3: Lập trình C Chương 4: Cấu trúc điều khiển


Nội dung chính Nội dung chính
• Chương 1: Tổng quan về ngôn ngữ C 1. Cấu trúc lệnh khối
2. Cấu trúc rẽ nhánh
• Chương 2: Kiểu dữ liệu và biểu thức trong C
– Cấu trúc if, if … else
• Chương 3: Vào ra dữ liệu – Cấu trúc lựa chọn switch
• Chương 4: Cấu trúc điều khiển 3. Cấu trúc lặp
– Vòng lặp for
• Chương 5: Mảng, con trỏ và xâu ký tự
– Vòng lặp while và do while
• Chương 6: Cấu trúc 4. Các lệnh thay đổi cấu trúc lập trình
• Chương 7: Hàm – Câu lệnh continue
• Chương 8: Tệp dữ liệu – Câu lệnh break
139 140

139 140

35
Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.1 Cấu trúc lệnh khối 4.1 Cấu trúc lệnh khối

Lệnh đơn >< Lệnh ghép Cấu trúc lồng nhau


• Lệnh đơn: • Trong lệnh ghép chứa lệnh ghép khác
– Là biểu thức theo sau bởi dấu ‘;’ – Sự lồng nhau không hạn chế
– Ví du: x= 0; i++; printf(“Hello”); {//Khai báo đối tượng cục bộ trong khối
• Lệnh ghép (khối lệnh) lenh;
– Là tập hợp các câu lệnh (đơn và ghép) được {//Khai báo đối tượng cục bộ trong khối
đặt trong cặp ngoặc nhọn { } lenh;
– C cho phép khai báo biến trong một khối lệnh ...
• Phần khai báo phải nằm trước các câu lệnh } Nếu các đối tượng được
– Chú ý: … khai báo trùng tên nhau ?
• Lệnh ghép có thể đặt tại bất cứ chỗ nào mà cú pháp }
cho phép đặt 1 câu lệnh đơn
• Không đặt dấu ‘;’ sau một lệnh khối 141 142

141 142

Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.1 Cấu trúc lệnh khối 4.1 Cấu trúc lệnh khối

Ví dụ Ví dụ→Kết quả thực hiện


#include <conio.h>
#include <stdio.h>
void main(){ // ham main() cung la mot khoi lenh
int c = 10, d= 20;
printf(“ Bien ngoai khoi c = %d; d=%d ”,c,d);
{ int c = 10;
printf(“\n Bien trong khoi c = %d; d=%d”,c,d);
printf(“\n Gia tri cua cac bien duoc them 10 don vi”);
c = c + 10; d= d + 10;
printf(“\n Bien trong khoi c = %d; d=%d”,c,d);
}
printf(“\n Bien ra ngoai khoi c = %d; d=%d”,c,d); Biến địa phương / Biến toàn cục
getch();
} // ket thuc khoi lenh cua ham main() 143 144

143 144

36
Chương 4: Cấu trúc điều khiển
Chương 4: Cấu trúc điều khiển
4.2 Cấu trúc rẽ nhánh

Nội dung chính Cấu trúc if …


1. Cấu trúc lệnh khối
2. Cấu trúc rẽ nhánh Đúng Sai
Biểu thức điều kiện
– Cấu trúc if, if … else
– Cấu trúc lựa chọn switch Câu lệnh

3. Cấu trúc lặp


– Vòng lặp for Câu lệnh tiếp
– Vòng lặp while và do while
4. Các lệnh thay đổi cấu trúc lập trình if (Biểu thức điều kiện)
if (n % 2 == 0)
– Câu lệnh continue Câu lệnh; printf(“so chan”);
– Câu lệnh break Câu lệnh kế tiếp;
145 146

145 146

Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.2 Cấu trúc rẽ nhánh 4.2 Cấu trúc rẽ nhánh

Cấu trúc if….else…. Lưu ý


Đúng Sai Biểu thức điều kiện:
Biểu thức điều kiện
• Là biểu thức trả về giá trị logic đúng/sai
Câu lệnh 1 Câu lệnh 2 • Giá trị logic đúng/True : khác 0
• Giá trị logic sai/False: bằng 0
Câu lệnh tiếp
Ví dụ
if (Biểu thức điều kiện) if (x > y) if (2+5) printf(“Hello world! ”);→Chấp nhận
Câu lệnh 1; z = x;
Câu lệnh:
else else
Có thể là một lệnh khối ( Đặt trong cặp { } )
Câu lệnh 2; z = y;
Câu lệnh kế tiếp; printf(“max: %d”, z);
147 148

147 148

37
Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.2 Cấu trúc rẽ nhánh 4.2 Cấu trúc rẽ nhánh

Ví dụ: So sánh 2 số thực được nhập vào Ví dụ: So sánh 2 số thực được nhập vào
#include <conio.h>
#include <stdio.h>
void main()
{
float a, b; float max; // khai bao bien
printf(“ Nhap gia tri a va b: “);
scanf(“%f %f”,&a,&b);
if(a < b)
max = b;
if(a < b)
else
max = a; max = b;
printf(“\nSo lon nhat trong 2 so %.4f va %.4f la %.4f “,a,b,max);
max = a > b ? a : b;
else
getch();
} //ket thuc ham main()
max = a;
149 150

149 150

Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.2 Cấu trúc rẽ nhánh 4.2 Cấu trúc rẽ nhánh

Ví dụ: Giải phương trình ax + b = 0 Giải phương trình ax + b = 0 → Thực hiện


#include <stdio.h>
#include <conio.h>
void main()
{ float a, b;
printf("\nGiai phuong trinh bac nhat ax + b = 0");
printf("\nCho biet he so a b : "); scanf("%f%f", &a, &b);
if (a==0)
if (b!=0)
printf("Phuong trinh vo nghiem");
else
printf("Phuong trinh vo so nghiem");
else
printf("Dap so cua phuong trinh tren = %f", -b/a);
getch();
} //ket thuc ham main()
151 152

151 152

38
Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.2 Cấu trúc rẽ nhánh 4.2 Cấu trúc rẽ nhánh

Ví dụ: Nhập x và tính hàm Cấu trúc if / if… else lồng nhau
#include <stdio.h>  x 2 + sin 4 2x + 1 khi x  3
#include <math.h> 

Cấu trúc if.. và if …else có thể lồng nhau
f ( x) = 5 khi x = 3
void main()  – Khi đó else sẽ tương ứng với if (phía trên,
{ 
 x − 3 + log ( x 2
− 3) khi x3
10
chưa có else) gần nhất
float x, fx;
printf(“\nNhap x: “); scanf(“%f”,&x); if (đ/k_1)
if (đ/k_1)
if(x < 3)
fx = x*x+pow(sin(2*M_PI*x),4)+1; if (đ/k_2) { if (đ/k_2)
else
if (x==3) lệnh_1; lệnh_1;
fx = 5; }
else
else
fx = sqrt(x-3) +log10(x*x-3); lệnh_2; else
printf(“\n Ket quả: %.4f“,fx);
}
lệnh_2;
153 154

153 154

Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.2 Cấu trúc rẽ nhánh 4.2 Cấu trúc rẽ nhánh

Cấu trúc if / if… else lồng nhau →Ví dụ Cấu trúc lựa chọn switch
int a, b, c = 10;
switch (bieu_thuc)
if (a==0) a ≠ 0, b=? → c = 10 {
if (b == 0)
c = 20; a=0, b=0 →c = 20 case gia_tri_1: lenh_1; [break];
else case gia_tri_2: lenh_2; [break];
c = 30; a=0, b ≠ 0 →c = 30

if (a==0){ a ≠ 0, b=? → c = 30 [default: lenh_n+1; [break];]
if (b == 0)
c = 20; a=0, b=0 →c = 20 }
}else Câu_lệnh_tiếp
c = 30; a=0, b ≠ 0 → c = 10
155 156

155 156

39
Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.2 Cấu trúc rẽ nhánh 4.2 Cấu trúc rẽ nhánh

Cấu trúc lựa chọn switch Cấu trúc lựa chọn switch

Tính g/trị
Biểu thức Cơ chế hoạt động
Sai Sai Sai • Tính giá trị của biểu_thức,
g/trị b/t=G/trị 1 g/trị b/t=G/trị 2  default ?

Đúng Đúng Đúng


• So sánh giá trị của biểu_thức với các
giá_trị_k (với k = 1, 2, … n) nằm sau các
Lệnh_1 Lệnh_2 Lệnh_n+1
từ khóa case
 break ?
Sai
 break ?
Sai
 break ?
Sai • Xảy ra 2 khả năng
Đúng Đúng Đúng

Câu_lệnh_tiếp
157 158

157 158

Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.2 Cấu trúc rẽ nhánh 4.2 Cấu trúc rẽ nhánh

Cấu trúc lựa chọn switch→cơ chế hoạt động Cấu trúc lựa chọn switch→cơ chế hoạt động
• Tồn tại giá_trị_i bằng giá trị biểu thức. • Không tồn tại giá_trị_i (i = 1, 2, …n) nào
• Thực hiện lệnh_i bằng giá trị biểu thức
• Nếu tồn tại lệnh break, • Nếu có nhãn default:
• Nhảy tới tiếp tục thực hiện Câu_lệnh_tiếp nằm
• Chương trình sẽ thực hiện lệnh_n+1
sau cấu trúc switch
• Thực hiện Câu_lệnh_tiếp nằm ngay sau cấu trúc
• Nếu không tồn tại lệnh break switch.
• Thực hiện các lệnh sau lệnh_i cho tới khi gặp
• Nếu không có nhãn default:
break hoặc tới khi thoát khỏi cấu trúc switch
• Chương trình chuyển sang thực hiện lệnh tiếp theo
• Thực hiện Câu_lệnh_tiếp
nằm ngay sau cấu trúc switch: Câu_Lệnh_tiếp

159 160

159 160

40
Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.2 Cấu trúc rẽ nhánh 4.2 Cấu trúc rẽ nhánh

Cấu trúc lựa chọn switch→Ví dụ 1 Cấu trúc lựa chọn switch→Ví dụ 1
#include <stdio.h>
void main(){
Lập trình đọc từ bàn phím một số int N;
printf(“\nNhap mot gia tri so nguyen khong am: “); scanf(“%d”,&N);
nguyên 1N 10 và đưa ra từ tiếng switch(N) {
case 1: printf(“ %d -> One \n”,N); break;
Anh tương ứng case 2: printf(“%d -> Two \n”,N); break;
case 3: printf(“%d -> Three \n”,N); break;
case 4: printf(“%d -> Four \n”,N); break;
case 5: printf(“%d -> Five \n”,N); break;
case 6: printf(“%d -> Six \n”,N); break;
case 7: printf(“%d -> Seven \n”,N); break;
case 8: printf(“%d -> Eight \n”,N); break;
case 9: printf(“%d -> Nine \n”,N); break;
case 10: printf(“%d -> Ten \n”,N); break;
default : printf(“Khong thoa man dieu kien [1..10] \n”);
}
161 } 162

161 162

Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.2 Cấu trúc rẽ nhánh 4.2 Cấu trúc rẽ nhánh

Cấu trúc lựa chọn switch→ Thực hiện Cấu trúc lựa chọn switch→Ví dụ 2

Nhập vào số nguyên không âm, đưa


ra ngày trong tuần tương ứng (theo
số dư khi chia cho 7).

163 164

163 164

41
Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.2 Cấu trúc rẽ nhánh 4.2 Cấu trúc rẽ nhánh

Cấu trúc lựa chọn switch→Ví dụ 2 Cấu trúc lựa chọn switch →Thực hiện
#include <conio.h>
#include <stdio.h>
void main(){
int a;
printf(“\nNhap mot gia tri so nguyen khong am: “); scanf(“%d”,&a);
switch(a % 7) {
case 0: printf(“ Chu nhat”); break;
case 1: printf(“ Thu Hai”); break;
case 2: printf(“ Thu Ba”); break;
case 3: printf(“ Thu Tu”); break;
case 4: printf(“ Thu Nam”); break;
case 5: printf(“ Thu Sau”); break;
case 6: printf(“ Thu Bay”); break;
}
getch();
}
165 166

165 166

Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.2 Cấu trúc rẽ nhánh 4.2 Cấu trúc rẽ nhánh

Cấu trúc lựa chọn switch Cấu trúc lựa chọn switch→ Ví dụ
Có thể sử dụng đặc điểm Không có lệnh #include <conio.h>
#include <stdio.h>
break chương trình sẽ tự động chuyển void main () {
xuống thực hiên các câu lệnh tiếp sau để int thang; clrscr();
viết chung mã lệnh cho các trường hợp printf("\nNhap vao thang trong nam "); sanf("%d",&thang);
switch(thang) {
khác nhau nhưng được xử lý như nhau case 1:
case 3:
Ví dụ:Trong một năm các tháng có 30 ngày là 4, 6, case 5:
9, 11 còn các tháng có 31 ngày là 1, 3, 5, 7, 8, 10, case 7:
12. Riêng tháng hai có thể có 28 hoặc 29 ngày. case 8:
Hãy viết chương trình nhập vào 1 tháng, sau đó case 10:
case 12: printf("\n Thang %d co 31 ngay ",thang);
đưa ra kết luận tháng đó có bao nhiêu ngày
break;
167 168

167 168

42
Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.2 Cấu trúc rẽ nhánh 4.2 Cấu trúc rẽ nhánh

Cấu trúc lựa chọn switch Cấu trúc lựa chọn switch→Lưu ý
case 4:
case 6:
• Giá trị của biểu thức trong cấu trúc
case 9: switch phải là số nguyên (kiểu đếm được)
case 11: printf("\n Thang %d co 30 ngay ",thang); – Phải có kiểu dữ liệu là char, int, long
break;
case 2: printf ("\ Thang 2 co 28 hoac 29 ngay"); • Các giá trị sau từ khóa case (gia_tri_1,
break; gia_tri_2,.. ) cũng phải là số nguyên
default : printf("\n Khong co thang %d", thang);
break;
} Điều kiện trong cấu trúc if / if..else cho phép
getch(); làm việc với các kiểu dữ liệu khác số
}
nguyên
169 170

169 170

Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.2 Cấu trúc rẽ nhánh 4.2 Cấu trúc rẽ nhánh

Các ví dụ Ví dụ 1: Tính cước taxi


#include <stdio.h>
1. Viết chương trình tính cước Taxi theo công #include <math.h> //Để sử dụng hàm toán học ceil
thức: void main() {
• 1 km đầu tiên có cước là 10000đ, unsigned long sotien;
• 30 km tiếp theo có giá là 8000đ/1km float sokm;
printf("\nBan hay cho biet so km da di duoc : ");
• Các km sau đó có giá là 6000đ/1km. scanf("%f", &sokm);
if (sokm <= 1.0)
2. Viết chương trình giải phương trình bậc hai
sotien = 10000;
ax2 + bx + c = 0 else
if (sokm <= 31.0)
3. Viết chương trình giải hệ phương trình bậc sotien = 10000 + (ceil(sokm) - 1.0 ) * 8000;
nhất a1 x + b1 y = c1 else
 sotien = 250000 + (ceil(sokm) - 31) * 6000;
a2 x + b2 y = c2 printf("\nSo tien can tra = %lud", sotien);
171 } 172

171 172

43
Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.2 Cấu trúc rẽ nhánh 4.2 Cấu trúc rẽ nhánh

Ví dụ 1 → Thực hiện chương trình Ví dụ 2: Giải phương trình bậc 2


#include <stdio.h>
#include <math.h> //Để sử dụng hàm toán học sqrt
void main(){
float a, b, c, delta;
printf(“\n\nNhap he so a b c : "); scanf("%f%f%f", &a, &b, &c);
delta = b * b - 4 * a * c;
if( a==0) printf(“P/trinh suy bien thanh p/trinh bac 1 %fx+%f=0“,b,c);
else if (delta < 0) printf("Phuong trinh vo nghiem");
else if (delta == 0)
printf("Phuong trinh co nghiem kep x1 = x2 = %f", -b/(2*a));
else
printf(“Phuong trinh co hai nghiem phan biet\n x1=%f \n x2=%f",
sotien= sokm <=1.0 ? 10000 : sokm <= 31 ? 10000 + (ceil(sokm) - (-b + sqrt(delta))/(2*a), (-b - sqrt(delta))/(2*a) );
1.0 ) * 8000 : 250000+(ceil(sokm) - 31) * 6000;
}
173 174

173 174

Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.2 Cấu trúc rẽ nhánh 4.2 Cấu trúc rẽ nhánh

Ví dụ 2→ Thực hiện chương trình Ví dụ 3: Giải hệ phương trình


#include <stdio.h>
void main() {
float a1,b1,c1,a2,b2,c2,x,y,dx,dy,d;
printf(“\n\nNhap cac so:\n");
printf("a1,b1,c1=");scanf("%f%f%f",&a1,&b1,&c1);
printf("a2,b2,c2=");scanf("%f%f%f",&a2,&b2,&c2);
d = a1 * b2 - a2 * b1;
dx = c1 * b2 - c2 * b1;
dy = a1 * c2 - a2 * c1;
if (d != 0) {
x = dx/d; y = dy/d;
printf("He PT co nghiem x=%f, y=%f\n",x,y);
}else
if (dx==0) printf("He PT co vo so nghiem!\n");
else printf("He phuong trinh vo nghiem!");
175 } 176

175 176

44
Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.2 Cấu trúc rẽ nhánh 4.2 Cấu trúc rẽ nhánh

Ví dụ 3 → Thực hiện chương trình Bài tập


1. Viết chương trình nhập vào một ký tự hệ hexa và
đưa ra giá trị hệ 10 tương ứng
2. Lập trình đọc tọa độ 4 điểm A,B,C,M rồi kiểm tra
xem điểm M nằm trong, nằm trên cạnh hay nằm
ngoài tam giác ABC.
3. Lập trình đọc vào từ bàn phím 2 giá trị a, b rồi
tính y = 15 x2+x+7.2 trong đó
a +b
 3 nê'u a  b

x = 1.5172 nê' u a = b
 a −b
 2 nê' u a  b
 a + b 2
177 178

177 178

Chương 4: Cấu trúc điều khiển


Chương 4: Cấu trúc điều khiển
4.3 Cấu trúc lặp

Nội dung chính Các cấu trúc lặp


1. Cấu trúc lệnh khối
2. Cấu trúc rẽ nhánh
– Cấu trúc if, if … else • Vòng lặp for
– Cấu trúc lựa chọn switch
3. Cấu trúc lặp • Vòng lặp while
– Vòng lặp for
– Vòng lặp while và do while • Vòng lặp do while
4. Các lệnh thay đổi cấu trúc lập trình
– Câu lệnh continue
– Câu lệnh break
179 180

179 180

45
Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.3 Cấu trúc lặp 4.3 Cấu trúc lặp

Mục đích và cú pháp

Dùng để lặp công việc một số chính xác lần


đã định trước dựa vào sự biến thiên của
biến điều khiển

for •
for([b.thuc_1];[b.thuc_2];[b.thuc_3]) Lệnh;

b.thuc_1: Khởi tạo giá trị ban đầu cho vòng lặp
• b.thuc_2: Điều kiện tiếp tục vòng lặp
• b.thuc_3: Thay đổi biến điều khiển của vòng lặp
• Lệnh: Có thể là lệnh đơn lệnh kép hoặc lệnh rỗng

181 182

181 182

Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.3 Cấu trúc lặp 4.3 Cấu trúc lặp

Sơ đồ cú pháp Sử dụng
int i;
for(i = 0; i < 100; i++) Câu_lệnh;
int i;
for(i = 0; i < 100; i+=2)Câu_lệnh;
int i;
for(i = 100; i > 0; i--) Câu_lệnh;

for(int i = 0; i < 100; i++) Lệnh;


for(int i = 100; i > 0; i--) Lệnh;
Turbo C++ 3.0, văn bản nguồn .cpp (c++)
183 184

183 184

46
Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.3 Cấu trúc lặp 4.3 Cấu trúc lặp

Ví dụ 1 : Đưa ra các số nguyên lẻ nhỏ hơn 100 Ví dụ 2 : Đưa ra các số nguyên lẻ nhỏ hơn 100
1. #include <stdio.h> 1. #include <stdio.h>
2. #include <conio.h> 2. #include <conio.h>
3. void main(){ 3. void main(){
4. int i; 4. int i;
5. for(i = 1;i<100;i++) { 5. for(i = 99;i > 0;i-=2) {
6. if(i%2 == 1) printf(“%5d”,i); 6. printf(“%5d”,i);
7. if((i+1)%20 ==0) printf(“\n”); 7. if( (i-1) % 20 == 0) printf(“\n”);
8. } 8. }
9. getch(); 9. getch();
10. } 10. }
185 186

185 186

Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.3 Cấu trúc lặp 4.3 Cấu trúc lặp

Ví dụ 3→ Nhập n và đưa ra n! Ví dụ 4 → Nhập n và tính tổng 1 +1/2+..+1/n


#include <stdio.h> #include <stdio.h>
#include <conio.h> #include <conio.h>
void main() void main()
{ {
long P = 1; float S = 0.0;
int n, i; int n, i;
printf(“Nhap n : “);scanf(“%d”,&n); printf(“Nhap n : “);scanf(“%d”,&n);
for(i = 1;i<=n;i++) for(i = 1;i <= n;i++)
P = P * i; S = S + (float)1/i; //S+=1.0/i;
printf(“Ket qua là %ld “,P); printf(“Ket qua là %7.4f “,S);
getch(); getch(); Nhap n : 10
} Nhap n : 6 }
Ket qua là 720 Ket qua là 2.9290
187 188

187 188

47
Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.3 Cấu trúc lặp 4.3 Cấu trúc lặp

Ví dụ 5→ Tìm số 3 chữ số thỏa mãn abc=a3+b3+c3 Ví dụ 5→ Tìm số 3 chữ số thỏa mãn abc=a3+b3+c3
#include <stdio.h> #include <stdio.h>
#include <conio.h> #include <conio.h>
void main()
void main()
{int i, a, b, c;
for(i = 100;i<1000;i++){
{ int a, b, c;
a = i / 100; 153 for(a = 1;a<=9;a++)
b = i % 100 / 10; 370 for(b = 0;b<=9;b++)
c = i % 100 % 10; for(c = 0;c<=9;c++)
371
if(a*a*a+b*b*b+c*c*c == i) if(a*a*a+b*b*b+c*c*c==100*a+10*b+c)
printf(“%d \n”,i);
407
printf(“%d \n”,100*a+10*b+c);
}//for
getch();
getch();
} 189
} 190

189 190

Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.3 Cấu trúc lặp 4.3 Cấu trúc lặp

Chú ý Chú ý
1. Biểu thức khởi tạo
Không nhất thiết phải có đầy đủ các Hello world
char c; int i=0;
thành phần trong vòng lặp for for( ; (c=getchar())! = '\n’ ; i++)
Hello world
So ky tu: 11
putchar(c);
printf(“\nSo ky tu: %d”,i);
int getchar(): đọc ký tự từ vùng đệm bàn 2. Biểu thức điều khiển
phím. Nếu vùng đệm rỗng, đợi người dùng for(i=0 ; ; c=getchar(), i++) Hello world
gõ dãy ký tự (cho tới khi ấn phím Enter), sẽ if(c==‘\n’) break;
So ky tu: 12
trả về ký tự đầu printf(“\nSo ky tu: %d”,i);
3. Thân vòng lặp
putchar(int c): đưa ký tự ra màn hình for(i=0 ; getchar() != ‘\n’, i++); Hello world

191
printf(“\nSo ky tu: %d”,i); So ky tu: 11
192

191 192

48
Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.3 Cấu trúc lặp 4.3 Cấu trúc lặp

Mục đích & Cú pháp


Dùng để thực hiện lặp đi lặp lại một công việc
nào đó với số lần lặp không xác định.
Cú pháp:
while while(bieu_thuc_dieu_kien)
lenh;
• Chương trình kiểm tra điều kiện trước khi lặp
– Giá trị của biểu thức điều kiện là đúng  thực hiện lệnh
• Các lenh của vòng lặp có thể không được thực hiện
lần nào Biểu_thức_điều_kiện sai ngay từ đầu
193 • Biểu_thức_điều_kiện luôn đúng  lặp vô hạn lần 194

193 194

Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.3 Cấu trúc lặp 4.3 Cấu trúc lặp

Sơ đồ cú pháp Nhập n và đưa tổng của n số nguyên đầu tiên


#include <stdio.h>
#include <conio.h>
Tính toán giá trị của void main(){
long S = 0;
Biểu thức điều kiên int n;
printf(“Nhap n : “);scanf(“%d”,&n);
Lệnh while (n > 0){
S = S + n; while (n> 0)
n = n – 1; S += n--;
Biểu thức != 0 }
Đúng printf(“Ket qua là %ld “,S);
getch();
Sai }

195 196

195 196

49
Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.3 Cấu trúc lặp 4.3 Cấu trúc lặp

Tìm số nguyên lớn nhất thỏa mãn 3n5-317n <5 Cho biết kết quả thực hiện chương trình
#include <stdio.h> #include <stdio.h>
#include <conio.h>
#include <conio.h>
void main()
#include <math.h> {
void main() n = 10 clrscr();
{ while (3*pow(n,5)-317*n >= 5) int i=3;
clrscr(); n--; while (i > 1){
int n=0; if(i % 2==0) i = i / 2;
while (3* pow(n,5) - 317*n < 5) n++; else i = i * 3 + 1;
printf("%4d",i);
printf("%4d",n-1);
}
getch(); getch(); 10 5 16 8 4 2 1
} n= 3 }
197 198

197 198

Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.3 Cấu trúc lặp 4.3 Cấu trúc lặp

Nhập chuỗi và đếm số nguyên âm, phụ âm, khoảng trắng


#include <stdio.h>
#include <conio.h>
void main()
{ int na, pa, kt; char c;
na = pa = kt = 0;
clrscr(); printf(“>”);
while( (c=getchar()) !='\n'){
switch(c){
do..while
case 'a': case ‘e': case ‘i': case ‘o': case ‘u‘ :
case ‘A': case‘E': case ‘I': case‘0': case ‘U‘ : na++; break;
case ' ': kt++; break;
default : pa++;
}
}
printf("Chuoi co :%d nguyen am :%d phu am va %d khoang trang",na,pa,kt);
} 199 200

199 200

50
Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.3 Cấu trúc lặp 4.3 Cấu trúc lặp

Mục đích & Cú pháp Sơ đồ cú pháp


• Dùng để thực hiện lặp đi lặp lại một công
việc nào đó với số lần lặp không xác định. Lệnh
• Cú pháp:
do{
Tính toán giá trị của
lenh;
Biểu thức điều kiên
}while(bieu_thuc_dieu_kien);
• Chương trình kiểm tra điều kiện sau khi lặp Đúng
Biểu thức != 0
• Các lenh được thực hiện ít nhất một lần
• Biểu thức luôn đúng, lặp vô hạn lần Sai
201 202

201 202

Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.3 Cấu trúc lặp 4.3 Cấu trúc lặp

Nhập n và đưa tổng của n số nguyên đầu tiên Ví dụ


#include <stdio.h> • Nhập vào điểm của một sinh viên, nếu
#include <conio.h>
void main(){ điểm đó không  [0, 10] thì thông báo cho
long S = 0; người dùng nhập lại.
int n;
printf(“Nhap n : “);scanf(“%d”,&n); • Thực hiện:
do { do – Nếu dùng lệnh if
S = S + n; S += n--; → Chỉ kiểm tra được 1 lần
n = n – 1; while (n> 0);
}while (n > 0); – Sử dụng for
printf(“Ket qua là %ld “,S); Chưa biết trước số lần lặp.
getch(); → Sử dụng vòng lặp không cần xác định trước
Nhap n : 96
} số lần lặp: while / do while
Ket qua là 4656
203 204

203 204

51
Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.3 Cấu trúc lặp 4.3 Cấu trúc lặp

Dùng vòng lặp while Dùng vòng lặp while → Kết quả
#include <stdio.h>
void main(){
float diem; clrscr();
printf(“Chuong trinh nhap diem sinh vien\n");
printf("Nhap diem (0<=diem<=10):"); scanf("%f",&diem);
while (diem < 0 || diem > 10) {
printf("\nBan nhap khong dung!\n");
printf("Ban hay nhap lai (0<=diem<=10):");
scanf("%f",&diem);
}
printf("\nDiem ban vua nhap la: %.2f“, diem);
}
205 206

205 206

Chương 4: Cấu trúc điều khiển


4.3 Cấu trúc lặp Ví dụ: Nhập số và kiểm tra số hoàn hảo
Dùng vòng lặp do…while 1. #include <stdio.h> fflush(): xóa vùng đệm bàn phím
2. #include <ctype.h>
#include <stdio.h> 3. #include <conio.h> toupper(): chuyển sang chữ hoa
4. void main(){
void main() { 5. long int n, tong, i; getche(): Đọc ký tự tự vùng đệm & hiện
float diem; clrscr();
6. char ch; thị lên màn hình (getch() thì không)
7. do {
printf(“Chuong trinh nhap diem sinh vien\n"); 8.
9.
tong = 0;
printf("\n\nNhap vao mot so nguyen: "); scanf("%ld",&n);
do { 10. printf("Cac uoc so cua %ld la: ",n);
11. for(i = 1;i<n;i++)
printf("Nhap diem (0<=diem<=10):"); 12. if(n % i == 0){
13. printf("%5d",i);
scanf("%f",&diem); 14. tong = tong + i;
if (diem < 0 || diem > 10) 15. }//if & for
16. printf("\nTong cac uoc so cua %ld bang %ld",n,tong);
printf("\nBan nhap khong dung!\n"); 17. if(tong == n) printf("\n %5ld LA so hoan hao“,n);
18. else printf("\n %5ld KHONG LA so hoan hao“,n);
} while (diem < 0 || diem > 10); 19. printf("\nBan co muon thuc hien lai(c/k)? ");
printf("\nDiem ban vua nhap la: %.2f“, diem); 20.
21.
fflush(stdin);
}while(toupper(getche()) !='K');
} 22. printf("\n\nAn phim bat ki de ket thuc ..."); getch();
207 23. } 208

207 208

52
Nhập số và phân tích số nguyên ra thừa số nguyên tố
1. #include <stdio.h>
2. #include <conio.h>
3. #include <ctype.h>
4. void main(){
5. int N, i;
6. do{ printf("\n\nNhap vao so nguyen duong "); scanf("%d",&N);
7. printf("%d = ",N);
8. i = 2;
9. while (i < N ){
10. if (N % i == 0){
11. printf("%d x ",i);
12. N = N/i;
13. } else i++;
14. }
15. printf("%d \n",N);
16. printf("Tiep tuc <C/K>?"); fflush(stdin);
17. }while(toupper(getche()) != 'K');
18. }
209 210

209 210

Chương 4: Cấu trúc điều khiển


4.3 Cấu trúc lặp

Ví dụ
Viết chương trình thực hiện công việc
- Nhập vào từ bàn phím 2 số nguyên
- Nhập vào từ bàn phím một ký tự bất kỳ;
▪ Nếu đây là một toán tử số học thì đưa ra
giá trị tương ứng với toán tử.
▪ Nếu không phải thì đưa ra thông báo sai
- Chương trình thực hiện cho tới khi ký tự
nhập vào là ‘q’ hoặc ‘Q’

211 212

211 212

53
#include <stdio.h> case '%': if (b==0) printf(" Chia cho 0\n");
#include <conio.h> else printf(" Co ket qua: %d\n",a%b);
void main() { break;
int a, b; case '/': if (b==0) printf(" Chia cho 0\n");
char ch; else printf(" Co ket qua: %d\n",a/b);
int Fin = 0; break;
clrscr(); case 'q':
printf("Nhap cac so a, b "); scanf("%d%d",&a,&b); case 'Q': Fin=1; break;
do{ default: printf(" khong co toan tu nay\n");
printf("\nToan tu (+ ; - ; * ; / ; %) "); ch=getche(); }
switch(ch){ }while(Fin==0);
case '+': printf(" Co ket qua: %d\n",a+b); break; printf("\nKet thuc, an mot phim...");
case '-': printf(" Co ket qua: %d\n",a-b); break; getch();
case '*': printf(" Co ket qua: %d\n",a*b); break; }
213 214

213 214

Chương 4: Cấu trúc điều khiển


4.3 Cấu trúc lặp

Ví dụ: Nhập xâu, đếm số ký tự của xâu


• Khai báo: int n=0; char c;
• Dùng vòng for
– for(n=0;;c=getchar(),n++) if(c==‘\n’) break;
– for(n=0 ; getchar() != '\n' ; n++);
• Dùng vòng lặp while
c = getchar();
while (c !=‘\n’){
c= getchar();
n++;
}
• Dùng vòng lặp do… while
do{
c = getchar();
n++;
}while(c!=‘\n’);
• Đưa kết quả ra: printf(«Chuoi chua %d ky tu »,n);
215 216

215 216

54
Chương 4: Cấu trúc điều khiển
Nhập chuỗi ký tự cho đến khi gặp ký tự ’*’ 4.4 Các lệnh thay đổi cấu trúc lập trình

Tính tần suất xuất hiện nguyên âm ‘a’ Ví dụ: Nhập một số nguyên, kiểm tra là số nguyên tố không?
1. #include <stdio.h> #includ <stdio.h>
2. #include <conio.h> #include <math.h>
3. #include <ctype.h> void main()
4. void main(){ { int N, i, OK = 1;
5. char c; int n, d; printf("\nNhap gia tri N : "); scanf("%d", &N);
6. do{ if (n<2) printf("\nSo %d khong phai so nguyen to",N);
7. printf("\n\n");
else {
8. d=0; n=0;
for
for (i=2;
(i=2; i < N;
i<=(int)sqrt(N); i++)i++)
9. while( (c=getche()) !='*'){
10. n++; if (N%i == 0) {
11. if (c=='a') d++; OK = 0;
12. } break; i <= (int)sqrt(N)
13. if(n==0) }
14. printf("\nChuoi ky tu rong\n"); if (OK) printf("\nSo %d la so nguyen to.", N);
15. else else printf("\nSo %d la hop so.", N);
16. printf("\ntan suat xuat hien ky tu 'a' la %5.2f%%\n",(float)100*d/n); } i= 2;
17. printf("Tiep tuc <C/K>?: "); getch(); while (N % i != 0) i++;
18. }while(toupper(getche()) != 'K');
} if (i == N) printf(« so ng to »)
19. } 217 218

217 218

Chương 4: Cấu trúc điều khiển


Chương 4: Cấu trúc điều khiển
4.4 Các lệnh thay đổi cấu trúc lập trình

Nội dung chính Mục đích


1. Cấu trúc lệnh khối • Các vòng lặp while/ do ... while/ for sẽ kết
2. Cấu trúc rẽ nhánh thúc quá trình lặp khi biểu thức điều kiện
– Cấu trúc if, if … else của vòng lặp không còn được thỏa mãn.
– Cấu trúc lựa chọn switch • Tuy nhiên trong lập trình đôi khi ta cũng cần
3. Cấu trúc lặp thoát khỏi vòng lặp ngay cả khi biểu thức
– Vòng lặp for điều kiện của vòng lặp vẫn còn được thỏa
– Vòng lặp while và do while mãn.
4. Các lệnh thay đổi cấu trúc lập trình • Để hỗ trợ người lập trình làm việc đó, ngôn
– Câu lệnh continue ngữ C cung cấp 2 câu lệnh là continue và
– Câu lệnh break break
219 220

219 220

55
Chương 4: Cấu trúc điều khiển
Chương 4: Cấu trúc điều khiển
4.4 Các lệnh thay đổi cấu trúc lập trình

Continue >< break continue

• Bỏ qua việc thực hiện các câu


lệnh nằm sau lệnh continue
trong thân vòng lặp.
• Chuyển sang thực hiện một vòng
lặp mới

221 222

221 222

Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.4 Các lệnh thay đổi cấu trúc lập trình 4.4 Các lệnh thay đổi cấu trúc lập trình

Ví dụ 1 break
#include <stdio.h>
Thoát khỏi vòng lặp ngay cả khi biểu
#include <conio.h>
void main() thức điều kiện của vòng lặp vẫn còn
Tính tổng 100 số nguyên đầu tiên
{ ngoại trừ các số chia hết cho 5 được thỏa mãn.
int i;
int sum = 0;
Chú ý:
for(i = 1;i<=100;i++) • break dùng để thoát ra khỏi khối lặp
{ hiện tại
if(i % 5 == 0) for(i=1;i<=100;i++)
continue; if (i % 5 != 0) • break cũng dùng để thoát ra khỏi
sum += i; sum += i; lệnh rẽ nhánh switch
}
}
223 224

223 224

56
Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.4 Các lệnh thay đổi cấu trúc lập trình 4.4 Các lệnh thay đổi cấu trúc lập trình

Ví dụ 2 Ví dụ 3
#include <stdio.h> #include <stdio.h>
#include <conio.h>
#include <conio.h>
void main() {
int n; void main()
do { {
printf(" \nEnter the number :"); scanf("%d", &n); int i;
if (n < 0) { for(i = 1;i<=10;i++)
break; {
}
if(i == 5) continue;
if (n >10) {
printf("Skip the value\n"); printf(“%5d”,i);
continue; if(i==7) break;
} }
printf("The number is: %d", n); getch();
} while (n!= 0); }
} 225 226

225 226

Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.4 Các lệnh thay đổi cấu trúc lập trình 4.4 Các lệnh thay đổi cấu trúc lập trình

Ví dụ 4 Ví dụ tổng hợp
#include <stdio.h>
#include <conio.h> Viết chương trình thực hiện các công việc
void main() sau
{ int i,j;
clrscr(); • Nhập vào một dãy số cho tới khi
for(i = 0;i<10;i++) { – Tổng của dãy lớn hơn 1550 hoặc là
for (j=0; j < 10; j ++) { – Số phần tử trong dãy lớn hơn 100
if(j > i){
break; • Đưa ra số lượng phần tử nằm trong
}//if khoảng (35, 70)
}//for _ j
printf("i:%d j:%d\n",i,j); • Đưa ra trung bình cộng của các phần tử
}//for_i chia hết cho 7
getch();
}
227 228

227 228

57
Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.4 Các lệnh thay đổi cấu trúc lập trình 4.4 Các lệnh thay đổi cấu trúc lập trình

Nhập một dãy số cho tới khi số phần tử trong dãy lớn hơn 100 Nhập một dãy số cho tới khi tổng của dãy lớn hơn 1550

Bắt đầu
#include <stdio.h> Bắt đầu #include <stdio.h>
void main(){ i0
void main(){
i0
int a, i; S0 int a, S;
Nhập số a i = 0; Nhập số a
S = 0;
do{ do{
i  i+1
printf("Nhap vao so nguyen:"); S  S+a printf("Nhap vao so nguyen:");
s i > 100
scanf("%d",&a); scanf("%d",&a);
s S > 1550
đ
i++; S+=a;
}while (i <= 100); đ }while (S <= 1550);
Kết thúc
Kết thúc
} }

229 230

229 230

Chương 4: Cấu trúc điều khiển


4.4 Các lệnh thay đổi cấu trúc lập trình Đưa ra TBC của các phần tử chia hết cho 7(1)
Nhập một dãy số cho tới khi thỏa mãn….
#include <stdio.h> Bắt đầu
Bắt đầu void main(){
#include <stdio.h> i0
int a, i=0,S7=0,d7=0; S70
i0 void main(){ do{ d70
S0 int a, i, S; printf("Nhap vao soNhập nguyen:");
số a
scanf("%d",&a);
i++; i  i+1
Nhập số a
S = 0; i=0;
do{ if(a%7==0){ đ d7d7+1
a % 7=0
S  S+a d7++; S7S7+a
printf("Nhap vao so nguyen:"); s
S7+=a;
scanf("%d",&a);
i  i+1 } i > 100
S+=a; s
}while (i <= 100); đ
s s i++; if(d7==0)
i > 100 S > 1550 TBC là: S7/d7
s
d7=0
đ Thông báo: Không
}while ( (i <=100)&&(S <= 1550) ); printf(“Khong co so chia het có sốcho
chia hết7);
cho 7
đ đ else
}
printf(“Ket qua la %.4f“,(float)
Kết thúc
S7/d7);
Kết thúc }
231 232

231 232

58
Chương 4: Cấu trúc điều khiển

Đưa ra TBC của các phần tử chia hết cho 7(2) 4.4 Các lệnh thay đổi cấu trúc lập trình

#include <stdio.h> Bắt đầu


Ví dụ tổng hợp Bắt đầu

void main(){ #include <stdio.h> i0 S70


int a, i=0,S7=0,d7=0,S=0; i0 S70 void main(){ S0 d70 d0
S0 d70
do{ int a, i=0,S7=0,d7=0,S=0, Nhập số a d = 0;
i  i+1 SS+a
printf("Nhap vaoNhập so sốnguyen:");
a
scanf("%d",&a); do{
i++; S+=a; i  i+1 SS+a printf("Nhap vao aso đ d7d7+1
nguyen:"); scanf("%d",&a);
% 7=0
S7S7+a
if(a%7==0){ đ d7d7+1
i++; S+=a; s
d7++; a % 7=0
S7S7+a if(a%7==0){ đ
a>35 &a<70 dd+1
S7+=a; s d7++;
s
} i > 100
s S > 1550 s S7+=a;
s S > 1550 s
}while ( (i <=100)&&(S <= đ 1550) ); đ } i > 100

đ
if(d7==0) if( (a>35) && (a < 70) ) d++; đ
printf(“Khong
TBC là: co
S7/d7so chia
s het cho
d7=0 7); báo: Không
đ Thông Thông bao: số p/tử trong khoảng (35,70) là d
}while ( (i <=100)&&(S <= 1550) );
có số chia hết cho 7
else printf(“So phanTBCtulà:trong
S7/d7
skhoang (35,70)
d7=0
đ Thông báo:laKhông
%d \n”,d);
có số chia hết cho 7
printf(“Ket qua la %.4f“,(float) S7/d7); if(d7==0) printf(“Khong co so chia het cho 7”);
} Kết thúc else printf(“TBC cac so chia het cho 7 %.4f“,(float) S7/d7);
Kết thúc
233 } 234

233 234

Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.3 Cấu trúc lặp 4.3 Cấu trúc lặp

Bài tập tại lớp Tính hàm f ( x) = x 5 + 5 x


1. #include <stdio.h> • pow(x,y) sinh ra lỗi khi x âm và y
1. Cho hàm số f ( x) = x 5 + 5 x Lập trình tính và đưa
không là số nguyên
2. #include <math.h>
ra màn hình các cặp giá trị <x,f(x)> với x lấy dãy giá trị -
3. void main(){ • fabs(x) trả về trị tuyệt đối của x
10;-9.9;-9.8; …..; 4.9;5.0.
4. float x, fx; khi là số thực
2. Đọc vào dãy số cho tới khi gặp một số dương chia hết
Có sai số khi x=0.0
cho 5; Tìm số lớn nhất của dãy và số lần xuất hiện các
giá trị đó 5. for(x=-10.0; x<=5.0; x+=0.1){
3. Nhập vào dãy cho tới khi gặp số 0. Tính trung bình cộng 6. if(x==0) for(int i=-100;i<50;i++){
các số chẵn đã đọc (không tính số 0) 7. fx = 0.0; x=(float)i/10;
4. Lập trình thực hiện trò chơi bốc sỏi với máy tính 8. else …….
– Có N viên sỏi, 2 người chơi lần lượt bốc từ 1 đến 5 viên. Người 9. fx = pow(x,5)+x/fabs(x) * pow(fabs(x), 0.2);
bốc vên sỏi cuối luôn thắng/thua. Hãy viết chương trình thực hiện
10. printf("<%4.1f,%7.2f>\n",x,fx);
nhập N (N  [30..50) ) và máy tính là một người chơi. Máy tính đi
trước và luôn thắng nếu được (N=6,12,.. người đi trước thua) 11. }
12. }
235 236

235 236

59
Chương 4: Cấu trúc điều khiển Chương 4: Cấu trúc điều khiển
4.3 Cấu trúc lặp 4.3 Cấu trúc lặp

Đọc dãy số tới khi gặp số 0, tìm và đếm số max Bài tập
1. #include <stdio.h>
2. #include <limits.h> Viết chương trình đọc x và n vào từ bàn phím rồi tính

3. void main(){
4. int a, d=0, max = INT_MIN; S = x + x + x +  + x n dâ' u c ăn
5. do { x 2 x3 xn
6. printf("Nhap mot so : "); scanf("%d",&a); S = 1+ x + + ++
7. if( a > max){ 2 3 n
8. max = a; x 2 x3 xn
9. d = 1;
S = 1+ x + + ++
2! 3! n!
10. }else
x 2 x3 (−1) n x n
11. if (a == max) d++; S = 1− x + − ++
12. }while ( a < 0 || a%5 !=0); 2! 3! n!
13. printf(“Max: %d; Co %d gia tri",max,d);
14. }
237 238

237 238

Chương 4: Cấu trúc điều khiển


Viết chương trình đọc x và n vào từ bàn phím rồi tính 4.3 Cấu trúc lặp

1. #include <stdio.h> Bài tập (Tính tổng vô hạn)


x 2 x3 xn
2. #include <conio.h> S =1+ x + + ++ Đọc x và eps từ bàn phím và tính biểu thức sau với
3. void main(){ 2! 3! n!
4. int n, i; độ chính xác nhỏ hơn eps
5. float x, u = 1.0,S=1.0;
x 2 x3 (−1) n x n
6. clrscr(); S1 = 1 − x + − ++ +
7. printf("Nhap vao so nguyen n : "); scanf("%d",&n); 2! 3! n!
8. printf("Nhap vao so thuc x : "); scanf("%f",&x); x3 x5 (−1) n 2 n +1
9. for(i = 1; i <= n; i ++){ S2 = x − + +  + x +  // sin( x)
3! 5! (2n + 1)!
10. u *= x/i;
11. S += u; x2 x4 (−1) n 2 n
12. }
S3 = 1 − + ++ x +  // cos( x)
2! 4! (2n)!
13. printf("Ket qua la %.8f",S);
14. getch();
15. }
239 240

239 240

60
Nhập x và  và tính với độ chính xác nhỏ hơn  Chương 4: Cấu trúc điều khiển
2
x x3
(−1) x
n n Tổng kết
S = 1− x + − ++ +
2! 3! n! 1. Câu lệnh khối
Đặt trong cặp ngoặc nhọn { }
2. Cấu trúc rẽ nhánh
– if (bieu_thuc), if (bieu_thuc) … else
– switch (bieu_thuc) {(case/break/default)}
3. Cấu trúc lặp
– for(bieu_thuc_1; bieu_thuc_2; bieu_thuc_3) CauLenh;
– while (bieu_thuc) CauLenh;
– do Cau_Lenh while (bieu_thuc);
4. Các lệnh thay đổi cấu trúc lập trình
– continue/ break
241 242

241 242

Phần 3: Lập trình C Chương 5: Mảng, con trỏ và xâu ký tự


Nội dung chính Nội dung chính
• Chương 1: Tổng quan về ngôn ngữ C 1. Mảng
• Khái niệm
• Chương 2: Kiểu dữ liệu và biểu thức trong C • Khai báo và sử dụng
• Các thao tác thường gặp
• Chương 3: Vào ra dữ liệu
2. Con trỏ
• Chương 4: Cấu trúc điều khiển • Khái niệm và cách khai báo
• Toán tử địa chỉ (&), toán tử nội dung (*)
• Chương 5: Mảng, con trỏ và xâu ký tự
• Phép toán trên con trỏ
• Chương 6: Cấu trúc • Con trỏ và mảng
3. Xâu ký tự
• Chương 7: Hàm • Khái niệm, khai báo và sử dụng
• Chương 8: Tệp dữ liệu • Các hàm xử lý ký tự và xâu ký tự
243
• Mảng xâu ký tự 244

243 244

61
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Giới thiệu Giới thiệu


Bài toán: • Trong thực tế, thường gặp các đối tượng có
• Nhập điểm thi (số nguyên) môn Tin đại cương cho lớp gồm tính chất chung
50 sinh viên rồi đưa ra số lượng sinh viên phải học lại
Phương pháp: Điểm của mỗi sinh viên là 1 biến – Tháng trong năm
• Tên biến là tên sinh viên – Điểm trung bình của sinh viên trong lớp
Ví dụ: int An, Anh, Binh1, Binh2, Cuong,….. Van, Viet; • Các đối tượng được nhóm lại dưới một tên
• Tên biến dạng “dx” với x là chỉ số thứ tự của SV trong lớp
• Đối tượng được đặc trưng bởi tên nhóm và
Ví dụ: int d1, d2, d3,……,d50;
Nhận xét 1: Không hợp lý
thứ tự trong nhóm
• Có quá nhiều biến (Điểm thi cho toàn trường.. !?) – Tháng thứ 3 trong năm: Tháng 3
• Khó khăn cho các thao tác duyệt toàn bộ danh sách – Sinh viên thứ 17 trong lớp:…
– Số SV học lại: if(d1 <5) d++; if(d2 <5) d++; ……if(d50 <5) d++; • Số thứ tự của đối tương trong nhóm là chỉ
Nhận xét 2: Các biến có chung ý nghĩa, tính chất 245 số phần tử 246

245 246

Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Khái niệm mảng Khai báo mảng


• Kiểu mảng là một kiểu dữ liệu gồm Kiểu_dữ_liệu Tên_Mảng[Kích thước];
– Một số hữu hạn thành phần.
– Các thành phần có cùng một kiểu: kiểu cơ sở • Kiểu_dữ_liệu: kiểu của các phần tử trong
hay là kiểu thành phần. mảng (nguyên, thực, ký tự, chuỗi, mảng,…)
• Mỗi phần tử của mảng được tham khảo • Tên_mảng: tên của mảng
thông qua • Kích_thước_mảng: số phần tử trong mảng
– Tên mảng và Ví dụ
– Chỉ số của phần tử trong mảng // khai báo mảng 50 phần tử có kiểu dữ liệu int
int DiemTin[50];
Ví dụ:
float A[10]; // Mảng 10 phần tử kiểu số thực
– <d7>: Điểm thi tin của sinh viên thứ tự 7 trong lớp
247 248

247 248

62
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Cấp phát bộ nhớ cho mảng Truy nhập đến thành phần của mảng
• Các phần tử trong mảng được cấp phát các • Biến mảng lưu trữ địa chỉ ô nhớ đầu tiên
ô nhớ kế tiếp nhau trong bộ nhớ trong vùng nhớ được cấp phát
• Kích thước của mảng bằng kích thước một • Ngôn ngữ C đánh chỉ số các phần tử trong
phần tử nhân với số phần tử mảng bắt đầu từ 0
Ví dụ: • Các phần tử của mảng được truy nhập
int A[10];//Mảng A gồm 10 phần tử nguyên thông qua
– Tên mảng và
A[0] A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8] A[9]
– Chỉ số của phần tử của phần tử trong mảng
Kích thước của mảng A: 10 x 2 = 20 bytes
Tên_Mang[Chỉ_số_phần_tử];
249 250

249 250

Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Truy nhập đến thành phần của mảng→Ví dụ Ví dụ


int A[10];//Mảng A gồm 10 phần tử nguyên int A[10];
for(int i = 0; i < 10; i++) A[i]= 2* i;
7
A[0] 5
A[1] A[2] A[3] 7
A[4] A[5] A[6] A[7] A[8] A[9]
A
0? 2? 4? 6
? 8? 10
? 12
? 14
? 16
? 18
?

A[0] A[4] A[9]


0
i : 10
7
1
4
2
5
6
3
8
9
A[0] = 7; Chú ý: C không kiểm tra vượt quá giới hạn
A[1] = 5; của mảng khi truy nhâp
A[4] = 7; int A[3], B[4], C[3];
int N = A[1] + A[4]; → N = 12 A[0] A[1] A[2] B[0] B[1] B[2] B[3] C[0] C[1] C[2]

251
A[5]  B[2]  C[-2] nếu c/cấp liên tiếp 252

251 252

63
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Mảng nhiều chiều Mảng nhiều chiều


• Mỗi phần tử của mảng có thể là một mảng int t[3][4] ;
Mảng nhiều chiều

Kiểu Tên[Chiều_1] [Chiều_2]… [Chiều_N]; t[0] t[0][0] t[0][1] t[0][2] t[0][3]

t[1] t[1][0] t[1][1] t[1][2] t[1][3]


• Kiểu: Kiểu của mỗi phần tử trong mảng
• Chiều_1, Chiều_2,…Chiều_N: Các hằng số t[2] t[2][0] t[2][1] t[2][2] t[2][3]
nguyên, cho biết kích thước (số phần tử) của mỗi
chiều
• Mảng gồm: Chiều_1 x Chiều_2 x...x Chiều_N
phần tử được lưu trữ trong vùng nhớ liên tục. Các
t[1][0] t[1][1] t[1][2] t[1][3]
phần tử thuộc kiểu Kiểu
253 254

253 254

Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Mảng nhiều chiều→Ví dụ Khởi tạo giá trị cho mảng


int b[3][4][5]; b[2][2][4] Các phần tử của mảng có thể được khởi tạo
b[2] giá trị ngay khi khai báo
b[1] Ví dụ
b[0] int a[4] = {1,4,6,2};
int b[2][3]={ {1,2,3}, {4,5,6} };
b[0][1][2] int t[3][4] = {
• Mảng b gồm 3 phần tử b[0], b[1], b[2] {1, 2, 3, 4},
• Mỗi phần tử là mảng hai chiều gồm 4 hàng {5, 6, 7, 8},
(hàng 0, 1, 2, 3) và 5 cột (0, 1, 2, 3, 4) {9, 10, 11, 12},
• Mỗi phần tử có kiểu nguyên có dấu, 2 byte };
255 256

255 256

64
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Khởi tạo giá trị cho mảng → Chú ý Các thao tác thường gặp
• Số lượng giá trị khởi tạo không được lớn • Nhập/Xuất dữ liệu cho mảng
hơn số lượng phần tử trong mảng – Mảng 1 chiều, ma trận
– Nếu số lượng này nhỏ hơn, các phần tử còn lại • Bài toán đếm
được khởi tạo giá trị 0
– Đếm số phần tử
int A[3][4] = { {1}, {4,5} };
– Tính toán trên các phần tử..
int A[3][4] = { };Tất cả đều mang giá trị 0
• Tìm kiếm phần tử
• Có thể xác định kích thước mảng thông qua
số giá trị khởi tạo nếu để trống kích thước – Lớn nhất/nhỏ nhất/bất kỳ
mảng • Sắp xếp phần tử trong mảng
int A1 [8] = {2, 4, 6, 8, 10, 12, 14, 16}; – Theo thứ tự, theo nguyên tắc
int A2 [] = {2, 4, 6, 8, 10, 12, 14, 16}; • Chèn thêm phần tử, xóa phần tử
257 258

257 258

Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Nhập dữ liệu Nhập dữ liệu→Ví dụ 1


Dùng hàm scanf() Nhập vào lượng mưa (mm) trong năm
Ví dụ: int Table[10]; #include <stdio.h>
• Nhập dữ liệu cho một phần tử #define MONTHS 12
int main(){
scanf(“%d”,&Table[2]);phần tử thứ 3 của mảng
int rainfall[MONTHS], i;
• Nhập dữ liệu cho cả mảng for ( i=0; i < MONTHS; i++ ){
– Dùng vòng lặp for printf(“Nhap luong mưa tháng %d: “, i+1);
for(i = 0; i < 10; i++) scanf("%d", &rainfall[i] );
scanf(“%d”,&Table[i]); }
– Nên in ra chỉ số phần tử khi nhập return 0;
printf(“Table[%d] : ”,i); scanf(“%d”,&Table[i]) 259
} 260

259 260

65
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Nhập dữ liệu→Lưu ý Nhập dữ liệu→Ví dụ 2


• Nếu số phần tử của mảng chỉ được biết tại #include<stdio.h>
thời điểm thực hiện chương trình (nhưng biết void main(){
số phần tử tối đa) float A[100];
– Khai báo mảng với kích thước tối đa int n, i;
do{
– Sử dụng biến nguyên lưu số phần tử thực sự của
mảng. printf(“\n Cho biet so phan tu cua mang: “);
scanf(“%d”,&n);
Ví dụ:
}while (n>100 || n<=0);
• Nhập vào mảng không quá 100 số thực for(i = 0; i < n; i++){
– Khai báo mảng thực Table có tối đa 100 phần tử. printf(“A[%d] = ", i); scanf("%f",&A[i]);
– Nhập số phần tử thực sự của mảng }
– Nhập giá trị cho từng phần phần tử (dùng for) }
261 262

261 262

Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Xuất dữ liệu trong mảng Xuất dữ liệu trong mảng→Ví dụ 1


Dùng hàm printf() #include <stdio.h>
#define MAX 12
Ví dụ: int Table[10];
void main(){
• Hiện thị phần tử thứ 5: int A[MAX], i;
printf(“%d”,Table[4]); for ( i=0; i < MAX; i++ ){ //Nhập dữ liệu
• Để hiển thị tất cả các phần tử: printf(“A[%d]: “, i+1); scanf("%d", &A [i] );
for(i = 0; i < 10; i++) }
printf(“%4d”,Table[i]); for ( i=0; i < MAX; i++ ){
)
Các kiểu xuất dữ liệu printf( "%4d”
"%4d ”,,,A[i]);
"%d\n” A[i]);
A[i]);
– Hiển thị tất cả/một phần theo dòng/cột.. if( (i+1) %4==0) printf(“\n”);
– Hiển thị từng k phần tử trên một dòng… }
263
} 264

263 264

66
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Xuất dữ liệu trong mảng→Ví dụ 1→Thực hiện Ví dụ 2: Nhập và đưa ra màn hình một ma trận
1. #include <stdio.h>
2. void main(){
3. int A[20][20], n, m, i,j;
4. printf("Nhap so hang : "); scanf("%d",&n);
5. printf("Nhap so cot : "); scanf("%d",&m);
6. printf("\n");
7. for ( i=0; i < n; i++ )
8. for(j=0; j < m; j++) {
9. printf("Nhap phan tu A[%d,%d]: ", i+1,j+1);
10. scanf("%d", &A[i][j] );
11. }
12. printf("\n\n MA TRAN DA NHAP \n\n");
13. for ( i=0; i < n; i++ ){
14. for(j=0; j < m; j++)
15. printf( "%4d" ,A[i][j]);
16. printf("\n");
17. }
265 18. } 266

265 266

Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Ví dụ 2→Kết quả thực hiện Đếm số phần tử thỏa mãn điều kiện
• Duyệt từng phần tử của dãy (dùng for )
• Nếu phần tử xét thỏa mãn điều kiện
– Ghi nhận
• Chuyển sang xem xét phần tử tiếp theo
Ví dụ: Đếm số tháng có lượng mưa lớn hơn 50mm
int dem = 0;
for(i = 0; i < MONTHS; i++)
if(rainfall[i] > 50)
dem++;
printf("\nThang mua nhieu hon 50mm: %d", dem);

267 268

267 268

67
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Ví dụ: Nhập mảng, đưa ra TBC các số chia hết cho 7 Tìm kiếm phần tử
#include<stdio.h>
void main(){
Tìm phần tử lớn nhất (nhỏ nhất)
int A[100]; – Giả sử phần tử đó là phần tử đầu tiên
int n, i, d = 0, S=0;
– Lần lượt so sánh với các phần tử còn lại
printf(“\n So phan tu cua mang (<100) : “); scanf(“%d”,&n);
for(i = 0; i < n; i++){ • Nếu phần tử mới của dãy lớn hơn coi đây là phần
printf("A[%d] = ", i); scanf("%d",&A[i]); tử lớn nhất và tiếp tục so sánh với phần tử kế
} • Nếu không đúng, so sánh tiếp với phần tử kế
for(i = 0; i < n; i++)
Ví dụ: Tìm tháng có lượng mưa nhiều nhất trong năm
if(A[i] %7==0){
d++; max = rainfall[0];
S+= A[i]; for(i = 1; i < MONTHS; i++)
} if(rainfall[i] > max)
if(d > 0) printf(”TBC so chia het cho 7: %7.2f”,(float)S/d); max = rainfall[i];
else printf(”Trong day khong co so chia het cho 7”); printf("\n Luong mua nhieu nhat la: %d", max);
} 269 270

269 270

Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Tìm kiếm phần tử Tìm kiếm phần tử (tiếp)


• Tìm kiếm các phần tử thỏa mãn điều kiện • Tìm phần tử đầu tiên của danh sách
(giống bài toán đếm) – Dùng vòng lặp for kết hợp với break;
– Dùng for duyệt toàn bộ – Dùng vòng lặp while
– Nếu cần thiết, dùng thêm mảng ghi lại chỉ số Ví dụ
Ví dụ: Đưa ra danh sách các tháng có lượng Đưa ra phần tử đầu của mảng có giá trị
mưa nhiều hơn 50mm bằng k;
printf(“Thang co luong mua lon hon 500mm”)
for(i = 0; i < MONTHS; i++)
if(rainfall[i] > 50)
printf("\nThang %d", i+1);
271 272

271 272

68
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Tìm kiếm phần tử →Ví dụ Bài tập 1


int Table[100] 1. Nhập vào dãy (<100) số, tính và đưa ra màn hình
int N, i, k, f;//N: số phần tử, k phần tử cần tìm • Tổng và tích của dãy số
• Các số chia hết cho 3 và lớn hơn 10
Dùng for • Đếm các số nằm trong đoạn [100,1000)
for(i = 0; i < N; i++) 2. Nhập vào một dãy số; tìm số chẵn nhỏ nhất dãy
if(Table[i] == k) break; 3. Nhập dãy số; đếm xem có bao nhiêu bộ 3 số thỏa
if(i< N) printf(“Tim thay tai vi tri %d“,i); mãn điều kiện xi=(xi-1+xi+1)/2
Dùng while 4. Viết chương trình nhập vào từ bàn một dãy số (<100
i=0; f =0; //f: found. f = 1  k is found phần tử). Đưa ra số bé nhất và vị trí những số bằng
while(i < N && f==0){ số bé nhất
if(Table[i] == k) f = 1; 5. Nhập vào n và dãy số (x1,x2,…xn) ;(y1,y2,..yn) rồi tính
n−1

cosx sin x (x − y ) x


n n
else i++;} a) b) 2
c) i +1
i i i i 2 yi +1
if (f==1) printf(“Tim thay tai vi tri %d”,i); 273
i=1 i =1 1
274

273 274

Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Bài 1 Bài toán sắp xếp theo thứ tự


• Cho mảng phần tử, sắp xếp theo thứ tự
tăng/giảm
• Các thuật toán
– Sắp xếp thêm dần (insertion sort)
– Sắp xếp lựa chọn (selection sort)
– Sắp xếp nổi bọt (bubble sort)
– Sắp xếp vun đống (heap sort)
– Sắp xếp nhanh (quick sort)
– Sắp xếp trộn (merge sort)
– ….
275 276

275 276

69
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Bài toán sắp xếp tăng →Thuật toán lựa chọn Bài toán sắp xếp tăng →Thuật toán lựa chọn
Nguyên tắc
Tại lượt sắp thứ k, tìm phần tử nhỏ nhất trong số Dãy Lượt 1 Lượt 2 Lượt 3 Lượt 4
các phần tử chưa được sắp xếp ([k..last]) và đổi
chỗ cho phần tử thứ k (có chỉ số k-1) 3 3
2
1 1 1 1 1
– Khi k = 1, phần tử thứ nhất (chỉ số 0) đúng vị trí
– Khi k= 2, phần tử thứ hai (chỉ số 1) đúng vị trí… 5 5 3
2
5 2 2 2
2 2
3 5
3 5
3 3 3
6 6 6 6 6
5 5
1 1
2 3
2 3
5 5
6 6
277 278

277 278

Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Bài toán sắp xếp tăng →Thuật toán lựa chọn Ví dụ


//Khai báo các biến
int A[100]; //Mảng chứa dữ liệu Nhập vào từ bàn phím một mảng các số
int N, i, j, tmp; nguyên không quá 100 phần tử
//Sắp xếp
Hiển thị dãy số vừa nhập
for(i = 0; i < N – 1; i++)
for(j = i + 1; j < N; j++) Sắp xếp dãy theo thứ tự giảm dần
if(A[i] > A[j]) { Hiện thị dãy tại mỗi lượt sắp xếp
tmp = A[i];
A[i] = A[j];
A[j] = tmp;
}
279 280

279 280

70
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Ví dụ Ví dụ
1. #include<stdio.h> 14. printf("Sap xep day theo thuat toan lua chon");
2. void main(){ 15. for(i=0; i < N-1; i++){
3. int A[100] ; 16. for(j=i+1; j < N; j++)
4. int N, i, j , t; 17. if(A[i] < A[j]) {
5. printf("So phan tu [< 100]: "); scanf("%d",&N); 18. t = A[i];
6. printf("Hay nhap day so...\n"); 19. A[i] = A[j];
7. for(i=0; i < N; i++){ 20. A[j] = t;
8. printf("A[%d] = ",i+1); scanf("%d",&A[i]); 21. }//if & for_j
9. } 22. printf("\nLuot %d : ",i+1);
10. printf("\nDay vua nhap...\n"); 23. for(j=0; j < N; j++)
11. for(i=0; i < N; i++) 24. printf("%4d", A[j]);
12. printf("%4d", A[i]); 25. }//for_i
13. printf("\n\n"); 26. }//main
281 282

281 282

Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Ví dụ→Kết quả Bài toán chèn phần tử a vào vị trí k

for(i = N; i > k; i--)


2
A[i] = A[i-1];
5
k A[k] = a;
8
7 7
N= N + 1;
4
8
Chú ý:
9
4 N = MAX: không chèn được
k > N → Chèn vào vị trí N;
?
9
k< 0 → Chèn vào vị trí 0
283 284

283 284

71
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Bài toán xóa phần tử ở vị trí k (0k<N) Bài tập 2


1. Nhập vào từ bàn phím một dãy số nguyên (<100 phần
2 tử). Sắp xếp dãy theo nguyên tắc: Bên trên là số chẵn
chia hết cho 3. Bên duới là số lẻ chia hết cho 3. Giữa là
5 for(i = k+1; i < N; i++) các số còn lại. Đưa cả 2 dãy ra màn hình.
k 2. Đọc vào dãy số có n phần từ (n<100). Đọc số x và số k
8
3 A[i-1] = A[i]; nguyên. Chèn x vào vị trí k của dãy. Nếu k>n, chèn x vào
vị trí n+1.
3
9 N= N - 1; 3. Nhập vào một dãy số (<100 phần tử) và sắp xếp theo
thứ tự tăng dần. Nhập thêm vào một số và chèn số mới
N 4
9 nhập vào đúng vị trí
4. Nhập vào một dãy (<100 phần tử); xóa đi các phần tử
4 chia hết cho 5 và đưa kết quả ra màn hình

285 286

285 286

Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Bài chữa Bài chữa → Sắp xếp số chẵn chia hết 3 lên đầu dãy..
#include<stdio.h> 1. { int d = 0, t;
void main(){ 2. for(i=0;i < N; i++)
int A[100];
3. if(A[i]%6==0){
int N, i;
//Nhập dữ liệu
4. t=A[i]; A[i]=A[d]; A[d] = t;
printf("So phan tu : "); scanf("%d",&N); 5. d++;
for(i=0; i < N; i ++){ 6. }
printf("A[%d] = ",i);scanf("%d",&A[i]); 7. for(i=d; i < N; i++)
} 8. if(A[i]%3 != 0){
//Các thao tác xử lý mảng: chèn, xóa, sắp xếp,…
9. t=A[i]; A[i]=A[d]; A[d] = t;
//Đưa Dữ liệu ra
for(i=0; i < N; i ++) 10. d++;
printf("%4d",A[i]); 11. }
} 12. }
287 288

287 288

72
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Bài chữa → Sắp xếp tăng dần và chèn đúng vị trí Bài chữa → Xóa các phần tử chia hết cho 5..
1. { int k = 0,i, j, t;
2. for(i=0;i < N - 1; i++)//Sắp xếp lựa chọn
1. { // PP: Giữ lại các phần tử không chia hết cho 5
3. for(j=i+1;j < N ; j++) 2. int d = 0, i;
4. if(A[i] > A[j]){ 3. for(i=0;i < N; i++)
5. t = A[j]; A[j] = A[i]; A[i]=t;
6. } 4. if(A[i] % 5 != 0){
7. printf("Phan tu moi:"); scanf("%d",&k);//Nhập p/tử mới 5. A[d] = A[i];
8. i = N; //Chèn đúng vị trí 6. d++;
9. while( (i > 0) &&(A[i-1] > k) ){
10. A[i] = A[i-1]; 7. }
11. i--; 8. N = d;
12. }
13. A[i] = k;
9. }
14. N++;
15. }
289 290

289 290

Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Xóa các phần tử chia hết cho 5 →Kết quả Bài tập 3 : Ma trận
1. Viết chương trình nhập vào một ma trận vuông,
các phần tử nguyên, sau đó
• Đưa ra ma trận tam giác duới
• Đưa ra ma trận tam giác trên
2. Nhập M, N (M, N < 30) và một ma trận MxN.
Đưa ma trận ra màn hình
• Tìm hàng/cột có tổng các phần tử lớn nhất
• Tìm số lớn nhất/nhỏ nhất và vị trí trong ma trận
• Đưa ra ma trận S cùng kích thước thỏa mãn
 1 nê'u ui , j  0

si , j =  0 nê'u ui , j = 0

− 1 nê'u ui , j  0
291 292

291 292

73
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng 5.1 Mảng

Nhập vào một ma trận vuông,.. Đưa ra ma trân tam giác trên, dưới
#include <stdio.h> printf("\n\n MA TRAN TAM GIAC TREN \n\n");
void main(){ for ( i=0; i < N; i++ ){
int A[20][20], N,i,j; for(j=0; j < N; j++)
printf("Nhap kich thuoc : "); scanf("%d",&N); if(j >= i)
printf("\n"); printf( "%4d" ,A[i][j]);
for ( i=0; i < N; i++ ) else
for(j=0; j < N; j++) { printf("%4c",32); //32 là mã ASCII của dấu cách
printf("Nhap phan tu [%d,%d]:", i+1,j+1); printf("\n");
scanf("%d", &A[i][j] ); }
} printf("\n\n MA TRAN TAM GIAC DUOI \n\n");
printf("\n\n MA TRAN DA NHAP \n\n"); for ( i=0; i < N; i++ ){
for ( i=0; i < N; i++ ){ for(j=0; j <= i; j++)
for(j=0; j < N; j++) printf( "%4d" ,A[i][j]);
printf( "%4d" ,A[i][j]); printf("\n");
printf("\n"); }
} 293 }//main 294

293 294

Chương 5: Mảng, con trỏ và xâu ký tự


Chương 5: Mảng, con trỏ và xâu ký tự
5.1 Mảng

Thực hiện Nội dung chính


1. Mảng
• Khái niệm
• Khai báo và sử dụng
• Các thao tác thường gặp
2. Con trỏ
• Khái niệm và cách khai báo
• Toán tử địa chỉ (&), toán tử nội dung (*)
• Phép toán trên con trỏ
• Con trỏ và mảng
3. Xâu ký tự
• Khái niệm, khai báo và sử dụng
• Các hàm xử lý ký tự và xâu ký tự
295
• Mảng xâu ký tự 296

295 296

74
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.2 Con trỏ 5.2 Con trỏ

Giới thiệu Địa chỉ


• Bộ nhớ gồm dãy các ô nhớ
• Là một khái niệm “mạnh“ 00000
– Mỗi ô nhớ là một byte
00001
trong C – Mỗi ô nhớ có một địa chỉ riêng
– Cho phép tính toán trên con trỏ • Các biến trong chương trình được lưu tại vùng
– Sử dụng con trỏ hàm nhớ nào đó trong bộ nhớ
Biến
• Cho phép truy nhập gián tiếp • Khi khai báo biến, tùy thuộc vào kiểu, biến sẽ
tới một đối tượng có địa chỉ được cấp một số ô nhớ liên tục nhau
(biến, hàm) – Biến int được cấp 2 bytes, float được cấp 4 bytes,..
Con trỏ
– Truy nhập trực tiếp→ thông – Địa chỉ của biến, là địa chỉ của byte đầu tiên trong số
qua tên các byte được cấp
FFFFF
Bộ nhớ – Khi gán giá trị cho biến, nội dung các byte cung cấp cho
297
biến sẽ thay đổi 298

297 298

Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.2 Con trỏ 5.2 Con trỏ

Địa chỉ →Ví dụ Con trỏ


int N; • Con trỏ là một biến mà 0000
Địa chỉ biến N giá trị của nó là địa chỉ Biến nhớ
float x;
?
E8 của một vùng nhớ EB03 ABCD
char Arr[4]; 03
?
N
Địa chỉ biến X – Vùng nhớ này có thể dùng
?
00
?
00 để chứa các biến có kiểu cơ
?
1B
X bản (nguyên, thực, ký tự,…)
N = 1000;//03E8
Địa chỉ biến Arr ?
41 hay có cấu trúc (mảng, bản
X=9.6875;//411B0000 ?
01
? ghi,..)
05
for(i=0;i<4;i++) Arr
?
09 • Con trỏ dùng “trỏ tới” một ABCD EFCD
Arr[i]= 4*i+1; ?
0D
biến nhớ Biến con trỏ
Địa chỉ của một biến là địa chỉ byte – Có thể trỏ tới một hàm FFFF
nhớ đầu tiên được cung cấp cho Bộ nhớ – Có thể trỏ tới con trỏ khác Bộ nhớ
biến để lưu trữ dữ liệu
299 300

299 300

75
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.2 Con trỏ 5.2 Con trỏ

Con trỏ →Khai báo Toán tử địa chỉ (&)

Kiểu * Tên; • Ký hiệu: & 0000


• Là toán tử một ngôi, trả Biến N
• Tên: Tên của một biến con trỏ về địa chỉ của biến ABCD
• Kiểu: Kiểu của biến mà con trỏ “Tên” trỏ tới – Địa chỉ biến có thể được
– Giá trị của con trỏ có thể thay đổi được gán cho một con trỏ, trỏ tới
• Trỏ tới các biến khác nhau, có cùng kiểu đối tượng cùng kiểu
– Kiểu biến mà con trỏ trỏ tới không thay đổi được Ví dụ
• Muốn thay đổi phải thực hiện “ép kiểu” ABCD EFCD
int N; // &N→ ABCD Biến pi
Ví dụ: int * pi;
FFFF
int * pi; //Con trỏ, trỏ tới một biến kiểu nguyên pi = &N; // piABCD Bộ nhớ
char * pc; //Con trỏ, trỏ tới một biến kiểu ký tự
301 302

301 302

Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.2 Con trỏ 5.2 Con trỏ

Toán tử nội dung (*) Gán giá trị cho con trỏ
• Ký hiệu: *
0000
• Con trỏ được gán địa chỉ của một biến
• Là toán tử một ngôi, trả về giá – Biến cùng kiểu với kiểu mà con trỏ trỏ tới
Biến N
trị (nội dung) của vùng nhớ mà ABCD
• Nếu không, cần phải ép kiểu
20
10
con trỏ đang trỏ tới • Con trỏ được gán giá trị của con trỏ khác
Ví dụ – Hai con trỏ sẽ trỏ tới cùng một biến(do cùng địa chỉ)
int N; – Hai con trỏ nên cùng kiểu trỏ đến
int * pi; • Nếu không, phải ép kiểu
pi = &N; N= 10; *pi = 10; ABCD EFCD • Con trỏ được gán giá trị NULL
N = 10;//Vùng nhớ mà pi trỏ tới
mang giá trị 10; Vậy *pi=10
Con trỏ pi Ví dụ: int *p; p = 0;
*pi = 20;// Vùng nhớ pi trỏ tới được FFFF • Gán nội dung vùng nhớ 2 con trỏ trỏ tới.
gán giá trị 20; Vậy N= 20 Bộ nhớ
Ví dụ: int *p1, *p2; *p1 = *p2;
303 304

303 304

76
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.2 Con trỏ 5.2 Con trỏ

Ví dụ Ví dụ→Trường hợp 1
#include <stdio.h> #include <stdio.h> 0000
1. #include <stdio.h>
void main(){ void main(){
2. void main(){
int N=5, M=10; int N=5, M=10; 10
5 ABCD
3. int N=5, M=10;
int *p1 = &N; int *p1 = &N; 10 ABCF
4. int *p1 = &N;
int *p2 = &M; int *p2 = &M;
5. int *p2 = &M;

p2 p1
*p1 = *p2; p1 = p2; ABCF
6. *p1 = *p2;
printf("%d %d",*p1,*p2); printf("%d %d",*p1,*p2); ABCD
7. printf("%d %d",*p1,*p2);
} }
8. }
10 10 10 10
FFFF
Bộ nhớ
305 306

305 306

Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.2 Con trỏ 5.2 Con trỏ

Ví dụ→Trường hợp 2 Các phép toán trên con trỏ


0000
1. #include <stdio.h> • Cộng con trỏ với một số nguyên
2. void main(){ – Kết quả: Con trỏ cùng kiểu
5 ABCD
3. int N=5, M=10; • Trừ con trỏ với một số nguyên
10 ABCF
4. int *p1 = &N; – Kết quả: Con trỏ cùng kiểu
5. int *p2 = &M; • Trừ 2 con trỏ cùng kiểu cho nhau
p2 p1

6. p1 = p2; ABCF
– Kết quả: Một số nguyên
7. printf("%d %d",*p1,*p2); ABCD
ABCF
• Khoảng cách giữa 2 con trỏ được đo bằng số phần tử
8. } thuộc kiểu dữ liệu mà con trỏ trỏ tới

FFFF
Bộ nhớ
307 308

307 308

77
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.2 Con trỏ 5.2 Con trỏ

Các phép toán trên con trỏ→Ví dụ Mối quan hệ giữa con trỏ và mảng một chiều

• Nếu T là tên một mảng  T là một con trỏ


0000
int N=1000, M=2000,P=3000;
int * p1 = &P, *p2 = &N; P
E8
03
ABC0
ABC1
hằng chứa địa chỉ của phần tử đầu tiên của
D0 ABC2 mảng T (&T [0])
p1 - p2 → -2 M 07 ABC3
N B8 ABC4 – Không tồn tại phép tính trên tên mảng, hoặc gán
0B ABC5
* (p2-1) → 2000 ABC6 giá trị cho tên mảng (VD: T=…; T++)
• Có thể sử dụng một con trỏ để duyệt mảng
* ++ p1 → 2000 p2 ABC4 nếu nó được gán giá trị bằng địa chỉ của
p1 ABC0
ABC2 mảng (địa chỉ của phần tử đầu tiên)
Ghi chú:
• Kiểu int, các phần tử cách nhau 2 bytes FFFF

• Kiểu float, các phần tử cách nhau 4 bytes Bộ nhớ


309 310

309 310

Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.2 Con trỏ 5.2 Con trỏ

Ví dụ Con trỏ void


int A[10]; void * Tên_con_trỏ
int * p = A; // int *p = &A[0] • Là một con trỏ đặc biệt: con trỏ không có kiểu
• Có thể nhận giá trị là địa chỉ của một biến có kiểu
for(i = 0; i < 10; i ++) dữ liệu bất kỳ
printf(“%d ”, *(p + i) ); – Thường dùng làm đối số trong lời gọi hàm để có thể
nhận bất kỳ kiểu địa chỉ nào của tham số được truyền
for(i = 0; i < 10; i ++) Ví dụ:
printf(“%d ”, p[i]); void * p, *q;
for(i = 0; i < 10; i ++) int n; float x;

printf(“%d ”, *(p++) ); p = & n; q= & x; \\Các câu lệnh hợp lệ


311 312

311 312

78
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.2 Con trỏ 5.2 Con trỏ

Câu hỏi 1 Câu hỏi 2

#include<stdio.h> #include<stdio.h>
int main() 30 int main(){
{ int arr[2][2][2] = {10, 2, 3, 4, 5, 6, 7, 8};
int a=3, *p; int *p, *q;

p = &a; p = &arr[1][1][1];
q = (int *) arr;
printf("%d\n", a * *p * a + *p); 8, 5
printf("%d, %d\n", *p, *(q+4) );
return 0;
return 0;
}
}

313 314

313 314

Chương 5: Mảng, con trỏ và xâu ký tự


Chương 5: Mảng, con trỏ và xâu ký tự
5.3 Xâu ký tự

Nội dung chính Khái niệm xâu ký tự


1. Mảng
• Xâu kí tự (string) là một dãy các kí tự viết
• Khái niệm
• Khai báo và sử dụng liên tiếp nhau
• Các thao tác thường gặp – Độ dài xâu là số kí tự có trong xâu
2. Con trỏ – Xâu không có kí tự nào: Xâu rỗng
• Khái niệm và cách khai báo
• Toán tử địa chỉ (&), toán tử nội dung (*) • Ví dụ: “Tin hoc”, “String”
• Phép toán trên con trỏ • Lưu trữ: kết thúc xâu bằng kí tự ‘\0’ hay
• Con trỏ và mảng NULL (mã ASCII là 0)
3. Xâu ký tự
• Khái niệm. khai báo và sử dụng
• Các hàm xử lý ký tự và xâu ký tự ‘T’ ‘i’ ‘ n ‘ ‘ ‘ ‘h’ ‘o’ ‘c’ ‘\0’
• Mảng xâu ký tự 315 316

315 316

79
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.3 Xâu ký tự 5.3 Xâu ký tự

Khái niệm xâu ký tự→Lưu ý Khai báo


• Xâu kí tự >< mảng kí tự char tên_xâu [số_kí_tự_tối_đa];
– Tập hợp các kí tự viết liên tiếp nhau
• Truy nhập một phần tử của xâu ký tự (là một ký tự) • Để lưu trữ một xâu có n kí tự chúng ta cần
giống như truy nhập vào một phần tử của mảng: một mảng có kích thước n+1
Tên[Chỉ_số]
– Phần tử cuối cùng chứa ký tự NULL
– Xâu kí tự có kí tự kết thúc xâu, mảng kí tự
không có kí tự kết thúc xâu Ví dụ
• Xâu kí tự độ dài 1 >< kí tự (“A” =’A’ ?) • Để lưu trữ xâu “Tin hoc” chúng ta phải khai
– ‘A’ là 1 kí tự, được lưu trữ trong 1 byte báo xâu có số phần tử tối đa ít nhất là 8
– “A” là 1 xâu kí tự, ngoài kí tự ‘A’ còn có kí tự ‘\0’ char str[8] = “Tin hoc”;
=> được lưu trữ trong 2 byte
‘T’ ‘i’ ‘ n ‘ ‘ ‘ ‘h’ ‘o’ ‘c’ ‘\0’
317 318

317 318

Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.3 Xâu ký tự 5.3 Xâu ký tự

Truy nhập phần tử của xâu Ví dụ: Nhập xâu và đếm số ký tự ‘*’
Giống như truy nhập tới một phần tử của #include <stdio.h> Tính chiều dài của xâu
mảng ký tự void main(){ d=0;
char Str[100]; while(Str[d] != '\0') d++;
tên_xâu [chỉ_số_của_kí_tự] int d=0, i=0;
Ví dụ: char Str[10] = “Tin hoc”; printf("Nhap xau ky tu: "); gets(Str);
while(Str[i] != '\0'){
T i n - h o 1 \0
c \0 ? ? if(Str[i]=='*')
d++;
Str[0] → ‘T’ Str[3] = ‘-’; i++;
Str[3] → ‘ ’ Str[7] = ‘ ’; }
Str[7] → ‘\0 ‘ Str[8] = ‘1 ‘ ; printf("Ket qua : %d",d);
Str[8] → ? Str[9] = ‘\0’; Str: Tin-hoc 1 }
319 320

319 320

80
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.3 Xâu ký tự 5.3 Xâu ký tự

Ví dụ: Nhập câu và đưa ra dưới dạng cột Các hàm xử lý ký tự


1. #include <stdio.h>
2. void main(){
3. char S[100];
4.
5.
int i=0;
printf("Nhap xau: "); gets(S);
Tệp tiêu đề : ctype.h
6. while(S[i] != '\0'){ //32 là mã ASCII của phím space
7.
8.
if(S[i] != 32 && S[i+1]==32) printf("%c\n",S[i]);
else if(S[i] != 32) printf("%c",S[i]);
#include <ctype.h>
9. i++;
10. }
11. printf(“\n\n”); Đếm số từ, nếu các từ
12. } được cách nhau bởi dấu
phân cách
321 322

321 322

Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.3 Xâu ký tự 5.3 Xâu ký tự

Các hàm xử lý ký tự→Chuyển đổi chữ hoa/thường Các hàm xử lý ký tự →Kiểm tra chữ hoa/thường
• int toupper(char ch):
• int islower(char ch)
– Chuyển kí tự thường thành kí tự hoa
toupper(‘a’) => ‘A’ – Kiểm tra chữ thường:
• int tolower(char ch) • Hàm trả về giá trị khác 0 nếu ch là chữ
thường, ngược lại trả về 0
– Chuyển kí tự hoa thành kí tự thường
• Ví dụ: printf("%d ",islower('A'));  0
tolower(‘B’) => ‘b’
• int isupper(char ch):
Ví dụ
do{
– Kiểm tra chữ hoa:
………. • Hàm trả về giá trị khác 0 nếu ch là chữ hoa,
ngược lại trả về 0
printf(“Tiep tuc <C/K>? :”); fflush(stdin);
}while(toupper(getche()) !='K'); • Ví dụ: printf("%d ",isupper('A'));  ≠ 0 (1 !?)
323 324

323 324

81
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.3 Xâu ký tự 5.3 Xâu ký tự

Các hàm xử lý ký tự →Kiểm tra chữ cái/chữ số Khái niệm xâu ký tự→Kiểm tra ký tự đặc biệt
• int isalpha(char ch): • int iscntrl(char ch)
– Kiểm tra kí tự trong tham số có phải chữ cái – Kiểm tra kí tự điều khiển (0-31).
không (‘a’…’z’,’A’,..’Z’). Hàm trả về khác 0 nếu – Hàm trả về khác 0 nếu đúng, ngược lại trả về
đúng, ngược lại trả về giá trị bằng 0 giá trị bằng 0
– Ví dụ: printf("%d ",isalpha('A'));  ≠ 0 (1 !?)
• int isspace(char ch)
• int isdigit(char ch):
– Kiểm tra kí tự dấu cách (mã 32), xuống dòng
– Kiểm tra kí tự trong tham số có phải chữ số
(‘\n’ 10), đầu dòng (‘\r’ 13), tab ngang (‘\t’ 9), tab
(‘0‘,‘1‘,..‘9‘) không. Hàm trả về khác 0 nếu đúng,
dọc (‘\v’ 11).
ngược lại trả về giá trị bằng 0
– Ví dụ: printf("%d ",isdigit('A'));  0 – Hàm trả về khác 0 nếu đúng, ngược lại trả về
giá trị bằng 0
325 326

325 326

Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.3 Xâu ký tự 5.3 Xâu ký tự

Ví dụ: Nhập xâu, chuyển thành xâu chữ hoa Ví dụ: Nhập xâu và đếm từ, phân cách bởi dấu trắng
1. #include <stdio.h> #include <stdio.h>
2. #include <ctype.h> #include <conio.h>
#include <ctype.h>
3. void main(){ int main(){
4. int i =0; char Str[100]; int d=0, i=0;
5. char S[50]; printf("Nhap xau ky tu: "); gets(Str);
if(Str[0] == '\0') printf(“ Xau rong ");
6. printf("Nhap mot xau: "); gets(S); else{
7. printf("\n\nXau ban dau : %s. ",S); if( ! isspace(Str[0]) ) d=1;
8. while(S[i] != '\0'){ i=1;
while(Str[i] != '\0'){
9. S[i] = toupper(S[i]);
if( isspace(Str[i-1] ) && (! isspace(Str[i])) ) d++;
10. i = i + 1; i++;
11. } }
printf("Ket qua : %d",d);
12. printf("Xau ket qua : %s",S);
}
13. } }
327 328

327 328

82
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.3 Xâu ký tự 5.3 Xâu ký tự

Các hàm xử lý xâu ký tự Các hàm xử lý xâu ký tự


Vào/ra xâu ký tự Tệp tiêu đề: string.h
• Tệp tiêu đề: stdio.h
• Nhập xâu kí tự #include <string.h >
– gets(tên_xâu); Chú ý:
– scanf(“%s”,&tên_xâu); char str[100] = “Hello world”;
• Hiển thị xâu kí tự char * p = str;
– puts(tên_xâu);
• p là con trỏ, trỏ tới mảng các ký tự/xâu ký tự
– printf(“%s”,tên_xâu);
p+6 : (Phép tính toán trên con trỏ), cũng là xâu ký
tự. p+6 trỏ tới xâu “world”
Sự khác nhau giữa gets và scanf?
329
• Xâu ký tự, có thể được khai báo char * 330

329 330

Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.3 Xâu ký tự 5.3 Xâu ký tự

Các hàm xử lý xâu ký tự Các hàm xử lý xâu ký tự


size_t strlen(char * xâu) int strcmp(char * xâu_1, char * xâu_2)
– Trả về độ dài xâu – So sánh hai xâu.
– Trả về giá trị 0 nếu hai xâu giống nhau;
printf("%d ",strlen("Hello world"));  11 – Giá trị < 0: xâu_1 < xâu_2
char * strcpy(char * đích, char * nguồn) – Giá trị >0: xâu_1 > xâu_2
– sao chép nội dung xâu nguồn vào xâu đích,
Ví dụ
trả về giá trị xâu nguồn char Str[20];
char Str[20]; strcpy(Str,“hello“);
printf(“%d”, strcmp(Str,”hello”));→0
printf("%s ",strcpy(Str,"Hello"));  Hello
printf(“%d”, strcmp(Str,”hello!”); →-1 (!?)
printf("%s", Str);  Hello
printf(“%d”, strcmp(Str,”Hello”); → 1 (!?)
Chú ý: Phép gán Str = “Hello” là không hợp lệ
331 332

331 332

83
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.3 Xâu ký tự 5.3 Xâu ký tự

Các hàm xử lý xâu ký tự Các hàm xử lý xâu ký tự


char * strcat(char * xđích, char * nguồn) char * strchr (char * s, int c)
– Ghép nối xâu nguồn vào ngay sau xâu đích, trả – Trả về con trỏ trỏ tới vị trí xuất hiện đầu tiên
lại xâu kết quả của ký tự c trong s. Nếu không có trả về con
Ví dụ trỏ null
char Str[20]; strcpy(Str,"Hello world");
strcpy(Str,"Hello "); printf("%s ",strchr(Str,‘o'));  o world
printf("%s ",strcat(Str,"world"));  Hello world char* strstr(char * s1, char * s2)
printf("\n%s",Str);  Hello world – Trả về con trỏ trỏ tới vị trí xuất hiện đầu tiên
của chuỗi s2 trong s1. Nếu không tồn tại, trả
về con trỏ null
printf("%s ",strstr(Str,”llo”));  llo world
333 334

333 334

Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.3 Xâu ký tự 5.3 Xâu ký tự

Các hàm xử lý xâu ký tự (tiếp) Ví dụ 1: Nhập 2 xâu cho biết số lần xuất hiện xâu 1 trong xâu 2
1. #include <stdio.h>
Tệp tiêu đề: stdlib.h 2. #include <string.h>
• int atoi(char * str): 3. void main(){
– Chuyển một xâu kí tự thành một số nguyên 4. int d =0;
tương ứng 5. char S1[50],S2[20], *p;
– Ví dụ: atoi(“1234”) →1234 6. printf("Nhap xau thu nhat: "); gets(S1);
• int atol(char * str): 7. printf("Nhap xau thu hai: "); gets(S2);
8. p = strstr(S1,S2);
– Chuyển xâu kí tự thành số long int
9. while(p !=NULL ){
• float atof(char * str): 10. d = d + 1;
– Chuyển xâu kí tự thành số thực 11. p = strstr(p+1,S2);//vi tri tim kiem ke tiep
– Ví dụ: atof(“123.456E-2”) →1.23456 12. }
13. printf("Xau \“ %s\" x/hien trong xau \"%s \“ %d lan",S2,S1,d);
• Thất bại cả 3 hàm: trả về 0 335 14. } 336

335 336

84
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.3 Xâu ký tự 5.3 Xâu ký tự

Ví dụ 2: Kiểm tra xâu đối xứng Ví dụ 3: Đảo ngược xâu ký tự


#include<stdio.h> #include<stdio.h>
#include<string.h> #include<string.h>
main(){ main(){
char s[20]; char s[100],c;
int i,n; int i, n;
printf("Nhap vao xau ki tu: ");gets(s); printf("Nhap xau: ");gets(s);
n=strlen(s); n =strlen(s);
for(i=0;i<n/2;i++) for(i=0;i <n/2;i++){
if(s[i]!=s[n-1-i]) c = s[i];
break; s[i] = s[n-i-1];
if(i==n/2) s[n-i-1]=c;
printf("Xau doi xung"); }
else printf("%s",s);
printf("Xau khong doi xung"); }
}
337 338

337 338

Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.3 Xâu ký tự 5.3 Xâu ký tự

Ví dụ 4: Đếm số lần xuất hiện chữ cái trong xâu Mảng xâu ký tự
#include<stdio.h>
#include<ctype.h> • Xâu ký tự có thể là kiểu phần tử của mảng
#include<string.h> • Khai báo
main(){
char s[20]; char DS[100][30];
int dem[26] = {}; Mảng có tối đa 100 phần tử, các phần tử là
int i,n;
puts("Nhap vao xau ki tu:");gets(s); xâu có độ dài tối đa 30
n=strlen(s); • Sử dụng
for(i=0;i<n;i++)
if(isalpha(s[i])) – Như một mảng bình thường
dem[ tolower(s[i ]) - 'a‘ ]++; – Mỗi phần tử mảng được sử dụng như một xâu
for(i=0;i<26;i++) ký tự
if(dem[i]!=0)
printf("Ki tu %c xuat hien %d lan\n",'a'+i,dem[i]);
} 339 340

339 340

85
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.3 Xâu ký tự 5.3 Xâu ký tự

Ví dụ: Nhập vào DSSV cho tới khi gặp tên rỗng, in DS Ví dụ→Kết quả thực hiện
#include <stdio.h> for(n = 0; n <100; n++){
#include <string.h> printf("Ten sinh vien[%d]: ",n+1); gets(DS[n]);
void main(){ if(DS[n][0] ='\x0') break;
int i, n; //n++;
char DS[100][30]; }
printf("Nhap DSSV (<100), go Enter de thoat..\n");
n =0;
do{
printf("Ten sinh vien[%d]: ",n+1); gets(DS[n]);
if(DS[n][0] !='\x0') n++;
else break;
if(strcmp(DS[n],""))n++
if(n==100) break;
}while(1); if(strlen(DS[n])>0) n++
printf("\n\nDS sinh vien vua nhap \n");
for(i=0;i<n;i++) printf("%s\n",DS[i]);
341
} 341 342

341 342

Chương 5: Mảng, con trỏ và xâu ký tự


Nhập dãy (<100) xâu cho tới khi gặp xâu “***” 5.3 Xâu ký tự

Đưa ra màn hình xâu có độ dài lớn nhất Ví dụ: Nhập vào DS sinh viên, in ra DS đã sắp xếp
1. #include <stdio.h>
#include <stdio.h>
2. #include <string.h>
3. void main(){ #include <string.h>
4. int i, n = 0, d=0; void main(){
5. char DS[100][30], s[30]="";
6. do{
int i, j, N;
7. printf("Nhap xau thu [%d]: ",n+1); gets(DS[n]); char DS[100][30], str[30];
8. if( strcmp(DS[n],"***")) n= n + 1;//Không tính xâu “***” //Nhap DS sinh viên
9. else break;
10. }while(1); printf("So sinh vien : "); scanf("%d",&N);
11. for(i = 0; i < n; i++) fflush(stdin);
12. if(strlen(DS[i]) > d){
for(i=0;i < N;i++){
13. d = strlen(DS[i]);
14. strcpy(s,DS[i]); printf("Ten sinh vien[%d]: ",i);
15. } gets(DS[i]);
16. printf("\n\nXau dai nhat la: %s, co do dai :%d\n",s,d);
17. }
}
343 344

343 344

86
Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.3 Xâu ký tự 5.3 Xâu ký tự

Ví dụ: Nhập vào DS sinh viên, in ra DS đã sắp xếp Ví dụ→Kết quả thực hiện
//So sánh theo Họ+đệm+tên
for(i = 0; i < N - 1; i ++)
for(j = i +1; j < N; j ++)
if(strcmp(DS[i],DS[j]) > 0){
strcpy(str,DS[i]);
strcpy(DS[i],DS[j]);
strcpy(DS[j],str);
}
//In danh sách đã sắp xếp
printf("\nDS sinh vien vua nhap \n");
for(i=0;i < N;i++)
printf("%s\n",DS[i]);
}//main
345 346

345 346

Chương 5: Mảng, con trỏ và xâu ký tự Chương 5: Mảng, con trỏ và xâu ký tự
5.3 Xâu ký tự 5.3 Xâu ký tự

Ví dụ : Sắp xếp theo tên Ví dụ


//Sap xep theo tên
char ten_i[30],ten_j[30];
for(i = 0; i < N - 1; i ++)
for(j = i +1; j < N; j ++){
strcpy(ten_i,strrchr(DS[i],32));//trích ra từ cuối
strcpy(ten_j,strrchr(DS[j],32));//của xâu họ&tên
if(strcmp(ten_i,ten_j) > 0){
strcpy(str,DS[i]);
strcpy(DS[i],DS[j]);
strcpy(DS[j],str);
}
}
347 348

347 348

87
Phần 3: Lập trình C
Chương 5: Mảng, con trỏ và xâu ký tự
5.3 Xâu ký tự

Bài tập Nội dung chính


1. Nhập vào 2 xâu S1, S2 và một số nguyên k. Hãy • Chương 1: Tổng quan về ngôn ngữ C
chèn xâu S1 vào S2 và đưa ra màn hình (giả thiết
xâu S2 được khai báo đủ lớn) • Chương 2: Kiểu dữ liệu và biểu thức trong C
2. Một văn bản gồm không quá 60 dòng, mỗi dòng • Chương 3: Vào ra dữ liệu
không quá 80 ký tự. Hãy viết chương trình thực
hiện nhập vào một văn bản, sau đó • Chương 4: Cấu trúc điều khiển
1. Nhập vào xâu s và chỉ ra vị trí xuất hiệncủa xâu S
trong văn bản nếu có. • Chương 5: Mảng, con trỏ và xâu ký tự
2. Thay tất cả các chuỗi « hanoi » (nếu có) bằng chuỗi
« HANOI »
• Chương 6: Cấu trúc
3. Đếm xem trong văn bản có bao nhiêu từ (các từ phân • Chương 7: Hàm
cách bởi dấu cách)
4. Tính tần xuất xuất hiện của các từ trong văn bản • Chương 8: Tệp dữ liệu
349 350

349 350

Chương 6: Cấu trúc


Chương 6: Cấu trúc
6.1 Khái niệm cấu trúc

Nội dung chính Ví dụ → Bài toán quản lý thí sinh thi đại học
1. Khái niệm cấu trúc Để quản lý cần lưu trữ các thông tin
• Khái niệm • Số báo danh: Số nguyên không dấu
2. Khai báo cấu trúc • Họ tên sinh viên: Chuỗi ký tự không quá 30
• Khái báo kiểu cấu trúc • Khối thi: Ký tự (A,B,C..)
• Khai báo biến cấu trúc • Tổng điểm 3 môn thi: kiểu thực
• Định nghĩa kiểu dữ liệu với typedef Do vậy với mỗi sinh viên cần các biến
3. Xử lý dữ liệu cấu trúc unsigned SBD;
• Truy nhập các trường dữ liệu char Ten[30];
• Phép gán giữa các biến cấu trúc char KhoiThi;
float KetQua;
4. Một số ví dụ
351 352

351 352

88
Chương 6: Cấu trúc Chương 6: Cấu trúc
6.1 Khái niệm cấu trúc 6.1 Khái niệm cấu trúc

Ví dụ → Bài toán quản lý thí sinh thi đại học (tiếp) Ví dụ → Bài toán quản lý thí sinh thi đại học (tiếp)

Để quản lý danh sách (dưới 1000) thí sinh dự DS_SBD


456
thi, cần nhiều mảng rời rạc 123 789

DS_Ten Mảng ký tự
#define MAX 1000 Nguyễn Nguyễn Trần An
Văn An Hoàng Nghĩa

unsigned DS_SBD[MAX];
DS_KhoiThi
char DS_Ten[MAX][30]; A D A
char DS_KhoiThi[MAX];
DS_KetQua
float DS_KetQua[MAX]; 24.5 28.5 22.0

Biến điều khiển


TS: TS: TS: i+2
i i+1 dùng duyệt mảng
353 354

353 354

Chương 6: Cấu trúc Chương 6: Cấu trúc


6.1 Khái niệm cấu trúc 6.1 Khái niệm cấu trúc

Ví dụ → Vấn đề & giải pháp Khái niệm


Dùng nhiều mảng • Cấu trúc là kiểu dữ liệu phức hợp, do người
- Khó quản lý, dễ nhầm lẫn dụng tự định nghĩa
- Không thể hiện cấu trúc thông tin dành cho từng – Kiểu cấu trúc bao gồm nhiều thành phần có thể
thí sinh
Cấu trúc thông tin thuộc các kiểu dữ liệu khác nhau
Mảng các cấu
dành cho một thí sinh – Các thành phần: gọi là trường dữ liệu (field)
trúc thông tin
dành cho thí sinh THÔNG TINTHÍ
THÍSINH
SINH
THÔNG TIN – Các thành phần, không được truy nhập theo chỉ
THÔNG SốSốbáo
báodanh:…………………
TINTHÍ
danh:…....123………
THÍSINH
SINH
số (như mảng) mà theo tên của trường.
THÔNG HọvàvàTên:……………………
TIN Tên:..Nguyễn Văn An..
Số báo
Họ
danh:…………………
Có thể coi một biến cấu trúc là một tập hợp của một
Khối
Số báo danh:…………………thi:…………A………….
Khối thi:……………………….
HọvàvàTên:……………………
Tên:……………………
Kếtquả:……………………….
quả:………24.5……….
hay nhiều biến rời rạc, thường có kiểu khác nhau
Họ Kết
Khốithi:……………………….
thi:………………………. thành một biến có một tên duy nhất để dễ dàng
Khối
Kếtquả:……………………….
quả:………………………. Mỗi phần tử của mảng quản lý và sử dụng
Kết là một cấu trúc thông355
tin 356

355 356

89
Chương 6: Cấu trúc
Chương 6: Cấu trúc
6.1 Khái niệm cấu trúc

Khái niệm → Ví dụ Nội dung chính


• Kết quả học tập của sinh viên 1. Khái niệm cấu trúc
– TenSV: Chuỗi ký tự • Khái niệm

– MaSV: Chuỗi số/ số nguyên 2. Khai báo cấu trúc


– Điem: Số thực • Khái báo kiểu cấu trúc
• Khai báo biến cấu trúc
• Điểm trong mặt phẳng • Định nghĩa kiểu dữ liệu với typedef
– Tên điểm: Ký tự (A, B, C..)
3. Xử lý dữ liệu cấu trúc
– Hoành độ: Số thực • Truy nhập các trường dữ liệu
– Tung độ: Số thực • Phép gán giữa các biến cấu trúc
4. Một số ví dụ
357 358

357 358

Chương 6: Cấu trúc Chương 6: Cấu trúc


6.2 Khai báo cấu trúc 6.2 Khai báo cấu trúc

Khai báo kiểu cấu trúc Khai báo kiểu cấu trúc → Ví dụ
struct Tên_kiểu_cấu_ trúc { Thẻ sinh viên struct SinhVien{
Số hiệu:…(Chuỗi ký tự)..
<Khai báo các trường dữ liệu> char SHSV[10];
Tên sinh viên: (Chuỗi ký tự) char Ten[30];
};
Năm sinh:…(Số nguyên)… int NS;
• struct: từ khóa, cho phép người dùng khai báo Khóa:……(Số nguyên)……. int Khoa;
kiểu dữ liệu mới: kiểu cấu trúc char Lop [10];
Lớp:…… :.(Chuỗi ký tự). …
• Tên_kiểu_cấu_truc: Tên của kiểu cấu trúc do };
người dùng tự định nghĩa
– Tuân theo nguyên tắc đặt tên đối tượng trong C Point2D
• Khai báo các trường dữ liệu: Danh sách các struct Point{
Hoành độ (x)…(Số thực)..
khai báo thành phần (trường:field) của cấu trúc float x, y;
– Giống khai báo biến Tung độ (y)…..(Số thực).. };
– Các trường có thể có kiểu bất kỳ 359 360

359 360

90
Chương 6: Cấu trúc Chương 6: Cấu trúc
6.2 Khai báo cấu trúc 6.2 Khai báo cấu trúc

Khai báo biến cấu trúc Khai báo biến cấu trúc → Cú pháp
Tồn tại định nghĩa kiểu cấu trúc
• Khai báo kiểu cấu trúc nhằm tạo định nghĩa
struct Kiểu_cấu_ trúc Tên_biến;
toàn thể cho các cấu trúc sẽ được dùng
Khai báo trực tiếp
sau này
struct {
– Không cung cấp không gian nhớ cho kiểu
<Khai báo các trường dữ liệu>
• Khai báo biến cấu trúc nhằm yêu cầu
}Tên_biến;
chương trình tạo vùng nhớ để lưu trữ các
dữ liệu cho biến cấu trúc Kết hợp với khai báo kiểu

– Chứa dữ liệu của các trường của cấu trúc struct Kiểu_cấu_ trúc {
<Khai báo các trường dữ liệu>
}Tên_biến;
361 362

361 362

Chương 6: Cấu trúc Chương 6: Cấu trúc


6.2 Khai báo cấu trúc 6.2 Khai báo cấu trúc

Khai báo biến cấu trúc → Ví dụ Khai báo biến cấu trúc →Chú ý
Tồn tại định nghĩa kiểu cấu trúc
Các cấu trúc có thể được khai báo lồng nhau
struct SinhVien SV1, SV2, Thu khoa;
struct diem_thi {
Khai báo trực tiếp
float dToan, dLy, dHoa;
struct {
}
float x, y; //Tọa độ trên mặt phẳng
struct thi_sinh{
}A, B; //Khai báo 2 điểm A, B
char SBD[10];
Kết hợp với khai báo kiểu
char ho_va_ten[30];
struct Point_3D{
struct diem_thi ket_qua;
float x, y, z;// Tọa độ không gian
} thi_sinh_1, thi_sinh_2;
}A, B;
363 364

363 364

91
Chương 6: Cấu trúc Chương 6: Cấu trúc
6.2 Khai báo cấu trúc 6.2 Khai báo cấu trúc

Khai báo biến cấu trúc →Chú ý Khai báo biến cấu trúc →Chú ý

Có thể khai báo trực tiếp các trường dữ liệu Có thể gán giá trị khởi đầu cho một biến cấu
của một cấu trúc bên trong cấu trúc khác trúc, theo nguyên tắc như kiểu mảng
struct thi_sinh{ Ví dụ: struct SinhVien{
struct Date{ char Ten[20];
char SBD[10];
int day; struct Date{
char ho_va_ten[30]; int month; int day;
struct{ int year; int month;
}; int year;
float dToan, dLy, dHoa; } NS;
struct SinhVien{
} ket_qua; char Ten[30]; } SV = {“Tran Anh", 20,12,1990 };
} thi_sinh_1, thi_sinh_2; struct Date NS;
} SV = {“Tran Anh", 20, 12, 1990 };
365 366

365 366

Chương 6: Cấu trúc Chương 6: Cấu trúc


6.2 Khai báo cấu trúc 6.2 Khai báo cấu trúc

Định nghĩa kiểu dữ liệu với typedef Định nghĩa kiểu dữ liệu với typedef
typedef <tên_cũ> <tên_mới>; Thường được kết hợp với kiểu cấu trúc để
Mục đích khai báo một bí danh cho một cấu trúc
– Giúp khai báo trở nên quen thuộc và ít bị sai hơn
• Đặt tên mới đồng nghĩa với tên của một kiểu
typedef struct { //Định nghĩa một cấu trúc
dữ liệu đã được định nghĩa
char SHSV[10];
– Thường được sử dụng cho kiểu cấu trúc
char Ten[30];
• Giúp cho khai báo trở nên quen thuộc và ít bị sai hơn
int NS;
Ví dụ int Khoa;
typedef char Str80[80] ;
char Lop [10];
typedef long mask;
} SinhVien; //Đặt tên cho cấu trúc là SinhVien
Str80 str="Bonjour tout le monde !";
mask a, b; SinhVien SV; //Tạo một biến cấu trúc
367 368

367 368

92
Chương 6: Cấu trúc Chương 6: Cấu trúc
6.2 Khai báo cấu trúc 6.2 Khai báo cấu trúc

Định nghĩa kiểu dữ liệu với typedef →Chú ý Định nghĩa kiểu dữ liệu với typedef →Chú ý
Cho phép đặt tên mới trùng với tên cũ typedef struct point_2D {
Ví dụ typedef struct { float x, y;
struct point_3D{ float x, y, z; }point_2D, diem_2_chieu, ten_bat_ki;
float x, y, z; }point_3D; point_2D X;
} point_3D M; diem_2_chieu Y;
struct point_3D M; point_3D N; ten_bat_ki Z;
typedef struct point_3D point_3D; Chú ý:
point_3D N; point_2D, diem_2_chieu, ten_bat_ki là
các tên cấu trúc, không phải tên biến
369 370

369 370

Chương 6: Cấu trúc


Chương 6: Cấu trúc
6.3 Xử lý dữ liệu cấu trúc

Nội dung chính Truy cập các trường dữ liệu


1. Khái niệm cấu trúc • Cú pháp
• Khái niệm
tên_biến_cấu_trúc.tên_trường
2. Khai báo cấu trúc • Lưu ý
• Khái báo kiểu cấu trúc
– Dấu “.” là toán tử truy cập vào trường
• Khai báo biến cấu trúc
dữ liệu trong cấu trúc
• Định nghĩa kiểu dữ liệu với typedef
– Nếu trường dữ liệu là một cấu trúc =>
3. Xử lý dữ liệu cấu trúc sử dụng tiếp dấu “.” để truy cập vào
• Truy nhập các trường dữ liệu thành phần mức sâu hơn
• Phép gán giữa các biến cấu trúc
4. Một số ví dụ
371 372

371 372

93
Chương 6: Cấu trúc Chương 6: Cấu trúc
6.3 Xử lý dữ liệu cấu trúc 6.3 Xử lý dữ liệu cấu trúc

Ví dụ Ví dụ
#include <stdio.h>
Bài toán: Xây dựng một cấu trúc biểu diễn
void main(){
struct{ điểm trong không gian 2 chiều.
char Ten[20]; – Nhập giá trị cho một biến kiểu cấu trúc này
struct Date{ – Hiển thị giá trị các trường dữ liệu của biến này
int day;
ra màn hình.
int month;
int year; Thực hiện:
} NS; – Cấu trúc gồm: tên điểm, tọa độ x, tọa độ y
} SV = {"Tran Anh", 20,12, 1990 };
– Nhập, hiển thị từng trường của biến cấu trúc
printf(" Sinh vien %s (%d/%d/%d)", như các biến dữ liệu khác
SV.Ten,SV.NS.day,SV.NS.month,SV.NS.year);
}
373 374

373 374

Chương 6: Cấu trúc Chương 6: Cấu trúc


6.3 Xử lý dữ liệu cấu trúc 6.3 Xử lý dữ liệu cấu trúc

Ví dụ Phép gán giữa các biến cấu trúc


#include<stdio.h> • C cho phép gán hai biến cấu trúc cùng kiểu:
#include<conio.h>
typedef struct{ Biến_cấu_trúc_1 = biến_cấu_trúc_2
char ten[5];
int x,y; • Ví dụ
}toado;
– Xây dựng cấu trúc gồm họ tên và điểm TĐC của
void main(){
toado t; sinh viên
printf("Nhap thong tin toa do\n"); – Khai báo 3 biến cấu trúc: a, b, c
printf("Ten diem: ");gets(t.ten); – Nhập giá trị cho biến a.
printf("Toa do x: ");scanf("%d",&t.x);
printf("Toa do y: ");scanf("%d",&t.y); – Gán biến a cho biến b
printf("Gia tri cac truong\n"); – gán từng trường của a cho c.
printf("%-5s%3d%3d\n",t.ten,t.x,t.y);
getch();
– So sánh a, b và c ?
} 375 376

375 376

94
Chương 6: Cấu trúc Chương 6: Cấu trúc
6.3 Xử lý dữ liệu cấu trúc 6.3 Xử lý dữ liệu cấu trúc

Ví dụ Ví dụ
#include<stdio.h> b=a; //Gán biến cấu trúc
typedef struct{ strcpy(c.hoten,a.hoten); //Gán từng trường
char hoten[20]; c.diem=a.diem;
int diem; printf(“Bien a: ");
}sinhvien; printf("%-20s%3d\n",a.hoten,a.diem);
void main(){ printf(“Bien b: ");
sinhvien a,b,c; printf("%-20s%3d\n",b.hoten,b.diem);
printf("Nhap thong tin sinh vien\n"); printf(“Bien c: ");
printf("Ho ten: ");gets(a.hoten); printf("%-20s%3d\n",c.hoten,c.diem);
printf("Diem:");scanf("%d",&a.diem); }
377 378

377 378

Chương 6: Cấu trúc


Chương 6: Cấu trúc
6.3 Xử lý dữ liệu cấu trúc

Ví dụ →Kết quả Nội dung chính


1. Khái niệm cấu trúc
• Khái niệm
2. Khai báo cấu trúc
• Khái báo kiểu cấu trúc
• Khai báo biến cấu trúc
• Định nghĩa kiểu dữ liệu với typedef
3. Xử lý dữ liệu cấu trúc
• Truy nhập các trường dữ liệu
• Phép gán giữa các biến cấu trúc
4. Một số ví dụ
379 380

379 380

95
Chương 6: Cấu trúc
6.4 Một số ví dụ Ví dụ 1
Một số ví dụ #include <stdio.h>
1. Nhập vào 2 số phức và đưa ra tổng và tích của chúng typedef struct {float re, im;} Complex;
void main(){
2. Nhập vào một danh sách (<100) sinh viên gồm họ tên, năm
Complex R, R1, R2;
sinh. Kết thúc nhập khi gặp SV có tên là rỗng
printf("Phan thuc & phan ao cho so thu nhat :");
• Đưa danh sách vừa nhập ra màn hình. scanf("%f%f",&R1.re,&R1.im);
• Đưa ra màn hình sinh viên lớn tuổi nhất printf("Phan thuc & phan ao cho so thu hai :");
3. Nhập danh sách có N (N < 100, nhập từ bàn phím) thí sinh scanf("%f%f",&R2.re,&R2.im);
gồm họ tên, số báo danh, khoa dự thi và điểm thi R.re = R1.re+R2.re; R.im = R1.im+R2.im; //phép cộng số ảo
• Đưa ra DSSV đã sắp xếp theo kết quả thi printf("(%.1f+%.1fi)+(%.1f+%.1fi)=(%.1f+%.1fi)\n",
R1.re,R1.im,R2.re,R2.im,R.re,R.im);
• Đưa ra danh sách sinh viên dự thi khoa CNTT có điểm
R.re = R1.re*R2.re - R1.im*R2.im; //nhân số ảo
thi từ 22.5 trở lên
R.im = R1.re*R2.im + R1.im*R2.re;
• Nhập vào một số báo danh và in ra họ tên, điểm thi và printf("(%.1f+%.1fi)*(%.1f+%.1fi)=(%.1f+%.1fi)\n",
khoa đăng ký của thí sinh nếu tìm thấy. Nếu không tìm R1.re,R1.im,R2.re,R2.im,R.re,R.im);
thấy thí sinh thì đưa ra thông báo « không tìm thấy »
}
381 382

381 382

Ví dụ 2 Ví dụ 2
1. #include <stdio.h> for(nfor(i =0;
=0;i<100;
n<100;i++){
n++){ 19. //In danh sach sinh vien
2. #include <string.h> printf("Nhap du lieu cho sinh vien %d: \n", n+1);
i+1);
20. printf("\n\n");
3. typedef struct{ printf("Ho ten : "); fflush(stdin); gets(SV[n].Ten);
gets(SV.Ten);
4. char Ten[30]; if (strlen(SV[n].Ten)
(strlen(SV.Ten) ==0) ==0)
break;
break; 21. printf(" HO & TEN NAM SINH\n");
5. int NS; printf("Nam sinh :");scanf("%d", &SV[n].NS);
&SV.NS); 22. for(i=0; i < n;i++)
6. }SinhVien; } DS[n] = SV; n = n + 1;
} 23. printf("%-3d%-30s %6d\n",i+1,DS[i].Ten,DS[i].NS);
7. void main(){
8. SinhVien DS[100], SV; 24. printf("\n\n");
9. int n=0,i; 25. //Tim sinh vien lon tuoi nhat
10. do{
11. fflush(stdin); 26. SV = DS[0];
12. printf("Nhap du lieu cho sinh vien %d: \n", n+1); 27. for(i=0; i < n;i++)
13. printf("Ho ten : "); gets(SV.Ten); 28. if(DS[i].NS < SV.NS)
14. if (strlen(SV.Ten) >0) {
15. printf("Nam sinh :");scanf("%d", &SV.NS);
29. SV = DS[i];
16. DS[n] = SV; n = n + 1; 30. printf("Sinh vien: %s sinh nam: %d lon tuoi nhat",SV.Ten,SV.NS);
17. } 31. }//main
18. } while (strlen(SV.Ten) > 0);
383 384

383 384

96
Ví dụ 2→Kết quả thực hiện Ví dụ 3 (1/5): Khai báo cần thiết
1. #include <stdio.h>
2. #include <string.h>
3. typedef struct{
4. int SBD;
5. char Ten[30];
6. char Khoa[10];
7. float Diem;
8. }ThiSinh;
9. void main(){
10. ThiSinh DS[100], SV;
11. int N, i, j, d=0, SBD;
12. char Ch; //Sử dụng trong thực hiện tìm kiếm nhiều lần

385 386

385 386

Ví dụ 3 (2/5): Nhập dữ liệu từ bàn phím Ví dụ 3 (3/5): Danh sách sắp xếp theo điểm thi
13. printf("Nhap so thi sinh : "); scanf("%d",&N); 26. for(i=0; i < N - 1; i ++) //Sắp xếp DS theo điểm thi
14. for ( i=0; i < N; i++ ){ 27. for(j=i+1; j < N; j ++)
15. printf("Nhap du lieu cho thi sinh %d: \n", i+1); 28. if(DS[i].Diem > DS[j].Diem) {
16. printf("So bao danh : "); scanf("%d",&DS[i].SBD); 29. SV=DS[i];
17. printf("Ho ten : "); 30. DS[i]=DS[j];
18. fflush(stdin); gets(DS[i].Ten); 31. DS[j]=SV;
19. printf("Khoa dang ky : "); 32. }
20. fflush(stdin); gets(DS[i].Khoa); 33. printf("\n\n KET QUA THI \n\n");
21. printf("Ket qua thi : ");scanf("%f", &DS[i].Diem); 34. for(i=0; i < N; i ++)
22. printf("\n"); C scanf: floating point format not linked
35. printf("%-3d BKA- %-6d %-24s %-6s %-6.1f\n",
23. }//for ++d, DS[i].SBD, DS[i].Ten, DS[i].Khoa, DS[i].Diem);
24. printf("\n\nNhan phim bat ky de xem ket qua thi..."); 36. printf("\n\nNhan phim bat ky de xem DSSV khoa CNTT");
25. fflush(stdin); getch(); 37. fflush(stdin); getch();
387 388

387 388

97
Ví dụ 3 (4/5): Danh sách trúng tuyển khoa CNTT Ví dụ 3 (5/5): Tìm kiếm sinh viên
//Dua ra danh sach du thi khoa CNTT 45. do{
38. d = 0; 46. printf("\nNhap so bao danh can tim : "); scanf("%d",&SBD);
47. for(i=0; i < N; i++)
39. printf("\n\nDanh sach thi sinh trung tuyen khoa CNTT\n\n");
48. if(DS[i].SBD == SBD){
40. for(i=0; i < N; i ++) 49. printf("So bao danh : %d \n",SBD);
41. if(strcmp(DS[i].Khoa,"CNTT")==0 && DS[i].Diem >=22.5) 50. printf("Ho ten : %s \n",DS[i].Ten);
42. printf("%-3d BKA%-6d %-24s %-f\n", 51. printf("Khoa du thi : %s \n", DS[i].Khoa);
52. printf("So bao danh : %.1f \n",DS[i].Diem);
++d,DS[i].SBD,DS[i].Ten,DS[i].Diem);
53. break;
43. printf("\n\nNhan phim bat ky de bat dau tim kiem theo so bao danh"); 54. }
55. if (i == N)
44. fflush(stdin); getch();
56. printf("So bao danh %d khong ton tai\n",SBD);
57. printf("\nCo tiep tuc tim kiem nua khong (C/K) :");
58. }while(toupper(getche())!='K');
59. }//main
389 390

389 390

Ví dụ 3→Kết quả thực hiện Ví dụ 3→Kết quả thực hiện

391 392

391 392

98
Chương 6: Cấu trúc
Ví dụ 3→Kết quả thực hiện 6.4 Một số ví dụ

Bài tập
1. Lập trình đọc vào một danh sách không quá 100
sinh viên gồm: Họ tên, năm sinh
1. Đưa ra DS những sinh viên sinh năm 1990
2. Nhập tên sinh viên, cho biết năm sinh nếu tìm thấy
3. Đưa ra DSSV đã sắp xếp theo thứ tự ABC của họ và tên
2. Lập trình đọc vào DS thí sinh gồm Họ tên, điểm thi
3 môn Toán, Lý,Hóa, kết thúc nhập khi gặp sinh
viên có tên rỗng
1. Đọc tiếp vào một điểm chuẩn; đưa ra danh sách thí sinh
trúng tuyển (không có điểm liệt - 0)
2. Đưa ra thí sinh có kết quả thi cao nhất
3. Tìm điểm chuẩn, nếu chỉ lấy K SV, K nhập vào. Nếu có
393
nhiều người bằng điểm nhau; loại cả 394

393 394

Bài tập 1 Bài tập 1 (tiếp)


1. #include <stdio.h> 17. printf("\n\nSINH VIEN SINH NAM 1990\n\n");
2. #include <string.h>
3. typedef struct{ 18. for(i = 0; i < N; i ++)
4. char Ten[30]; 19. if(DS[i].NS ==1990)
5. int NS; 20. printf("%s\n",DS[i].Ten);
6. }SinhVien;
21. printf("\n\nTim SV : "); fflush(stdin); gets(Ten);
7. void main(){
8. SinhVien DS[100], SV; 22. for(int i=0;i <N; i++)
9. int N, i, j, d=0; 23. if(strcmp(Ten,DS[i].Ten)==0){
10. char ten[30]; 24. printf("Sinh vien: %s\nSinh nam %d\n", DS[i].Ten,DS[i].NS);
11. printf("Nhap so sinh vien : "); scanf("%d",&N); 25. d = d + 1;
12. for ( i=0; i < N; i++ ){
26. } Tìm kiếm chỉ theo tên ?
13. printf("Nhap du lieu cho sinh vien %d: \n", i+1); strcmp(Ten,strrchr(DS[i].Ten,32)+1))
14. printf("Ho ten : "); fflush(stdin);gets(DS[i].Ten); 27. if(d==0)
15. printf("Nam sinh : ");scanf("%d", &DS[i].NS); 28. printf("Khong co sinh vien: %s trong danh sach\n",Ten);
16. }
395 396

395 396

99
Chương 6: Cấu trúc
Bài tập 1 (tiếp) 6.3 Xử lý dư liệu cấu trúc

Bài tập 1 → Kết quả thực hiện


29. for(i = 0; i < N - 1; i ++) //sắp xếp theo pp lựa chọn
30. for(j = i+1; j < N; j ++)
31. if(strcmp(DS[i].Ten,DS[j].Ten) > 0){
32. SV= DS[i];
33. DS[i]=DS[j];
34. DS[j] = SV;
35. }
36.
37. printf("\n\n DANH SACH SAP XEP\n\n");
38. for(i = 0; i < N; i ++)
39. printf("%d %-20s %d \n",i+1, DS[i].Ten, DS[i].NS);
40. }//main

397 398

397 398

Bài tập 2 (1/5) Bài tập 2 (2/5)


#include <stdio.h> N = 0; //N chứa số sinh viên đã nhập
#include <string.h> do{
printf("\nNhap DL cho sv thu %d\n",N+1);
typedef struct{
char Ten[30]; printf("Ten SV : ");
struct{ fflush(stdin); gets(DS[N].Ten);
int T, L, H, S; //S = T+L+H if(strlen(DS[N].Ten)==0) //Độ dài bằng 0  xâu rỗng
} DT; break;
}SinhVien; else{
printf(« Nhập điểm thi T L H cua SV %s : ",DS[N].Ten);
void main(){
scanf("%d%d%d",&DS[N].DT.T,&DS[N].DT.L,&DS[N].DT.H);
SinhVien DS[100], TK, SV;
int N,i,j,K; DS[N].DT.S = DS[N].DT.T + DS[N].DT.L + DS[N].DT.H;
float C; N++;
}
}while(1);
399 400

399 400

100
Bài tập 2 (3/5) Bài tập 2 (4/5)
//In ra danh sách vừa nhập
//Tìm điểm của thủ khoa, bỏ qua tường hợp điểm liệt
printf("\n\n DANH SACH SINH VIEN\n\n");
TK = DS[0];
printf(" Ten SV Toan Ly Hoa Tong \n");
for(i = 1; i < N; i ++)
for(i = 0; i < N; i ++)
if(DS[i].DT.S > TK.DT.S)
printf("%-20s%5d%5d%5d%6d\n",DS[i].Ten,
DS[i].DT.T,DS[i].DT.L,DS[i].DT.H,DS[i].DT.S); TK = DS[i];
//Đưa ra danh sách thí sinh có điểm bằng điểm cao nhât
//In danh sách trúng tuyển theo điểm chuẩn
for(i = 0; i < N; i ++)
printf("\n\nDiem Chuan : ");scanf("%f",&C);
if(DS[i].DT.S == TK.DT.S)
printf("\n\n DANH SACH SINH VIEN TRUNG TUYEN \n\n");
for(i = 0; i < N; i ++) printf("\n\n THU KHOA: %s \n\n",TK.Ten);
if( (DS[i].DT.S >= C)&&(DS[i].DT.T*DS[i].DT.L*DS[i].DT.H>0))
printf("%s\n",DS[i].Ten);

401 402

401 402

Chương 6: Cấu trúc


Bài tập 2 (5/5) Bài tập

printf("\nSo nguoi trung tuyen:"); scanf("%d",&K);


Bài tập 1
for(i = 0; i < N - 1; i ++) //Sắp xếp theo tổng điểm thi Lập trình thực hiện các công việc sau
for(j = i+1; j < N; j ++)
▪ Đọc vào từ bàn phím một danh sách thuốc gồm
if(DS[i].DT.S < DS[j].DT.S ){
▪ Tên thuốc (chuỗi không quá 20 ký tự)
SV= DS[i];
▪ Năm hết hạn
DS[i]=DS[j];
DS[j] = SV; ▪ Số lượng còn
} ▪ Đơn giá
while((K>0)&&(DS[K-1].DT.S==DS[K].DT.S))K--; Kết thúc nhập khi gặp thuốc có tên »*** »
if(K>0){ ▪ Đưa danh sách thuốc ra màn hình
printf("Diem Chuan La : %4d",DS[K-1].DT.S); ▪ Đưa ra danh sách các thuốc đã hết hạn
printf("\n\n Danh Sach sinh vien trung tuyen \n"); ▪ Xóa khỏi danh sách những thuốc đã hết hạn.
for(i=0; i < K; i++) Đưa danh sách mới ra màn hình
printf("%s\n",DS[i].Ten);
}
▪ Tính tổng giá trị các thuốc đã hết hạn
}//main 403
▪ Đưa ra DS thuốc được sắp xếp theo năm hết hạn
404

403 404

101
Chương 6: Cấu trúc Chương 6: Cấu trúc
Bài tập Câu hỏi

Bài tập 2 1. Kết quả đưa ra màn hình


Cho một danh sách thành tích thi đấu bóng đá của 32 #include<stdio.h> a 12 Mai
đội tuyển bao gồm: Tên đội bóng, số bàn thắng, số typedef struct { b 12 Nam
bàn thua, số thẻ đỏ, số thẻ vàng int SHSV; c 13 Nam
Viết chương trình thực hiện char Ten[25];
d 13 Minh
• Nhập dữ liệu vào từ bàn phím }SV;
e 14 Minh
• Nhập vào tên đội bóng, void main(){
• Đưa ra thành thích của đội này SV DS[] = { {12, "Mai"},
• Nếu không tồn tại, thông báo: không tìm thấy {13, "Nam"},
• Tính và đưa ra màn hình số điểm của các đội nếu {14, "Minh"}};
• Mỗi bàn thắng được tính 10 điểm printf("%d ", DS[1].SHSV);
• Mỗi bàn thua bị phạt 5 điểm, mỗi thẻ vàng trừ 2 điểm, printf("%s\n", (*(DS+2)).Ten);
thẻ đỏ trừ 5 điểm }
405 406

405 406

Phần 3: Lập trình C


Chương 6: Cấu trúc
Câu hỏi

2. Chỉ ra câu trả lời đúng Nội dung chính


Chỉ ra khai báo hợp lệ cho biến SV có kiểu cấu trúc chỉ gồm
• Chương 1: Tổng quan về ngôn ngữ C
2 trường: Tên có kiểu xâu ký tự và NS có kiểu số nguyên

a struct SinhVien{ b struct {


• Chương 2: Kiểu dữ liệu và biểu thức trong C
char Ten[20]; char Ten[20]; • Chương 3: Vào ra dữ liệu
unsigned NS; unsigned NS;
}; } SinhVien; • Chương 4: Cấu trúc điều khiển
SinhVien SV; struct SinhVien SV; • Chương 5: Mảng, con trỏ và xâu ký tự
c struct { d typedef struct {
unsigned NS; unsigned NS;
• Chương 6: Cấu trúc
char Ten[20]; char Ten[20]; • Chương 7: Hàm
} SV; } SV;
• Chương 8: Tệp dữ liệu
e Không có câu trả lời nào đúng
407 408

407 408

102
Chương 7: Hàm
Chương 7: Hàm
7.1 Khái niệm hàm

Nội dung chính Khái niệm & Vai trò


1. Khái niệm hàm • Khái niệm
• Khái niệm chương trình con – Là một chương trình nằm trong một chương
• Phân loại: hàm và thủ tục trình lớn hơn nhằm thực hiện một nhiệm vụ cụ
2. Khai báo và sử dụng hàm thể
• Khai báo và sử dụng • Vai trò
3. Phạm vi của biến – Chia nhỏ chương trình ra thành từng phần để
quản lý
• Toàn cục và địa phương
• Phương pháp lập trình có cấu trúc
• Biến static, biến register
– Có thể sử dụng lại nhiều lần: printf(), scanf()…
4. Truyền tham số – Chương trình dễ dàng đọc và bảo trì hơn
• Truyền theo giá trị, truyền theo địa chỉ
409 410

409 410

Chương 7: Hàm
Chương 7: Hàm
7.1 Khái niệm hàm

Phân loại Nội dung chính


Hàm chuẩn – Có 1. Khái niệm hàm
Hàm trong thư viện
• Khái niệm chương trình con
(function)
Hàm (người dùng) • Phân loại: hàm và thủ tục
Chương Có trả về giá trị tự định nghĩa
trình con 2. Khai báo và sử dụng hàm
Thủ tục
• Khai báo và sử dụng
(procedure)
Không trả về giá trị 3. Phạm vi của biến
Ngôn ngữ lập trình C • Toàn cục và địa phương
• Chỉ cho phép khai báo chương trình con là hàm. • Biến static, biến register

• Sử dụng kiểu “void” với ý nghĩa “không là kiểu 4. Truyền tham số


dữ liệu nào cả” để chuyển thủ tục về dạng hàm • Truyền theo giá trị, truyền theo địa chỉ
411 412

411 412

103
Chương 7: Hàm Chương 7: Hàm
7.2 Khai báo và sử dụng hàm 7.2 Khai báo và sử dụng hàm

Ví dụ Định nghĩa hàm


#include<stdio.h> Cú pháp
int bp(int x){ Dòng đầu hàm
Khai báo int y; Kiểu_hàm Tên_hàm(DS khai báo tham số)
chương y = x * x;
trình con
return y; {

Thân hàm
} [<Các khai báo cục bộ>]
void main(){ [<Các câu lệnh>]
int i;
}
Gọi chương for (i=1; i< 20; i+=2)
trình con ra printf("%4d\n", bp(i));
thực hiên printf("\n");
}
413 414

413 414

Chương 7: Hàm Chương 7: Hàm


7.2 Khai báo và sử dụng hàm 7.2 Khai báo và sử dụng hàm

Dòng đầu hàm Dòng đầu hàm→Tên hàm

Kiểu_hàm Tên_hàm(DS khai báo tham số)


Là tên do người sử dụng tự định nghĩa
• Mô tả các thông tin được trao đổi giữa bên
trong và bên ngoài hàm. • Tuân theo quy tắc đặt tên đối tượng
– Tên của hàm,
• Nên mang ý nghĩa gợi ý chức năng của hàm
– Các tham số đầu vào
• Hàm cần những thông tin gì để hoạt động
– Tham số đầu ra và giá trị trả về
• Hàm cung cấp những thông tin gì cho môi trường
• Dùng phân biệt các hàm với nhau,
– không tồn tại 2 hàm có dòng đầu hàm giống nhau.
415 416

415 416

104
Chương 7: Hàm Chương 7: Hàm
7.2 Khai báo và sử dụng hàm 7.2 Khai báo và sử dụng hàm

Dòng đầu hàm→Khai báo các tham số hình thức Dòng đầu hàm→Khai báo các tham số hình thức

• Khai báo các thông tin cần cho hoạt động • Các tham số cung cấp cho hàm trong quá
của hàm và các thông tin, kết quả tính toán trình thực hiện hàm là tham số thực sự
được hàm trả lại. – Kiểu dữ liệu của tham số thực phải giống kiểu dữ
– Tham số chứa dữ liệu vào cung cấp cho hàm liệu của tham số hình thức tương ứng với tham
– Tham số chứa dữ liệu ra mà hàm tính toán được. số thực sự đó,.
• Các tham số sử dụng trong khai báo hàm là • Một hàm có thể có một, nhiều hoặc không có
tham số hình thức. tham số nào cả
– Nguyên tắc khai báo tham số hình thức như – Nếu có nhiều tham số, phải được phân cách với
giống như khai báo một biến nhau bằng dấu phẩy.
kiểu_dữ_liệu_của_tham_số tên_của_tham_số – không có tham số vẫn phải có cặp dấu ngoặc
đơn sau tên hàm
417 418

417 418

Chương 7: Hàm Chương 7: Hàm


7.2 Khai báo và sử dụng hàm 7.2 Khai báo và sử dụng hàm

Dòng đầu hàm→Kiểu dữ liệu trả về Dòng đầu hàm→Kiểu dữ liệu trả về
• Thông thường hàm sau khi được thực hiện • Trong C, kiểu dữ liệu trả về của hàm có thể
sẽ trả về một giá trị kết quả tính toán nào đó. là kiểu dữ liệu bất kì (kiểu dữ liệu có sẵn
• Để sử dụng được giá trị đó cần phải biết nó hoặc kiểu dữ liệu do người dùng tự định
thuộc kiểu dữ liệu gì. nghĩa) nhưng không được là kiểu dữ liệu
– Kiểu dữ liệu của đối tượng tính toán được hàm mảng.
trả về được gọi là kiểu dữ liệu trả về của hàm. • Nếu kiểu dữ liệu trả về là kiểu void thì hàm
không trả về giá trị nào cả.
• Nếu không khai báo kiểu dữ liệu trả về thì
chương trình dịch của C sẽ ngầm hiểu rằng
kiểu dữ liệu trả về của hàm là kiểu int.
419 420

419 420

105
Chương 7: Hàm Chương 7: Hàm
7.2 Khai báo và sử dụng hàm 7.2 Khai báo và sử dụng hàm

Thân hàm Thân hàm (tiếp)

• Danh sách các câu lệnh Khi gặp lệnh return biểu_thức
• Thường có ít nhất một lệnh return • Tính toán giá trị của biểu_thức,
Họat động của hàm • Lấy kết quả tính toán được làm giá trị trả về cho
lời gọi hàm
• Thực hiện lần lượt các lệnh cho đến khi
– Thực hiện xong tất cả các câu lệnh có trong • Kết thúc việc thực hiện hàm, trở về chương trình
đã gọi nó.
thân hàm
– Gặp lệnh return Nếu return không có phần biểu_thức,
• Cú pháp chung – Kết thúc thực hiện hàm mà không trả về giá trị
return [biểu_thức]; nào cả.
• Dùng khi hàm được khai báo có kiểu trả về là void

421 422

421 422

Chương 7: Hàm Chương 7: Hàm


7.2 Khai báo và sử dụng hàm 7.2 Khai báo và sử dụng hàm

Sử dụng hàm Ví dụ: Cho biết kết quả thực hiện chương trình

Tên_hàm (DS_tham_số_thực _sự); #include<stdio.h>


3
Ví dụ: int fun(int a){ fun(3)
N = bp(1);N= bp(3);,… a++; 4
Lưu ý: return a;
fun(4)
• Gọi hàm thông qua tên hàm và các tham số được cung }
cấp thực sự cho hàm (tham số thực sự). 5
• Nếu hàm nhận nhiều tham số thì các tham số ngăn cách fun(5)
int main(){
nhau bởi dấu phẩy
• Các tham số hình thức của hàm sẽ nhận các giá trị từ printf("%d\n", fun(fun(fun(3))));
tham số truyền vào return 0; 6
• Sau khi thực hiện xong, trở về điểm mà hàm được gọi }
423 424

423 424

106
Chương 7: Hàm Chương 7: Hàm
7.2 Khai báo và sử dụng hàm 7.2 Khai báo và sử dụng hàm

Ví dụ: Cho biết kết quả thực hiện chương trình Ví dụ 1: Tính TBC f(a),f(b), f(c) nếu f(x) = f ( x) = x5 + 5 x
#include<stdio.h> fun(5) #include <stdio.h>
#include <math.h>
int fun(int n){
5 * fun(4) float f(float x){
if(n==0) return 1; if(x==0.0)
4 * fun(3) return 0;
else return n*fun(n-1);
else
} 3 * fun(2)
return pow(x,5)+x/fabs(x) * pow(fabs(x), 0.2);
}
int main(){ 2 * fun(1) void main(){
printf("%d\n", fun(5)); float a, b, c;
1 * fun(0) printf("So 3 so thuc : "); scanf("%f%f%f",&a,&b,&c);
return 0;
} 120 1
printf("Ket qua %f \n",(f(a)+f(b)+f(c))/3);
425 } 426

425 426

Chương 7: Hàm Chương 7: Hàm


7.2 Khai báo và sử dụng hàm 7.2 Khai báo và sử dụng hàm

Ví dụ 2: Tìm ƯSCLN của dãy số Giải phương trình f(x)=0 trên đoạn [a,b]
1. # include <stdio.h>
2. int uscln(int a, int b) {
1. #include <stdio.h> Giải phương trình x3-x-1=0
3. while (a !=b){ 2. #include <math.h>
y
4. if(a > b) a = a- b; 3. float f(float x){
5. else b = b - a; 4. return x*x*x-x-1; 1 2
6. }
7. return a; 5. } x
8. } 6. void main(){
9. void main(){ 7. float a =1.0, b= 2.0, c, eps = 1.0e-6;
10. int A[100], N, i, r;
11. printf("So phan tu : "); scanf("%d",&N); 8. do{
12. for(i=0; i < N; i++){ 9. c =(a+b)/2;
13. printf("A[%d] = ",i+1); scanf("%d",&A[i]); 10. if( f(a) * f(c) < 0) b = c;
14. }
15. r = A[0]; 11. else a = c;
16. for(i = 1; i < N; i++) 12. }while(fabs(b-a) > eps);
17. r = uscln(r,A[i]); 13. printf("Nghiem la : %.6f",(b+a)/2);
18. printf("Ket qua %d \n",r);
19. } 427
14.} 428

427 428

107
Chương 7: Hàm Chương 7: Hàm
7.2 Khai báo và sử dụng hàm 7.2 Khai báo và sử dụng hàm

VD Đọc tọa độ 3 điểm A,B,C và đưa ra d/tích ABC… VD Đọc tọa độ 3 điểm A,B,C và đưa ra d/tích ABC…

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


#include <math.h> Point A, B, C;
float AB,BC,CA,p,S;
typedef struct{
printf("Toa do A (x,y) :"); scanf("%f%f",&A.x,&A.y);
float x, y;
printf("Toa do B (x,y) :"); scanf("%f%f",&B.x,&B.y);
}Point; printf("Toa do C (x,y) :"); scanf("%f%f",&C.x,&C.y);
AB = kc(A,B); BC = kc(B,C); CA = kc(C,A);
float kc(Point A, Point B){ p= (AB + BC + CA)/2;
return sqrt(pow(A.x-B.x,2)+pow(A.y-B.y,2)); S = sqrt(p*(p-AB)*(p-BC)*(p-CA));
printf("Dien tich ABC %f",S);
}
}
429 430

429 430

Bài tập 1 Bài tập 2


Cho hàm f(x) được định nghĩa như sau • Tiền điện được tính theo số điện tiêu thụ như sau
– Dùng ít hơn 250 số: 2000đồng/số
𝑓 𝑥 =൝ 𝒆𝟐𝒙+𝟏+𝟏+7 𝑘ℎ𝑖 𝑥 ≤ 2
5 3 – Dùng từ 250 đến 400 số: 3000 đồng/số
𝑥 + 5𝑥 + 𝑥 + 1 𝑘ℎ𝑖 𝑥 > 2
– Dùng từ 400 đến 500 số: 4000 đồng/số
Hãy viết chương trình thực hiện các công việc sau – Dùng từ 500 số trở lên: 5000đ/số
• Viết chương trình con tính hàm trên • Hãy viết hàm TienDien, trả về số tiền điện phải trả
• Nhập vào từ bàn phím 2 số thực x, y, tính và đưa ra với tham số vào là số điện năng đã tiêu thụ
màn hình (f(x)+f(y))2 • Nhập vào danh sách sử dụng điện của các hộ gia
• Đưa ra màn hình theo dòng các cặp <x, f(x)> (định đình (tên chủ hộ, số điện tiêu thụ), Kết thúc nhập
dạng đưa ra là các số thực tĩnh có 2 chữ số sau dấu khi đã đủ 100 hộ hoặc nhập tên chủ hộ là “***”
chấm) trong đó giá trị của x lần lượt là -5.0; -4.9; • Đưa ra màn hình hộ trả tiền điện ít nhât
-4.8;…..2.8; 2.9; 3.0.
• Sắp xếp danh sách theo thứ tự tăng của tiền phải trả
431 432

431 432

108
Chương 7: Hàm
Bài tập 3 Nội dung chính
Cho hàm f(x) được định nghĩa như sau 1. Khái niệm hàm
3
4− 𝑥2 +1 Khi |x| < 2 • Khái niệm chương trình con
𝑓 𝑥 = 7 𝐾ℎ𝑖 |𝑥| = 2 • Phân loại: hàm và thủ tục
3 +1
𝑒𝑥 + log 5 𝑥 2 − 1 𝐾ℎ𝑖 |𝑥| > 2 2. Khai báo và sử dụng hàm
Hãy viết chương trình thực hiện các công việc sau • Khai báo và sử dụng
• Viết chương trình con tính hàm trên 3. Phạm vi của biến
• Nhập từ bàn phím N số thực và tìm và đưa ra màn hình giá
trị lớn nhất của hàm f(x) tại N số đã nhập. • Toàn cục và địa phương
• Nhập vào từ bàn phím một dãy các số thực cho tới khi nhập • Biến static, biến register
đủ 100 số hoặc cho tới khi gặp một giá trị x thỏa mãn f(x) lớn 4. Truyền tham số
hơn giá trị lớn nhất trong câu trên.
• Truyền theo giá trị, truyền theo địa chỉ
433 434

433 434

Chương 7: Hàm Chương 7: Hàm


7.3 Phạm vi của biến 7.3 Phạm vi của biến

Phạm vi Phân loại biến


• Phạm vi: #include<stdio.h>
• Biến toàn cục:
#include<conio.h>
– Khối lệnh, chương trình con, – Biến được khai báo trong chương trình chính,
int i;
chương trình chính
int binhphuong(int x){ được đặt sau khai báo tệp tiêu đề.
• Biến chỉ có tác dụng trong int y;
phạm vi được khai báo y = x * x;
• Biến cục bộ:
• Trong cùng một phạm vi return y; – biến được khai báo trong lệnh khối hoặc
các biến phải có tên khác
} chương trình con, được đặt trước các câu lệnh.
void main(){
nhau. int y; Ghi chú
Tình huống for (i=0; i<= 10; i++){ – Hàm main() cũng là một chương trình con
• Trong hai phạm vi khác nhau có y = binhphuong(i); nhưng là nơi chương trình được bắt đầu
hai biến cùng tên. Trong đó một printf(“%d ”, y);
phạm vi này nằm trong phạm vi } – Biến khai báo trong hàm main() cũng là biến
kia? } cục bộ, chỉ có phạm vi trong hàm main().
435 436

435 436

109
Chương 7: Hàm Chương 7: Hàm
7.3 Phạm vi của biến 7.3 Phạm vi của biến

Biến static Ví dụ→Kết quả

• Biến cục bộ ra khỏi phạm vi thì bộ nhớ #include <stdio.h>


# include <conio.h>
dành cho biến được giải phóng
void fct() {
• Yêu cầu lưu trữ giá trị của biến cục bộ một static int count = 1;
cách lâu dài => sử dụng từ khóa static printf("\n Day la lan goi ham fct lan thu %2d", count++);
}
Cú pháp: void main(){
static <kiểu_dữ_liệu> tên_biến; int i;
for(i = 0; i < 10; i++) fct();
getch();
}
437 438

437 438

Chương 7: Hàm Chương 7: Hàm


7.3 Phạm vi của biến 7.3 Phạm vi của biến

Ví dụ Biến register

• Thanh ghi có tốc độ truy cập nhanh hơn


RAM, bộ nhớ ngoài
• Lưu biến trong thanh ghi sẽ tăng tốc độ
thực hiện chương trình
Cú pháp
register <kiểu_dữ_liệu> tên_biến;
Lưu ý:
– số lượng biến register không nhiều và thường
chỉ với kiểu dữ liệu nhỏ như int, char
439 440

439 440

110
Chương 7: Hàm
Chương 7: Hàm
7.4 Truyền tham sô

Nội dung chính Ví dụ


1. Khái niệm hàm # include <stdio.h>
void swap(int a, int b) {
• Khái niệm chương trình con
int x = a;
• Phân loại: hàm và thủ tục a = b;
2. Khai báo và sử dụng hàm b = x;
return;
• Khai báo và sử dụng }
3. Phạm vi của biến void main(){
int a = 5, b = 100;
• Toàn cục và địa phương
printf("Truoc: a=%d, b=%d \n\n",a,b);
• Biến static, biến register swap(a,b);
4. Truyền tham số printf("Sau : a=%d, b=%d\n\n",a,b);
return;
• Truyền theo giá trị, truyền theo địa chỉ }
441 442

441 442

Chương 7: Hàm Chương 7: Hàm


74 Truyền tham sô 7.4 Truyền tham sô

Truyền theo giá trị và truyền theo biến Truyền theo biến

• Truyền theo trị • Thực chất là truyền theo địa chỉ của biến
– Dựa trên nguyên tắc truyền những bản sao của • Khi khai báo hàm [tham số có kiểu “địa chỉ”]:
biến được truyền
– Khai báo là một con trỏ, trỏ tới một đối tượng có
– Những câu lệnh thay đổi giá trị tham số hình
kiểu muốn truyền vào
thức sẽ không ảnh hưởng tới biến được truyền
– Ví dụ: void swap (int *pa, int *pb);
• Truyền theo biến
– Tham số được truyền sẽ thực sự là biến và các • Khi truyền tham số
thao tác sẽ thi hành trực tiếp với biến – Địa chỉ của biến được truyền
– Những câu lệnh thay đổi giá trị tham số hình Ví dụ: swap(&a,&b)
thức sẽ ảnh hưởng tới biến được truyền
– Có thể truyền tên của mảng
• Tên mảng là hằng địa chỉ
443 444

443 444

111
Chương 7: Hàm
7.4 Truyền tham sô Ví dụ 2: Nhập danh sách các xâu cho tới khi gặp xâu rỗng
Ví dụ 1: Truyền theo địa chỉ của biến Đưa ra xâu có tần xuất xuất hiện nguyên âm lớn nhất
# include <stdio.h>
# include <conio.h>
void swap(int * pa, int * pb) {
int x = *pa;
*pa = *pb;
*pb = x;
return;
}
void main(){
int a = 5, b = 100;
printf("Truoc: a=%d, b=%d \n\n",a,b);
swap(&a,&b);
printf("Sau : a=%d, b=%d\n\n",a,b);
return;
}
445 446

445 446

Chương 6: Cấu trúc Chương 6: Cấu trúc


6.3 Xử lý dư liệu cấu trúc 6.3 Xử lý dư liệu cấu trúc

Câu hỏi 1: Kết quả đưa ra màn hình Câu hỏi 2: Kết quả đưa ra màn hình
#include<stdio.h> a 0210 #include<stdio.h> a 5, 2
void fun(int n){ b 0102 void fun(int *i, int *j){ b 2, 5
if(n > 0) { c 1120 *i = *i * *i; c 10, 4
fun(--n); *j = *j * *j;
d 0120 d 4, 25
printf("%d ", n); }
e 0201 e 25, 4
fun(--n);
int main(){
}
int i=5, j=2;
}
int main(){ fun(&i, &j);
fun(3); printf("%d, %d", i, j);
return 0; return 0;
} }
447 448

447 448

112
Phần 3: Lập trình C
Chương 6: Cấu trúc
6.3 Xử lý dư liệu cấu trúc

Câu hỏi 3: Kết quả đưa ra màn hình Nội dung chính
“”””””””””””””””””"
#include<stdio.h> a AB • Chương 1: Tổng quan về ngôn ngữ C
void fun(char*); b AC • Chương 2: Kiểu dữ liệu và biểu thức trong C
int main(){ c BC
char a[10]="ABCDEF"; • Chương 3: Vào ra dữ liệu
d BD
fun(&a[0]);
e CD • Chương 4: Cấu trúc điều khiển
return 0;
} • Chương 5: Mảng, con trỏ và xâu ký tự
void fun(char *a){
• Chương 6: Cấu trúc
printf("%c", *++a);
a++; • Chương 7: Hàm
printf("%c", *a); • Chương 8: Tệp dữ liệu
} 449 450

449 450

Chương 8: Tệp dữ liệu


Chương 8: Tệp dữ liệu
8.1 Tệp và phân loại tệp

Nội dung chính Khái niệm


1. Tệp và phân loại tệp • Tệp (Tập tin/File):
• Khái niệm và phân loại – Tập hợp các dữ liệu cùng kiểu
• Tệp và mảng – Có liên quan tới nhau
• Tổ chức tệp • Lưu trữ tệp
2. Các thao tác với tệp – Lưu trữ trên thiết bị lưu trữ ngoài
• Khai báo – Có tên riêng để phân biệt
• Mở tệp • Phân thành 2 loại
• Đóng tệp – Tệp văn bản (text file)
• Truy nhập tệp văn bản – Tệp nhị phân (binary file)
• Truy nhập tệp nhị phân
452
451

451 452

113
Chương 8: Tệp dữ liệu Chương 8: Tệp dữ liệu
8.1 Tệp và phân loại tệp 8.1 Tệp và phân loại tệp

Phân loại Tệp dữ liệu và mảng


• Tệp văn bản • Mảng
– Được tổ chức theo từng dòng – Được lưu trong bộ nhớ →dữ liệu bị mất đi khi tắt
• Trên mỗi dòng là các ký tự ASCII hiện thị được như máy
chữ cái, chữ số, dấu câu,… – Truy nhập trực tiếp tới một phần tử qua số hiệu
– Cuối mỗi dòng là các ký tự điều khiển – Kích thước mảng xác định trước
• CR: Carriage Return - mã ASCII 13
• LF:Line Feed- Mã ASCII 10
• Tệp
– Lưu trữ trên thiết bị lưu trữ ngoài→dữ liệu được
• Tệp nhị phân
lưu trữ lâu dài, không bị mất đi khi tắt máy
– Các phần tử của tệp là các số nhị phân dung
– Không truy nhập trực tiếp qua số hiệu phần tử
mã hóa thông tin
– Kích thước có thể rất lớn và không cần xác định
– Thông tin được mã hóa: số, cấu trúc dữ liệu,..
trước
453 454

453 454

Chương 8: Tệp dữ liệu


Chương 8: Tệp dữ liệu
8.1 Tệp và phân loại tệp

Tổ chức tệp Nội dung chính


Phần tử dữ liệu ngay sau khi mở file Ký hiệu đánh dấu kết thúc file 1. Tệp và phân loại tệp
EOF • Khái niệm và phân loại
• Vai trò của tệp
Phần tử dữ liệu Phần tử dữ liệu Phần tử dữ liệu
đầu tiên đang truy cập cuối cùng
• Tổ chức tệp
• Tệp là dãy các phần tử kế tiếp nhau 2. Các thao tác với tệp
– Sử dụng phần tử đặc biệt (EOF) để đánh dấu kết thúc tệp • Khai báo
• Con trỏ tệp: • Mở tệp
– Xác định vị trí phần tử hiện có thể truy cập • Đóng tệp
– Khi mở file, con trỏ tệp luôn ở vị trí phần tử đầu
• Truy nhập tệp văn bản
– Sau các thao tác đọc/ghi tệp, con trỏ file dịch chuyển về
cuối tệp một khỏng bằng số byte đã đọc/ ghi • Truy nhập tệp nhị phân
455
456

455 456

114
Chương 8: Tệp dữ liệu Chương 8: Tệp dữ liệu
8.2 Thao tác với tệp 8.2 Thao tác với tệp

Quy trình Khai báo biến tệp

• Khai báo biến tệp FILE * Con_Trỏ_Tệp

• Mở tệp để làm việc • Tệp được truy nhập qua con_trỏ_tệp


– Phân biệt các loại tệp và các mục đích mở tệp • Ví dụ
• Truy nhập tệp – FILE * f1, *f2;

– Truy nhập để đọc/ ghi/thêm mới

– Phân biệt giữa các loại tệp

• Đóng tệp
457 458

457 458

Chương 8: Tệp dữ liệu Chương 8: Tệp dữ liệu


8.2 Thao tác với tệp 8.2 Thao tác với tệp

Mở tệp Đóng tệp


Con_Trỏ_Tệp = fopen(Tên_Tệp, Chế_độ mở) int fclose(FILE * Con_Trỏ_Tệp)
• Hàm fopen() khi báo trong thư viện stdio.h
• Tên_Tệp: Kiểu chuỗi, xác định tên tệp trên đĩa
• Hàm fclose() khi báo trong thư viện stdio.h
– Tên đầy đủ của tệp hoặc tệp trên thư mực hiện thời • Con_trỏ_tệp: Tên biến tệp
• Chế độ mở: Hằng xâu, gồm các ký tự r/w/a/+/t/b
– Tùy thuộc kiểu tệp và mục đích sử dụng • Kết quả trả về
– Kiểu tệp: t: text file; b: binary file
– Chế độ: + Vừa đọc/ vừa ghi – 0: Nếu đóng tệp thành công
- r : Mở để đọc; Báo lỗi nếutệp chưa tồn tại – EOF: Nếu có lỗi
- w : Mở mới để ghi; Xóa nội dung tệp cũ nếu đã có
- a : Mở để ghi vào cuối; Tạo tệp mới nếu chưa tồn tại
• Trả về NULL nếu có lỗi mở tệp 459 460

459 460

115
Chương 8: Tệp dữ liệu Chương 8: Tệp dữ liệu
8.2 Thao tác với tệp 8.2 Thao tác với tệp

Truy nhập tệp văn bản Truy nhập tệp nhị phân
• Tương tự như với bàn phím/ màn hình Đọc dữ liệu
• Yêu cầu chỉ rõ nguồn/đích thông tin
int fread(void * Địa_Chỉ_Đích, int Kích_thước,
• Các thao tác
int số_phần_tử, FILE *fptr)
– Đọc dữ liệu từ tệp : fscanf() / fgets() /getc()
– Đọc từ file xác đinh bởi biến fptr một khối dữ liệu
– Ghi dữ liệu ra tệp : fprintf() / fputs() /putc()
kích thước Số_Phần_Tử x Kích_Thước vào
– Dịch chuyển con trỏ tệp : fseek() / rewind()
vùng nhớ xác định bởi Địa_Chỉ_Đích
– Kiểm tra kết thúc tệp : feof()
– Nếu đọc thành công: Trả về số phần tử đọc được
• Ví dụ:
– fprintf(FILE *fptr, Xâu_định dạng [,DS giá trị]) – Nếu không thành công: Trả về giá trị 0
– fgets(char * Xâu ký tự, int n, FILE *fptr) • Ví dụ: int Buf[100]; FILE * fptr =fopen(“so.dat”,”rb”)
fread( Buf, sizeof(int), 100, fptr);
461 462

461 462

Chương 8: Tệp dữ liệu Chương 8: Tệp dữ liệu


8.2 Thao tác với tệp 8.2 Thao tác với tệp

Truy nhập tệp nhị phân Truy nhập tệp nhị phân

Ghi dữ liệu Dịch chuyển con trỏ file


int fseek(FILE *fptr, long int N, int Vị_Trí_Đầu)
int fwrite(void * Đ_Chỉ_Nguồn, int Kích_thước,
– Dịch chuyển con trỏ file của file fptr đi một
int số_phần_tử, FILE *fptr) khoảng N so với Vị_Trí_Đầu
– Ghi từ vùng nhớ xác định bởi Địa_Chỉ_nguồn • SEEK_SET / 0: Vị trí đầu là đầu tệp
một khối dữ liệu có kích thước Số_Phần_Tử x • SEEK_CUR / 1: Vị trí đầu là vị trí con trỏ file hiện thời
Kích_Thước ra file được xác đinh bởi biến fptr • SEEK_END / 2: Vị trí đầu là cuối tệp
– void rewind(FILE *fptr): Đưa con trỏ về đầu tệp
– Nếu ghi thành công: Trả về số phần tử đã ghi
Kiểm tra kết thúc file
– Nếu không thành công: Trả về giá trị 0
int feof(FILE *fptr) Chú ý khi dùng, có thể lỗi
• Ví dụ: int Buf[100]; FILE * fptr =fopen(“so.dat”,”wb”)
– Trả về 0 nếu con trỏ file vẫn còn trỏ tới một phần
fwrite(Buf, sizeof(int), 100, fptr);
463 tử dữ liệu, 1 nếu con trỏ file đang trỏ tới EOF 464

463 464

116
Chương 8: Tệp dữ liệu Chương 8: Tệp dữ liệu
8.2 Thao tác với tệp 8.2 Thao tác với tệp

Ví dụ 1 Ví dụ 2

• Tạo file Songuyen.dat ghi 100 số lẻ đầu tiên. • Đọc file Songuyen.dat, đưa ra màn hình các
số lẻ từ vị trí số thứ 50 của file
#include <stdio.h> #include <stdio.h>
void main(){ void main(){
FILE * f = fopen(“SoNguyen.Dat”,”wb”); FILE * f = fopen("SoNguyen.Dat","rb");
int i, n; int n;
for(i = 0; i <100; i++){ fseek(f,50*sizeof(int),SEEK_SET);
n = 2*i+1; while(!feof(f)){
fwrite(&n, sizeof(int), 1, f); fread(&n,sizeof(int),1,f);
} printf("%4d",n);
fclose(f); }
} fclose(f);
465 } 466

465 466

Chương 8: Tệp dữ liệu Chương 8: Tệp dữ liệu


8.2 Thao tác với tệp 8.2 Thao tác với tệp

Ví dụ 3 Ví dụ 4
• Nhập vào từ bàn phím 100 số thực và ghi file nhị phân • Nhập danh sách từ bàn phím các thí sinh dự thi, mỗi thí
SO_DUONG.DAT các số thực dương trong các số đã nhập sinh gồm họ tên, số báo danh, khoa dự thi và điểm thi. Dữ
• Đọc từ file SO_DUONG.DAT và đưa ra màn hình số thực liệu nhập được ghi vào file ThiSinh.dat. Kết thúc nhập khi
có giá trị lớn nhất gặp một thí sinh có tên là « *** »
• Đọc từ file ThiSinh.Dat, đưa ra màn hình danh sách các thí
sinh thi vào ngành CNTT có điểm thi lớn hớn 21 theo quy
cách
STT Số Báo Danh Ho Tên Điểm Thi
• Từ file ThiSinh.Dat, tạo file CNTT.Dat chỉ chứa danh sách
các thí inh thi vào khoa CNTT
• Nhập vào một số báo danh, tìm trong file ThiSinh.Dat và in
ra họ tên, điểm thi và khoa đăng ký của thí sinh nếu tìm
thấy. Nếu không tìm thấy thí sinh thì đưa ra thông báo
467 « không tìm thấy » 468

467 468

117
Chương 8: Tệp dữ liệu Chương 8: Tệp dữ liệu
8.2 Thao tác với tệp 8.2 Thao tác với tệp

Ví dụ 4 Ví dụ 4
#include <stdio.h> //Nhap thong tin cho file ThiSinh.Dat
#include <string.h> f1 = fopen("ThiSinh.Dat","wb");
typedef struct{ i = 1;
char Ten[30]; do{
long SBD; printf("Thi sinh %d :\n", i);
char Khoa[10]; printf(" Ho Ten : "); fflush(stdin); gets(SV.Ten);
float Diem;
if(strcmp(SV.Ten,"***")==0)break;
}SinhVien;
printf(" So Bao Danh: "); scanf("%d",&SV.SBD);
void main(){ printf(" Khoa : "); fflush(stdin); gets(SV.Khoa);
FILE * f1,* f2; printf(" Diem : "); scanf("%f",&SV.Diem);
SinhVien SV;
fwrite(&SV,sizeof(SinhVien),1,f1);
int i, SBD;
//Nhap thong tin cho file ThiSinh.Dat i++;
//Tao file CNTT.Dat }while(1);
} 469 fclose(f1); 470

469 470

Chương 8: Tệp dữ liệu Chương 8: Tệp dữ liệu


8.2 Thao tác với tệp 8.2 Thao tác với tệp

Ví dụ 4 Ví dụ 3
printf("\n\n DANH SACH BAN DAU \n"); printf("\n\n Tao file CNTT.Dat\n");
f1 = fopen("ThiSinh.Dat","rb"); i = 0;
i = 0; rewind(f1);
while(fread(&SV,sizeof(SinhVien),1,f1) > 0) f2 = fopen("CNTT.Dat","wb");
printf("%-3d %-5d %-20s %-20s %-5.1f\n", while(fread(&SV,sizeof(SinhVien),1,f1) > 0)
++i,SV.SBD, SV.Ten, SV.Khoa, SV.Diem); if(strcmp(SV.Khoa,"CNTT")==0 )
printf("\n\n Thi Sinh thi CNTT tren 21.0\n"); fwrite(&SV,sizeof(SinhVien),1,f2);
i = 0; fclose(f2);
rewind(f1); f2 = fopen("CNTT.Dat","rb"); //doc lai file
while(fread(&SV,sizeof(SinhVien),1,f1) > 0) while(fread(&SV,sizeof(SinhVien),1,f2) > 0)
if(strcmp(SV.Khoa,"CNTT")==0 && SV.Diem > 21.0) printf("%-3d %-5d %-20s %-5.1f\n",
printf("%-3d %-5d %-20s %-5.1f\n",++i,SV.SBD, ++i, SV.SBD, SV.Ten, SV.Diem);
SV.Ten, SV.Diem); fclose(f2);
471 472

471 472

118
Chương 8: Tệp dữ liệu
8.2 Thao tác với tệp

Ví dụ 3
printf("\n\nTim Sinh Vien\n");
printf(" So Bao Danh ");scanf("%d",&SBD);
rewind(f1);
while(fread(&SV,sizeof(SinhVien),1,f1))
if(SV.SBD==SBD){
printf("Tim thay sinh vien %s",SV.Ten);
break;
}
if(feof(f1)) printf("Khong thay ");
fclose(f1)

473

473

119

You might also like