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

TIN HỌC ĐẠI CƯƠNG

Phần 3: LẬP TRÌNH C


Lê Xuân Thành
thanhlx@soict.hust.edu.vn

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
• Chương 3: Vào ra dữ liệu
• Chương 4: Cấu trúc điều khiển
• Chương 5: Mảng, con trỏ và xâu ký tự
• Chương 6: Cấu trúc
• Chương 7: Hàm
• Chương 8: Tệp dữ liệu
26/09/2019 2

1
Chương 1: Tổng quan về ngôn ngữ C
Nội dung chính

1. Lịch sử phát triển của ngôn ngữ C

2. Các phần tử cơ bản của ngôn ngữ C

3. Cấu trúc cơ bản của chương trình C

4. Biên dịch chương trình C

26/09/2019 3

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

Sự ra đời của C
• Nhu cầu viết lại HĐH Unix cho các hệ máy
tính khác nhau
– Dùng Assembly
• Công việc nặng nề, phức tạp
• 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
• Đơn giản việc lập trình
• Tính khả chuyển cao
• 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
– Phát triển năm 1970, hoàn thành 1972
26/09/2019 4

2
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

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


• Đặc điểm
– Ngôn ngữ lập trình hệ thống
– Tính khả chuyển, linh hoạt cao
– Có thế mạnh trong xử lý dữ liệu số, văn bản, cơ
sở dữ liệu,..
• Phạm vi sử dụng
– Viết các chương trình hệ thống
• Hệ điều hành Unix có 90% mã C, 10% mã hợp ngữ
– Các trình điều khiển thiết bị (device driver)
– Xử lý ảnh
26/09/2019 5

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

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


• Các phiên bản
– ANSI C: C chuẩn (1989)
– Các phiên bản khác xây dựng dựa trên ANSI C
• Đưa thêm thư viện; Bổ sung cho thư viện chẩn
của ANSI C
• Các trình biên dịch phổ biên
– Turbo C++ và Borland C++ của hãng Borland
Inc
– VC và MSC của Microsoft Corp
– GCC của GNU project
26/09/2019 6

3
Chương 1: Tổng quan về ngôn ngữ C
Nội dung chính

1. Lịch sử phát triển

2. Các phần tử cơ bản của ngôn ngữ C

3. Cấu trúc cơ bản của chương trình C

4. Biên dịch chương trình C

26/09/2019 7

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

Các phần tử cơ bản


1. Tập ký tự
2. Từ khóa
3. Định danh
4. Các kiểu dữ liệu
5. Hằng
6. Biến
7. Hàm
8. Biểu thức
9. Câu lệnh
10. Chú thích
26/09/2019 8

4
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. Tập ký tự
Ký tự là các phần tử cơ bản tạo nên chương
trình
• Chương trình: Tập các câu lệnh nhằm
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
nhau theo cú pháp của ngôn ngữ lập trình
– Ví dụ: while (i < N ) do
• Các từ: Tổ hợp các ký tự theo nguyên tắc
xây dựng từ vựng
– Ví dụ: TenFile, BaiTap2…
26/09/2019 9

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. Tập ký tự→ Tập ký tự trong C


• 26 chữ cái hoa:A B C ... X Y Z
• 26 chữ cái thường:a b c … x y z.
• 10 chữ số: 0 1 2 3 4 5 6 7 8 9.
• Các kí hiệu toán học:+ - * / = < >
• Các dấu ngăn cách: . ; , : space tab
• Các dấu ngoặc:( ) [ ] { }
• Các kí hiệu đặc biệt:_ ? $ & # ^ \ ! ‘ “
~ ...

26/09/2019 10

10

5
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

2. Từ khóa (keyword)

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

• Dành riêng cho các mục đích xác định


– Đặt tên cho kiểu dữ liệu:
• int, float, double…

– Mô tả các lệnh, các cấu trúc lập trình


• if, else, while, case, for…

26/09/2019 11

11

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

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

break case char const continue default


do double else enum float for
goto if int interrupt long return
short signed sizeof static struct switch
typedef union unsigned void while

Lưu ý:Tất cả từ khóa trong C đều viết bằng


chữ cái thường

26/09/2019 12

12

6
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

3. Định danh (Identifier)


• Định danh (Tên) là một dãy các kí tự dùng
để gọi tên các đối tượng trong chương
trình.
– Các đối tượng trong chương trình
• Biến
• Hằng số
• Hàm
• Kiểu dữ liệu
• Định danh có thể được đặt bởi
– Ngôn ngữ lập trình → các từ khóa
– Người lập trình
26/09/2019 13

13

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

3. Định danh→ Quy tắc đặt tên định danh trong C


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

14

7
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

3. Định danh→Ví dụ
• Định danh hợp lệ:
i, x, y, a, b, _function,
_MY_CONSTANT, PI, gia_tri_1
• Định danh không hợp lệ
1_a, 3d, 55x (bắt đầu bằng chữ số)
so luong, sin() (có kí tự không hợp lệ, dấu
cách, dấu ngoặc..)
int, char (trùng với từ khóa của C)

26/09/2019 15

15

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

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


• Định danh nên có tính gợi nhớ
• Nên sử dụng dấu gạch dưới để phân tách
các định danh gồm nhiều từ
– Có thể dùng cách viết hoa chữ cái đầu mỗi từ
-Ví dụ: sinh_vien, sinhVien, SinhVien
• Quy ước thường được sử dụng:
– Hằng số dùng chữ cái hoa
• Ví dụ: PI, EPSILON,…
– Các biến, hàm, cấu trúc dùng chữ cái thường
• Biến điều khiển vòng lặp: i, j, k…
• Hàm: NhapDuLieu, TimKiem,…
• Cấu trúc: SinhVien, MatHang,…
26/09/2019 16

16

8
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

4. Các kiểu dữ liệu


• Một kiểu dữ liệu là một tập hợp các giá trị
mà một dữ liệu thuộc kiểu dữ liệu đó có thể
nhận được.
– Ví dụ: Một đối tượng kiểu int của C sẽ là
• Một số nguyên (Số nguyên có dấu, 2 byte)
• Giá trị thuộc khoảng: [-32,768 (-215) …32,767 (215-1)]

• Trên một kiểu dữ liệu, xác định một số phép


toán đối với các dữ liệu thuộc kiểu dữ liệu
tương ứng.

26/09/2019 17

17

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

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


Một số phép toán được định nghĩa trên kiểu
dữ liệu int của C

Tên phép toán Ký hiệu Ví dụ


Đảo dấu -
Cộng;Trừ;Nhân +;-;*
Chia lấy nguyên / 17/3→5
Chia lấy phần dư % 17%3→2
So sánh >, <, >=, <=, ==, !=
Logic bit: AND; OR; & ; | ; 3^17 →18
XOR;NOT, Shift,… ^ ; ~ ; <<; >> ~3 →-4
26/09/2019 18

18

9
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

5. Hằng
• Hằng (constant) là đại lượng có giá trị
không đổi trong chương trình.
• Giá trị hằng do người lập trình xác định
• Các loại hằng
– Hằng số nguyên
– Hằng số thực
– Hằng ký tự
– Hằng chuỗi/xâu kỹ tự

26/09/2019 19

19

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

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


• Trong C, hằng số nguyên có thể biểu diễn
dưới các dạng
– Dạng thập phân
– Dạng thập lục phân
– Dạng bát phân

Giá trị Giá trị Giá trị


thập phân thập lục phân bát phân
2011 0x7DB 03733
396 0x18C 0614
26/09/2019 20

20

10
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

5. Hằng → Hằng số thực


• Trong C, hằng số thực có thể biểu diễn dưới
các dạng
– Dạng số thực dấu phẩy tĩnh
– Dạng số thực dấu phẩy động

Số thực dấu phẩy tĩnh Số thực dấu phẩy động


3.14159 31.4159 E-1
123.456 12.3456 E+1 hoặc
1.23456 E+2

26/09/2019 21

21

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

5. Hằng → Hằng ký tự
• Hằng ký tự có thể biểu diễn theo hai cách
– Đặt ký hiệu của ký tự giữa hai dấu nháy đơn
– Dùng mã ASCII của ký tự:
• 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

Ký tự Dùng nháy đơn Dùng mã ASCII


Chữ cái A ‘A’ 65, 0x41, 0101
Dấu nháy đơn ‘\’’ 39, 0x27, 047
Ký tự tab ‘\t’ 9, 0x09, 011
26/09/2019 22

22

11
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

5. Hằng → Hằng chuỗi/xâu kỹ tự

• Hằng chuỗi/xâu kí tự được biểu diễn bởi đặt


dãy các kí tự trong xâu trong cặp dấu nháy
kép.
• Ví dụ:
– “ngon ngu lap trinh C”
– “Tin hoc dai cuong”
– “Dai hoc Bach Khoa Ha Noi”

26/09/2019 23

23

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

6. Biến (variable)
• Biến là đại lượng mà giá trị có thể thay đổi
trong chương trình.
• Tên biến phải được đặt theo quy tắc đặt tên
– Về thực chất, biến là các ô nhớ trong bộ nhớ
máy tính dành cho 1 kiểu dữ liệu nào đó và
được đặt tên để tiện tham khảo
• Ví dụ: Biến kiểu int chiếm 2 ô nhớ
• Lưu ý:
– 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 đó
26/09/2019 24

24

12
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

7. Hàm (function)
• Hàm là chương trình con có chức năng
– Nhận dữ liệu đầu vào (các tham số vào)
– Thực hiện một công việc nào đó
– Trả về kết quả ứng với tham số truyền vào
• Ví dụ: hàm sin(x)
– sin(3.14/2) →1.000
– sin(3.14/6) →0.499770

• Hàm không trả lại một giá trị: Thủ tục


– Ví dụ: clrscr()
26/09/2019 25

25

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

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


Hàm Ý nghĩa Ví dụ
sqrt(x) Căn bậc 2 của x sqrt(16.0) → 4.0
pow(x,y) X mũ y ( xy ) pow(2,3) → 8
fabs(x) Trị tuyệt đối của x ( |x| ) fabs(-5.0) →5.0
exp(x) E mũ x ( ex ) exp(1.0)→2.71828
log(x) Logarithm tự nhiên của x (ln x) Log(2.718)→0.999
log10(x) Logarithm cơ số 10 của x (logx) Log10(100) →2.00
sin(x) Các hàm lượng giác
cos(x)/ tan(x)
ceil(x) Số nguyên nhỏ nhất không nhỏ ceil(2.5)=3
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
26/09/2019
hơn x ( x) floor(-2.5)=-3 26

26

13
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

8. Biểu thức
• Biểu thức là sự kết hợp các các toán hạng
(operand) bởi các toán tử (operator) theo
một quy tắc xác định.
• Các toán hạng có thể là biến, hằng, hàm…
• Các toán tử rất đa dạng: cộng, trừ, nhân,
chia
Ví dụ
– Thể tích hình hộp: V=Rộng*Cao*Dày
• Phép nhân (*) là toán tử

Cao
• Các toán hạng Rộng, Cao, Dày
Rộng
26/09/2019 27

27

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

9. Câu lệnh (statement)

• Câu lệnh diễn tả một hoặc một nhóm các


thao tác trong giải thuật.
– Chương trình được tạo thành từ dãy các câu
lệnh.

• Các câu lệnh trong C, được kết thúc bởi


dấu chấm phẩy (;)
– Dấu chấm phẩy (;) dùng phân cách các lệnh

26/09/2019 28

28

14
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

9. Câu lệnh → Phân loại


• Câu lệnh đơn:
– Những câu lệnh không chứa câu lệnh khác.
• Ví dụ: Phép gán, gọi hàm, vào/ra dữ liệu
• Các câu lệnh phức:
– Những câu lệnh chứa câu lệnh khác.
• 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 « { } »)
– Các lệnh điều khiển cấu trúc chương trình
• Ví dụ: Lệnh rẽ nhánh, lệnh lặp..

26/09/2019 29

29

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

10. Chú thích (comment)


• Lời mô tả, giải thích vắn tắt cho một câu
lệnh, một đoạn chương trình hoặc cả
chương trình
– Giúp việc đọc hiểu chương trình dễ dàng hơn
– Chú thích không phải là câu lệnh  không ảnh
hưởng tới chương trình
• Khi gặp chú thích, trình biên dịch sẽ bỏ qua
• Cách viết chú thích
– Chú thích một dòng: sử dụng « // »
– Chú thích nhiều dòng: sử dụng « /* » và « */ »
26/09/2019 30

30

15
Chương 1: Tổng quan về ngôn ngữ C
Nội dung chính

1. Lịch sử phát triển

2. Các phần tử cơ bản của ngôn ngữ C

3. Cấu trúc cơ bản của chương trình C

4. Biên dịch chương trình C

26/09/2019 31

31

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

Các phần cơ bản


Khai báo các tệp tiêu đề
#include
Khai báo các đối tượng toàn cụ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)

Định nghĩa hàm main()


{

}
Định nghĩa các hàm đã khai báo nguyên mẫu
26/09/2019 32

32

16
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. Khai báo các tệp tiêu đề


• Liệt kê danh sách thư viện sẽ được sử dụng
trong chương trình
– Các hàm của C đều thuộc một thư viện nào đó
– Không khai báo thư viện, trình biên dịch không
hiểu được hàm (có thể báo lỗi)
• Cách thức (cú pháp) khai báo
1. #include<ThuVien.h>
• Thư viện phải nằm trong thư mục chứa các header file
• Thường được sử dụ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
26/09/2019 33

33

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

2. Khai báo các đối tượng toàn cục

• Các đối tượng toàn cục có phạm vi sử dụng


trong toàn bộ chương trình
– Các kiểu dữ liệu mới
– Các hằng, biến
– Các nguyên hàm

• Tuân theo nguyên tắc khai báo đối tượng

26/09/2019 34

34

17
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

2. Khai báo các đối tượng toàn cục


Định nghĩa kiểu dữ liệu
Cú pháp: typedef <ĐịnhNghĩaKiểu> <Tên kiểu>
Ví dụ: typedef unsigned char byte;
typedef struct {float re, im;} complex;

Khai báo hằng


const float PI = 3.1415;
#define Max 50
Khai báo biến
int N;
float Delta, x1, x2;
26/09/2019 35

35

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

2. Khai báo các đối tượng toàn cục (tiếp)


Khai báo các hàm nguyên mẫu
• Khai báo thông tin về các hàm của người
dùng sẽ được sử dụng trong chương trình
– Tên hàm
– Danh sách các kiểu tham số sẽ truyền vào
– Kiểu dữ liệu trả về
• Ví dụ
float DienTichTamGiac(float a, float b, float c);
int getMax(int Arr []);
Có thể bỏ tên tham số
void swap(int * a, int * b);
void swap(int *, int *);
26/09/2019 36

36

18
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

3. Định nghĩa hàm main()


• Bắt buộc phải có
• Là hàm đặc biệt trong C, đánh dấu điểm bắt
đầu của mọi chương trình C
– Khi thực hiện một chương trình C, hệ thống sẽ
gọi tới hàm main đầu tiên, sau đó sẽ thực hiện
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()
• Cú pháp
void main(){….}
void main(int argc, char * argv[ ]){….}
int main(){….; return 0;}
int main(int argc, char * argv[ ]){….; return 0;}
26/09/2019 37

37

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

4. Định nghĩa các hàm đã khai báo


• Định nghĩa các hàm đã khai báo ở phần 3
(Phần khai báo nguyên mẫu - prototype)
– Phần khai báo nguyên mẫu mới chỉ khai báo các
thông tin cơ bản về hàm, chưa xác định rõ hàm
hoạt động như thế nào
• Ví dụ
float DienTichTamGiac(float a, float b, float c){
float p = (a+b+c)/2;
return sqrt(p*(p-a)*(p-b)*(p-c));
}
26/09/2019 38

38

19
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

Chú ý

Các phần không bắt buộc phải theo đúng thứ tự


• Khi định nghĩa hàm được đặt trước hàm
main(), không cần khai báo nguyên hàm
• Nguyên tắc:
– Mọi đối tượng cần phải được khai báo trước khi
sử dụng

26/09/2019 39

39

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

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


1. #include <stdio.h>
2. int main(){ //Không cần tham số dòng lệnh
3. printf("Hello world! \n");
4. return 0; //Trả về giá trị 0
5. }
1. Nạp thư viện stdio.h vào, đây là thư viện vào ra chuẩn
(standard input output) chứa khai báo nguyên hàm cho
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
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
26/09/2019 40

40

20
Chương 1: Tổng quan về ngôn ngữ C
Nội dung chính

1. Lịch sử phát triển

2. Các phần tử cơ bản của ngôn ngữ C

3. Cấu trúc cơ bản của chương trình C

4. Biên dịch chương trình C

26/09/2019 41

41

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

Biên dịch chương trình


• Chương trình được viết bằng ngôn ngữ bậc
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)
• 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ữ
Source code Preprocessor Compiler Assembly code

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
26/09/2019 42

42

21
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

Các trình biên dịch C


Tồn tại nhiều trình biên dịch cho ngôn ngữ C
• Turbo C++ của Borland Inc (Ví dụ Turbo C++3.0)
– Cho phép biên dịch cả C và C++
– Gọn nhẹ, đủ tính năng và dễ sử dụng
– Hệ điều hành DOS (16bit), không phù hợp với Win64 bit

• MSC của Microsoft,


• GCC của GNU
– Trên môi trường Linux
• Dev-C, C-free, Codeblocks…
Dev-Cpp Ver 4.9.9.2 hoặc Dev-Cpp 5.1.1
26/09/2019 43

43

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

Cài đặt Dev-Cpp


• Tải Dev-C++
– Google  Dev-C++
– Tìm đến phiên bản thích hợp, thực hiện tải về
• Dev-Cpp 5.11 TDM-GCC 4.9.2 Setup.exe
• Devcpp_v4_9_9_2_setup.exe

• Thực thi file tải về, làm theo hướng dẫn

26/09/2019 44

44

22
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

Cài đặt Dev-Cpp

26/09/2019 45

45

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

Màn hình giao diện DEV-C++

26/09/2019 46

46

23
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

Màn hình giao diện DEV-C++

26/09/2019 47

47

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

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.
26/09/2019 48

48

24
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

Cài đặt 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
26/09/2019

49

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

Màn hình giao diện Turbo C++ 3.0

26/09/2019 50

50

25
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

Sử dụng Turbo C++ 3.0


• 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
26/09/2019 51

51

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

Chương trình Hello world!

26/09/2019 52

52

26
Chương 1: Tổng quan về ngôn ngữ C
Tóm tắt

1. Lịch sử phát triển của ngôn ngữ C


2. Các phần tử cơ bản của ngôn ngữ C
– 10 phần tử cơ bản
3. Cấu trúc cơ bản của chương trình C
– 4 phần
4. Thực hiện chương trình C với Dev-C++

26/09/2019 53

53

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
• Chương 3: Vào ra dữ liệu
• Chương 4: Cấu trúc điều khiển
• Chương 5: Mảng, con trỏ và xâu ký tự
• Chương 6: Cấu trúc
• Chương 7: Hàm
• Chương 8: Tệp dữ liệu
26/09/2019 54

54

27
Chương 2: Kiểu dữ liệu và biểu thức trong C
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

26/09/2019 55

55

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

Các kiểu đơn

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


char Kí tự; 1 byte -128  127
Số nguyên có dấu

int Số nguyên 2 byte -32.76832.767


có dấu
short int
long Số nguyên có dấu 4 byte -2,147,483,648
 2,147,483,647
long int
float Số thực dấu phẩy 4 byte  3.4E-38 
động,  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
26/09/2019 56

56

28
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

Các kiểu kết hợp


Với số nguyên, thêm từ khóa unsigned để chỉ ra số không dấu

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


unsigned char Số nguyên 1 byte 0  255
không dấu

unsigned short Số nguyên 2 byte 065.535


unsigned không dấu
unsigned int
unsigned long Số nguyên 4 byte 0  4,294,967,295
unsigned long int không dấu

long double Số thực dấu 10 byte 3.4E-4932 


phẩy động, 1.1E+4932
void Là kiểu rỗng, kích thước không
26/09/2019 57

57

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

Biểu diễn hằng số

Kiểu dữ liệu Ví dụ Ý nghĩa


Số nguyên 123, -12 Số thập phân
012, 03777 Số bát phân
0x7F, 0x3fe15 Số hệ 16
39u 0267u, 0xFFu Số không dấu
Số nguyên lớn 12L, 07723L
0xFFL, -10L
0xFFUL,0xFFLU
Số thực 3.1415 -12.3, .327
10e-12, -15.3E12
3.1415F, -12.F
26/09/2019 58

58

29
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 biến


• Một biến phải được khai báo trước khi sử dụng
• Cú pháp khai báo:
KieuDuLieu TenBien;
KieuDuLieu TenBien1, …, TenBien_N;
• Ví dụ:
//Khai báo biến x là một số nguyên 2 byte có dấu
int x;
//Khai báo các biến y, z là các số thực 4 byte
float y,z;
//Sau khi khai báo, có thể sử dụng
x = 3; y = x + 1;
26/09/2019 59

59

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 biến


• Sau khi khai báo, biến chưa có giá trị xác định.
int n; m = 2 * n;  m=?
– Biến cần được gán giá trị trước khi sử dụng
• C cho phép kết hợp khai báo và khởi tạo biến
KieuDuLieu TenBien = GiaTriBanDau;
KieuDuLieu Bien1=GiaTri1, BienN=Gia_TriN;
• Ví dụ:
//Khai báo biến nguyên a và khởi tạo gia tri bằng 3
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
float x = 5.0, y = 7.6;
26/09/2019 60

60

30
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

Dùng chỉ thị #define Không có dấu


chấm phây (;)
• Cú pháp:
# define Tên_hằng Giá_trị
• Ví dụ:
#define MAX_SINH_VIEN 50
#define CNTT “Cong nghe thong tin”
#define DIEM_CHUAN 23.5

26/09/2019 61

61

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

Dùng từ khóa const


• Cú pháp:
const Kiểu Tên_hằng = giá_trị;
• Ví dụ:
const int MAX_SINH_VIEN = 50;
const char CNTT[20] = “Cong nghe thong tin”;
const float DIEM_CHUAN = 23.5;

26/09/2019 62

62

31
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

Chú ý:
• Giá trị của các hằng phải được xác định ngay
khi khai báo.
• Trong chương trình, KHÔNG thể thay đổi
được giá trị của hằng.
• #define là chỉ thị tiền xử lý
– Dễ đọc, dễ thay đổi
– Dễ chuyển đổi giữa các nền tảng phần cứng hơn
– Tốc độ nhanh hơn
26/09/2019 63

63

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


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

26/09/2019 64

64

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

Mục đích sử dụng

• Làm vế phải của lệnh gán.


• Làm toán hạng trong các biểu thức khác.
• Làm tham số thực sự trong lời gọi hàm.
• Làm biểu thức kiểm tra trong các cấu trúc
điều khiển
– Cấu trúc lặp: for, while, do while.
– Cấu trúc rẽ nhánh: if, switch.
26/09/2019 65

65

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


2.2 Biểu thức trong C

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
• Các phép tính được thực hiên

Ví dụ (alpha = 10, beta = 81)


Biểu thức: alpha + sqrt(beta)
: alpha + sqrt(81)
: alpha + 9.0
: 10 + 9.0
: 19.0
26/09/2019 66

66

33
Chương 2: Kiểu dữ liệu và 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ứ số học

• Biểu thức quan hệ

• Biểu thức logic

26/09/2019 67

67

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 số học


• Là biểu thức mà giá trị của nó là các đại
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…),
– 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).
• 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
26/09/2019 68

68

34
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 quan hệ


• Là những biểu thức có sử dụng các toán tử
quan hệ như lớn hơn, nhỏ hơn, khác nhau…
• Chỉ có thể trả về một trong 2 giá trị logic
Đúng (TRUE) hoặc Sai (FALSE)
Ví dụ

26/09/2019 69

69

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


• Là biểu thức trả về các giá trị logic Đúng/Sai
– Các phép toán logic gồm có
AND VÀ logic, sử dụng toán tử &&
OR HOẶC logic, sử dụng toán tử ||
NOT PHỦ ĐỊNH, sử dụng toán tử !
– 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)
– Biểu thức logic cũng trả về một giá trị số học 0/170
26/09/2019

70

35
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ụ

5 * (12 > 6) →?
26/09/2019 71

71

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


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

26/09/2019 72

72

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

Các toán tử chính

Các toán tử cho phép tạo nên các biểu


thức từ các hằng và biến
• Toán tử số học
• Toán tử quan hệ
• Toán tử logic
• Toán tử logic bit
• Toán tử gán
26/09/2019 73

73

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


2.3 Các phép tử trong C

Các toán tử số học


Toán Ý nghĩa Kiểu dữ liệu của Ví dụ
tử toán hạng (int a = 12; float x=3.0)
Đảo dấu float, double, int, long,.. -12, -12.34, - a, - x
-
(Số nguyên hoặc thực) - -a →12, --a →?
Cộng float, double, int, long,.. 12 + -x → 9.0
+
Trừ float, double, int, long,.. 12.0 - -3 →15.0
-
Nhân float, double, int, long,.. 12 * 3.0 →36.0
*
(Số nguyên hoặc thực) 12 * 3 → 36
Chia 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
17.0/3 →5.666667
/ Chia lấy nguyên Số nguyên int, long,.. 17/3→5

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


26/09/2019 74

74

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

Các toán tử quan hệ


<, >, <=, >=, ==, !=
• Dùng cho phép so sánh giá trị 2 toán hạng
• Kết quả phép so sánh là một số nguyên
1 nếu quan hệ có kết quả là đúng,
0 nếu quan hệ có kết quả sai
Ví dụ:
6 > 4 → Trả về giá trị 1
6 < 4 → Trả về giá trị 0
int b =(x !=y);
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

26/09/2019
5 * (12 > 6) → 5 75

75

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


2.3 Các toán tử trong C

Các toán tử logic


Sử dụng để xây dựng các biểu thức logic
• Biểu thức logic có kết quả logic đúng
→ Trả về giá trị 1
• Biểu thức logic có kết quả logic sai
→ Trả về giá trị 0
Các toán tử
Và logic: Op1 && Op2
Hoặc logic: Op1 || Op2
Phủ định logic: ! Op
Oprand: Toán hạng
26/09/2019 76

76

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

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


Và logic ( && ) :
– Cho kết quả đúng (trả về giá trị 1) khi cả 2 toán
hạng đều đúng (khác 0)
– Ví dụ: 3 < 5 && 4 < 6 →1; 3 < 5 && 5 > 6 → 0
Hoặc logic ( || ):
– Cho kết quả sai (trả về giá trị 0) chỉ khi cả 2 toán
hạng đều sai (bằng 0)
– Ví dụ: 4 || 5 < 3 → 1; 5 < 5 || 2 > 6 → 0
Phủ định logic ( ! ):
– Cho kết quả đúng (1) hoặc sai (0) khi toán hạng
là sai (0) hoặc đúng (khác 0)
– Ví dụ: ! 3 → 0; !(2 > 3) → 1;
26/09/2019 77

77

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ử logic bit


Toán tử bit được sử dụng với kiểu số nguyên
Và nhị phân: Op1 & Op2
Hoặc nhị phân : Op1 | Op2
Hoặc có loại trừ nhị phân: Op1 ^ Op2
Đảo bít nhị phân : ~ Op
Oprand: Toán hạng
Dịch trái: Op << n (nhân với 2n)
Dịch phải: Op >> n (Chia với 2n)
Op là giá trị được dịch, n là số bit dịch
26/09/2019 78

78

39
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ử logic bit (tiếp)


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

char r = Op1 & Op2; char r = Op1 | Op2;


01010011 01010011
11011010 11011010
r = 0 1 0 1 0 0 1 0 → (82) r = 1 1 0 1 1 0 1 1 → (-37)
char r = Op1 ^ Op2; char r = ~ Op2;
01010011 11011010
11011010 r = 0 0 1 0 0 1 0 1 → (37)
r = 1 0 0 0 1 0 0 1 → (-119)
unsigned char r = Op1 | Op2; r = 1 1 0 1 1 0 1 1 → 219
26/09/2019 79

79

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ử logic bit (tiếp)


char Op1 = 83, Op2 = -38, Op = 3;
char r = Op1 >> Op;
01010011
r = 0 0 0 0 1 0 1 0 → (10)
char r = Op2 >> Op; unsigned char Op =218;
11011010 unsigned char r =Op >> 3;
r =1 1 1 1 1 0 1 1 → (-5) 11011010
r =0 0 0 1 1 0 1 1 → (27)
char r = Op2 << 2;
r = 0 1 1 0 1 0 0 0 →(104)
26/09/2019
(unsigned) int r = Op2<<2 →? 80

80

40
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
Biến = Biểu_thức;
• Ký tự “=“ là toán tử gán
– Biểu thức bên phải dấu bằng tược tính toán
– Giá trị của biểu_thức được gán cho biến
• Ví dụ:
int a, b, c;
a = 3;
b = a + 5;
c = a * b;

26/09/2019 81

81

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
• 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
biểu_thức bên phải toán tử
– Có thể gán giá trị của biểu thức gán cho một
biến khác
– Có thể sử dụng như một biểu thức bình thường
• Ví dụ:
int a, b, c;
a = b = 2007;
c = (a = 20) * (b = 30);// c→600
26/09/2019 82

82

41
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


Var <op>= Exp  Var = Var <op> Exp
Toán tử số học:
+= -= *= /= %=
Ví dụ: a *= b // a= a * b
Toán tử logic bit:
&= |= ^=
Ví dụ: x &= 0x3F // x = x & 0x3F
Toán tử dịch:
<<= >>=
Ví dụ: s <<= 4 // s = s << 4
26/09/2019 83

83

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


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

26/09/2019 84

84

42
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

Các toán tử

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

• Lấy địa chỉ

• Biểu thức điều kiện

• Toán tử phẩy

26/09/2019 85

85

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

Tăng giảm tự động một đơn vị


++ Tăng tự động ++Var, Var++
-- Giảm tự động --Var, Var--
Variable: Biến
• 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ụ:
int a = 5, b, c, d, e;
b = a++; // b = 5 sau đó a = 6
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
26/09/2019 86

86

43
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

Toán tử lấy địa chỉ


& Tên_biến
Ký tự & là toán tử lấy địa chỉ biến
• Biến thực chất là một vùng .
1

nhớ của máy tính được đặt tên ..


..
→ tên của biến . 157

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

tính đều được đánh địa chỉ. 07 159

→ Mọi biến đều có địa chỉ 160

Ví dụ: .
.
.
int a = 2006;
&a → Địa chỉ của ô nhớ dùng
Kiểu địa chỉ?
26/09/2019
chứa giá trị biến a 87

87

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

Toán tử phỏng điều kiện (biểu thức điều kiện)


exp1 ? exp 2 : exp3
expression: Biểu thức
• Nếu exp1 ≠ 0 (giá trị đúng), biểu thức điều
kiện trả về giá trị của exp2
• Nếu exp1 = 0 (giá trị sai) biểu thức điều kiện
trả về giá trị của exp3
Ví dụ:
float x= 5.2, y = 3.8, z;
z = (x < y) ? x : y;
→ z = 3.8 // z min{x, y}
 if (x < y) z = x; else z = y;
26/09/2019 88

88

44
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

Toán tử phẩy
biểu_thức_1, biểu thức_2,..
• 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
• Các biểu thức được tính toán từ trái qua phải
• Giá trị và kiểu của biểu thức là giá trị và kiểu của
biểu thức cuối cùng, bên phải
Ví dụ:
if (i = 0, a !=b)…
for(i = 0, j = 0; i < 100; i++, j++)….

26/09/2019 89

89

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

Chuyển kiểu
(Kiểu) biểu thức
• Chuyển kiểu tự động
– 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
diễn cao
char → int → long int → float →
double → long double
• Ép kiểu
– Bằng câu lệnh tường minh trong chương trình
– Được sử dụng khi muốn chuyển sang kiểu có
phạm vi biểu diễn thấp hơn
26/09/2019 90

90

45
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

Chuyển kiểu→Ví dụ
#include <stdio.h>
#include <conio.h>
void main(){
long L = 0xABCDEF; float f = 123.456;
int i; L = 11259375; i = -12817(CDEF)
clrscr(); f = 123.456001; L = 123; i = 123
i = (int) L;
printf(“\n L = %ld; i = %d(%X)”, L, i, i);
i = (int) f; L = (long) f;
printf(“\n f = %f; L = %ld; i = %d”, f, L, i);
}
26/09/2019 91

91

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ử


Mức Toán tử Chức năng Chiều
1 -> . [ ] () ++ hậu tố --hậu tố Lựa chọn, chỉ số… →
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

3 * / %
4 + - Toán tử số học lớp cộng →
5 >> << Dịch bit →
6 < <= > >= Toán tử quan hệ →
7 == != Bằng, khác →
8 & AND nhị phân →
9 ^ XOR nhị phân →
10 | OR nhị phân →
11 && AND logic →
12 || OR logic →
13 ?: Toán tử phỏng điều kiện 
14 = *= += <<= &= ... Toán tử gán 
26/09/2019 92

92

46
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ử


Nguyên tắc
• Biểu thức con trong ngoặc được tính toán trước
• Phép toán một ngôi đứng bên trái toán hạng được
kết hợp với toán hạng đi liền nó.
• Toán hạng đứng cạnh hai toán tử
– 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
– 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ụ
a < 10 && 2 * b < c  ( a < 10 ) && ( ( 2 * b ) < c )
Chú ý: int x = 5, a = 5 * x++; → a = 25, x = 6
26/09/2019 93

93

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


Ví dụ
const int N=10; int a= 3, b=4, c;
float S= 0.0; c = a++ * ++b;
int b;
S = N/3 +1;
a= ? b= ? c= ?
b=(S>4);

S= ? b = ?

int k ,num=30;
k =num>5 ? (num <=10 ? 100 : 200): 500;
k=?
26/09/2019 94

94

47
Chương 2: Kiểu dữ liệu và biểu thức trong C
Ví dụ
const int N=10; int a= 3, b=4, c;
float S= 0.0; c = a++ * ++b;
int b;
S = N/3 +1;
a=4 b= 5 c=15
b=(S>4);

S= 4 b = 0

int k ,num=30;
k =num>5 ? (num <=10 ? 100 : 200): 500;
k=200
26/09/2019 95

95

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


Tóm tắt
• Kiểu dữ liệu
– Nguyên : char, unsigned char, int, long,
unsigned int, unsigned long
– Thực : float, double, long double
• Giá trị logic
– Đúng/TRUE : 1 (Khác 0)
– Sai/FALSE : 0
• Toán tử
– Một ngôi : + -; ++ --; ~ !; &; ();
– Hai ngôi : + - * / %; == != < <= > >=; << >>;
&, ^, |, && ||; = *= +=…
– 3 ngôi
26/09/2019
:?: 96

96

48
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
• Chương 3: Vào ra dữ liệu
• Chương 4: Cấu trúc điều khiển
• Chương 5: Mảng, con trỏ và xâu ký tự
• Chương 6: Cấu trúc
• Chương 7: Hàm
• Chương 8: Tệp dữ liệu
26/09/2019 97

97

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


Nội dung chính
1. Các hàm vào ra cơ bản:
– printf()
– scanf()
2. Các hàm vào ra khác
– gets()
– puts()
– getch()
26/09/2019 98

98

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

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


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

26/09/2019 99

99

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


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

Hàm đưa ra dữ liệu

printf()

26/09/2019 100

100

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

Mục đích

• Hiển thị ra màn hình các loại dữ liệu cơ bản


– Số nguyên, số thực, kí tự, xâu kí tự

• Tạo một số hiệu ứng hiển thị đặc biệt


– Xuống dòng, sang trang,…
Cú pháp
printf(xau_dinh_dang [, DS_tham_so]);

26/09/2019 101

101

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


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

Cú pháp
printf(xau_dinh_dang [, DS_tham_so]);
• 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.
– Bao gồm các nhóm kí tự định dạng
– 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ố
• Số lượng tham số trong DS_tham_số bằng số lượng
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.
26/09/2019 102

102

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

Ví dụ
#include <stdio.h>
void main()
{ int a = 5;
float x = 1.234;
printf(” Hien thi mot bieu thuc nguyen %d và
mot so thuc %f ”,2 * a, x);
}

Kết quả:
Hien thi mot bieu thuc nguyen 10 va mot so thuc 1.234000
26/09/2019 103

103

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


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

Xâu định dạng


• Các kí tự thông thường:
– Được hiển thị ra màn hình.

• Các kí tự điều khiển:


– Dùng để tạo các hiệu ứng hiển thị đặc biệt như
xuống dòng (‘\n’)..

• Các nhóm kí tự định dạng:


– Xác định quy cách hiển thị các tham số trong
phần danh_sach_tham_so.

26/09/2019 104

104

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

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


• Mỗi nhóm kí tự định dạng chỉ dùng cho một
kiểu dữ liệu”
Ví dụ: %d dùng cho kiểu nguyên
%f dùng cho kiểu thực
• DS_tham_so phải phù hợp với các nhóm kí
tự định dạng trong xau_dinh_dang về:
– Số lượng; Nếu không phù hợp sẽ hiển
– Thứ tự thị ra kết quả không như ý
– Kiểu dữ liệu; printf(” %d ” ,3.14); →-31457

26/09/2019
C-Free →1374389535 !? 105

105

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


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

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


Ký tự Kiểu dữ liệu Kết quả
%i, %d int, char Số thập phân
%o int, char Số bát phân
(không có 0 đằng trước)
%x %X int, char Số hexa
(chữ thường/chữ hoa)
%u unsigned int/char Số thập phân

26/09/2019 106

106

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

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


Ký tự Kiểu dữ liệu Kết quả
%ld, %li long Số thập phân
%lo long Số bát phân
(không có 0 đằng trước)
%lx, %LX long Số hexa
(chữ thường/chữ hoa)
%lu unsigned long Số thập phân

Nhận xét:
Với kiểu long, thêm ký tự l ngay sau dấu %
26/09/2019 107

107

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


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

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


Ký tự Kiểu dữ liệu Kết quả
%f float/double Số thực dấu phẩy tĩnh
%e, %E float/double Số thực dấu phẩy động
%c int, char Kí tự đơn lẻ
%s char [] Hiển thị xâu kí tự kết
thúc bởi ‘\0’
%% Hiển thị kí tự %

26/09/2019 108

108

54
Chương 3: Vào/Ra dữ liệu
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ự

• Có dạng “%m”,
– m là một giá trị nguyên, không âm.
– m cho biết số chỗ trống dành cho hiển thị
biểu thức tương ứng
Ví dụ:
int a = 1234;
printf(“%5d”,a) → 1234
printf(“%5d”,34)→ 34
ký hiệu cho dấu trắng (space)
26/09/2019 109

109

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


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

Độ rộng hiển thị→Ví dụ

printf("\n%3d %15s %3c", 1, "nguyen van a", 'g');


printf("\n%3d %15s %3c", 2, "tran van b", 'k');

1 nguyen van a g
2 tran van b k

26/09/2019 110

110

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

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


• Có dạng “%m.n”,
– m, n là 2 giá trị nguyên, không âm.
– m cho biết kích thước để hiển thị số thực
– n cho biết kích thước dành cho phần thập
phân, nếu không đủ C sẽ làm tròn khi hiển thị
Ví dụ:
printf("\n%f",17.346); → 17.346000
printf("\n%.2f",17.346); → 17.35
printf("\n%.2f",17.345); → 17.34 !?
printf("\n%8.2f",17.346); → 17.35
printf("\n%8.2f",17.344); → ???
26/09/2019 111

111

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


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

Độ rộng hiển thị→ Chú ý


• Nếu số chỗ cần để hiển thị dữ liệu lớn hơn
được cung cấp trong định dạng  Tự động
cung cấp thêm chỗ mới để hiển thị đầy đủ,
không cắt bớt nội dung của dữ liệu.
Ví dụ:
printf(“%2d”, 1234); → 1234
printf(“%6.3f”, 123.456); → 123.456
printf(“%12.6e”, 123.456); →1.234560e+02
printf(“%12.3e”, 123.456); →1.235e+02
26/09/2019
C-Free →1.235e+002 112

112

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

Căn lề trái - căn lề phải

%-
• 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
Ví dụ:
printf("%-3d%-10s%-5.2f%-3c",5,"Hello",7.5, 'g')
→5Hello7.50g

26/09/2019 113

113

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


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

Hàm nhập dữ liệu

scanf()

26/09/2019 114

114

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

Mục đích
Dùng để nhập dữ liệu từ bàn phím
• Ký tự đơn lẻ
• Chuỗi ký tự
• Số nguyên
– Thập phân, Bát phân, Hexa
• Số thực
– Dấu phẩy tĩnh; Dấu phẩy động
Cú pháp
scanf(xau_dinh_dang[,DS_dia_chi]);
26/09/2019 115

115

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


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

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

116

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

Hoạt động
• Đọc các ký tự được gõ vào từ bàn phím
• Căn cứ vào xâu định dạng, chuyển thông
tin đã nhập sang kiểu dữ liệu phù hợp
• Gán những giá trị vừa nhập vào các biến
tương ứng trong DS_dia_chi
Ví dụ:
int a;
scanf(“%d”,&a); →1234_ → a = 1234
26/09/2019 117

117

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


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

Ghi chú
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
scanf()→Hàm scanf() đọc từ vùng đệm
#include <stdio.h>
int main(){
int a, b;
scanf("%d",&a);
scanf("%d",&b);
printf ("%d %d", a, b);
return 0;
}
26/09/2019 118

118

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

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

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


%c Đọc kí tự đơn lẻ
%d Đọc số thập phân
%o Đọc số bát phân
%x Đọc số hexa
%u Đọc số thập phân không dấu

26/09/2019 119

119

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


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

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


Kí tự Chú thích
%s Đọc xâu kí tự tới khi gặp dấu phân cách
%f Đọc số thực dấu phẩy tĩnh (float)
%ld Đọc số nguyên kiểu long
%lf Đọc số thực dấu phẩy tĩnh (double)
%e Đọc số thực dấu phẩy động
%% Đọc ký tự %

26/09/2019 120

120

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

Ví dụ
#include <conio.h>
#include <stdio.h>
void main(){
// khai bao bien
int a; float x;
char ch; char str[30];
// Nhap du lieu
printf(“Nhap vao mot so nguyen:”); scanf(“%d”,&a);
printf(“\nNhap vao mot so thuc:”); scanf(“%f”,&x);
printf(“\n Nhap vao mot ki tu:”);
fflush(stdin); scanf(“%c”,&ch);
26/09/2019 121

121

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


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

Ví dụ
printf(“\nNhap vao mot xau ki tu:”);
fflush(stdin); scanf(“%s”,str);

// Hien thi du lieu vua nhap vao


printf(“\nNhung du lieu vua nhap vao”);
printf(“\nSo nguyen : %d”,a);
printf(“\nSo thuc : %5.2f”,x);
printf(“\nKy tu : %c”,ch);
printf(“\nXau ky tu : %s”,str);
getch();
}

26/09/2019 122

122

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

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

26/09/2019 123

123

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


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

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ố

26/09/2019 124

124

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

Các quy tắc cần lưu ý


Khi đọc kí tự
Hàm scanf() cho rằng mọi kí tự có trong bộ đệm
của thiết bị vào chuẩn đều là hợp lệ, kể cả các kí
tự tab, xuống dòng hay dấu cách
Khi đọc xâu kí tự:
Hàm scanf() nếu gặp các kí tự dấu trắng, dấu tab
hay dấu xuống dòng thì nó sẽ hiểu là kết thúc
nhập dữ liệu cho một xâu kí tự.
Ghi chú:
Trước khi nhập dữ liệu kí tự hay xâu kí tự nên
dùng lệnh fflush(stdin) để xóa bộ đệm.
26/09/2019 125

125

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


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…


#include <stdio.h>
int main(){
int A, B;
printf("Nhap vao 2 so nguyen : "); scanf("%d %d",&A,&B);
printf("\n");
printf("Tong %d + %d = %d \n", A, B, A + B);
printf("Hieu %d - %d = %d\n", A, B, A - B);
printf("Tich %d x %d = %d\n", A, B, A * B);
printf("Thuong %d / %d = %.3f\n", A, B, (float)A / B);
printf("Chia nguyen %d / %d = %d\n", A, B, A / B);
printf("Chia du %d %% %d = %d\n", A, B, A % B);
printf("\n");
return 0;
}26/09/2019 126

126

63
Chương 3: Vào/Ra dữ liệu
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…

26/09/2019 127

127

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
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 = cos 3a + 5 2 x3 + x + 1 trong đó a = 2 x +  và b = ln( e x+1.23 + 1)
2
log 7 (3x + 2.14b)
26/09/2019 128

128

64
Chương 3: Vào/Ra dữ liệu
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


#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;
}26/09/2019 129

129

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


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

26/09/2019 130

130

65
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


1. Viết chương trình nhập vào từ bàn phím 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
2. Viết chương trình nhập vào từ bàn phím một giá
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.
Ghi chú:
1. Giả thiết  = 3.1416. Cần khai báo hằng PI trong
chương trình.
2.  là hằng số được khai báo trong tệp tiêu đề math.h
và có tên là M_PI
26/09/2019 131

131

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


Nội dung chính
1. Các hàm vào ra cơ bản:
– printf()
– scanf()
2. Các hàm vào ra khác
– gets() Cần nạp thư viện
conio.h
– puts()
#include <conio.h>
– getch()
26/09/2019 132

132

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

gets()
• Mục đích:
– Dùng để nhập vào từ bàn phím một xâu
kí tự bao gồm cả dấu cách, điều mà
hàm scanf() không làm được.
• Cú pháp :
gets (xâu_kí_tự);
• Ví dụ:
char str [40];
printf(“Nhap vao mot xau ki tu:”);
fflush(stdin);
gets(str);
26/09/2019 133

133

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


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

puts()
• Mục đích:
– Hiển thị ra màn hình nội dung xâu_kí_tự
và sau đó đưa con trỏ xuống dòng mới
• Cú pháp:
puts(xâu_kí_tự);
• Ví dụ:
puts(“Nhap vao xau ki tu:”);
Tương đương với lệnh:
printf(“%s\n”,“Nhap vao xau ki tu:“).
26/09/2019 134

134

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

getch()
• Mục đích
– Đợi đọc một ký tự bàn phím
– Thường dùng để chờ người sử dụng
ấn một phím bất kì trước khi kết thúc
chương trình.
• Cú pháp
getch();

26/09/2019 135

135

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


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

Ví dụ
#include <conio.h>
#include <stdio.h>
void main(){
char ten[30], lop[10]; //Kieu chuoi, mang ky tu
puts("Hay cho biet ten ban : ");
fflush(stdin); gets(ten);
puts("Hay cho biet lop ban hoc : ");
fflush(stdin); gets(lop);

printf("\nChao ban %s, sinh viên lop %s\n",ten,lop);


puts("Chuc ban thi qua mon Tin Hoc Dai Cuong");
getch();
}26/09/2019 136

136

68
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

26/09/2019 137

137

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


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
– sprintf(f) / sscanf()  Vào ra từ xâu ký tự
26/09/2019 138

138

69
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
• Chương 3: Vào ra dữ liệu
• Chương 4: Cấu trúc điều khiển
• Chương 5: Mảng, con trỏ và xâu ký tự
• Chương 6: Cấu trúc
• Chương 7: Hàm
• Chương 8: Tệp dữ liệu
26/09/2019 139

139

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


Nội dung chính
1. Cấu trúc lệnh khối
2. Cấu trúc rẽ nhánh
– Cấu trúc if, if … else
– Cấu trúc lựa chọn switch
3. Cấu trúc lặp
– Vòng lặp for
– Vòng lặp while và 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
26/09/2019 140

140

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

Lệnh đơn >< Lệnh ghép


• Lệnh đơn:
– Là biểu thức theo sau bởi dấu ‘;’
– Ví du: x= 0; i++; printf(“Hello”);
• Lệnh ghép (khối lệnh)
– Là tập hợp các câu lệnh (đơn và ghép) được
đặt trong cặp ngoặc nhọn { }
– 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
– Chú ý:
• 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
26/09/2019
• Không đặt dấu ‘;’ sau một lệnh khối 141

141

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


4.1 Cấu trúc lệnh khối

Cấu trúc lồng nhau


• Trong lệnh ghép chứa lệnh ghép khác
– Sự lồng nhau không hạn chế
{//Khai báo đối tượng cục bộ trong khối
lenh;
{//Khai báo đối tượng cục bộ trong khối
lenh;
...
} Nếu các đối tượng được
… khai báo trùng tên nhau ?
}

26/09/2019 142

142

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

Ví dụ
#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);
getch();
}26/09/2019
// ket thuc khoi lenh cua ham main() 143

143

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


4.1 Cấu trúc lệnh khối

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

Biến địa phương / Biến toàn cục


26/09/2019 144

144

72
Chương 4: Cấu trúc điều khiển
Nội dung chính
1. Cấu trúc lệnh khối
2. Cấu trúc rẽ nhánh
– Cấu trúc if, if … else
– Cấu trúc lựa chọn switch
3. Cấu trúc lặp
– Vòng lặp for
– Vòng lặp while và 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
26/09/2019 145

145

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


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

Cấu trúc if …

Đúng Sai
Biểu thức điều kiện

Câu lệnh

Câu lệnh tiếp

if (Biểu thức điều kiện)


if (n % 2 == 0)
Câu lệnh; printf(“so chan”);
Câu lệnh kế tiếp;
26/09/2019 146

146

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

Cấu trúc if….else….


Đúng Sai
Biểu thức điều kiện

Câu lệnh 1 Câu lệnh 2

Câu lệnh tiếp

if (Biểu thức điều kiện) if (x > y)


Câu lệnh 1; z = x;
else else
Câu lệnh 2; z = y;
Câu lệnh kế tiếp; printf(“max: %d”, z);
26/09/2019 147

147

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


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

Lưu ý
Biểu thức điều kiện:
• Là biểu thức trả về giá trị logic đúng/sai
• Giá trị logic đúng/True : khác 0
• Giá trị logic sai/False: bằng 0
Ví dụ
if (2+5) printf(“Hello world! ”);→Chấp nhận
Câu lệnh:
Có thể là một lệnh khối ( Đặt trong cặp { } )

26/09/2019 148

148

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

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;
else
max = a;
printf(“\nSo lon nhat trong 2 so %.4f va %.4f la %.4f “,a,b,max);
getch();
} //ket thuc ham main()
26/09/2019 149

149

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


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

Ví dụ: So sánh 2 số thực được nhập vào

if(a < b)
max = b;
max = a > b ? a : b;
else
max = a;
26/09/2019 150

150

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

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


#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()
26/09/2019 151

151

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


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

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

26/09/2019 152

152

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

Ví dụ: Nhập x và tính hàm


#include <stdio.h>  x 2 + sin 4 2x + 1 khi x  3
#include <math.h> 
f ( x) = 5 khi x = 3
void main() 
{  x − 3 + log 10 ( x 2 − 3) khi x  3
float x, fx;
printf(“\nNhap x: “); scanf(“%f”,&x);
if(x < 3)
fx = x*x+pow(sin(2*M_PI*x),4)+1;
else
if (x==3)
fx = 5;
else
fx = sqrt(x-3) +log10(x*x-3);
printf(“\n Ket quả: %.4f“,fx);
}
26/09/2019 153

153

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


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

Cấu trúc if / if… else lồng nhau


Cấu trúc if.. và if …else có thể lồng nhau
– Khi đó else sẽ tương ứng với if (phía trên,
chưa có else) gần nhất

if (đ/k_1) if (đ/k_1)
if (đ/k_2) { if (đ/k_2)
lệnh_1; lệnh_1;
else }
lệnh_2; else
lệnh_2;
26/09/2019 154

154

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

Cấu trúc if / if… else lồng nhau →Ví dụ


int a, b, c = 10;

if (a==0) a ≠ 0, b=? → c = 10
if (b == 0)
c = 20; a=0, b=0 →c = 20
else
c = 30; a=0, b ≠ 0 →c = 30

if (a==0){ a ≠ 0, b=? → c = 30
if (b == 0)
c = 20; a=0, b=0 →c = 20
}else
c = 30; a=0, b ≠ 0 → c = 10
26/09/2019 155

155

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


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

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


switch (bieu_thuc)
{
case gia_tri_1: lenh_1; [break];
case gia_tri_2: lenh_2; [break];

[default: lenh_n+1; [break];]
}
Câu_lệnh_tiếp
26/09/2019 156

156

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

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

Tính g/trị
Biểu thức

Sai Sai Sai


g/trị b/t=G/trị 1 g/trị b/t=G/trị 2  default ?

Đúng Đúng Đúng

Lệnh_1 Lệnh_2 Lệnh_n+1

Sai Sai Sai


 break ?  break ?  break ?

Đúng Đúng Đúng

Câu_lệnh_tiếp
26/09/2019 157

157

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


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

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

Cơ chế hoạt động


• Tính giá trị của biểu_thức,
• 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
từ khóa case
• Xảy ra 2 khả năng

26/09/2019 158

158

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

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.
• Thực hiện lệnh_i
• Nếu tồn tại lệnh break,
• Nhảy tới tiếp tục thực hiện Câu_lệnh_tiếp nằm
sau cấu trúc switch
• Nếu không tồn tại lệnh break
• Thực hiện các lệnh sau lệnh_i cho tới khi gặp
break hoặc tới khi thoát khỏi cấu trúc switch
• Thực hiện Câu_lệnh_tiếp

26/09/2019 159

159

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


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

Cấu trúc lựa chọn switch→cơ chế hoạt động

• Không tồn tại giá_trị_i (i = 1, 2, …n) nào


bằng giá trị biểu thức
• Nếu có nhãn default:
• Chương trình sẽ thực hiện lệnh_n+1
• Thực hiện Câu_lệnh_tiếp nằm ngay sau cấu trúc
switch.
• Nếu không có nhãn default:
• Chương trình chuyển sang thực hiện lệnh tiếp theo
nằm ngay sau cấu trúc switch: Câu_Lệnh_tiếp

26/09/2019 160

160

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

Cấu trúc lựa chọn switch→Ví dụ 1

Lập trình đọc từ bàn phím một số


nguyên 1N 10 và đưa ra từ tiếng
Anh tương ứng

26/09/2019 161

161

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


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

Cấu trúc lựa chọn switch→Ví dụ 1


#include <stdio.h>
void main(){
int N;
printf(“\nNhap mot gia tri so nguyen khong am: “); scanf(“%d”,&N);
switch(N) {
case 1: printf(“ %d -> One \n”,N); break;
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”);
}
}26/09/2019 162

162

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

Cấu trúc lựa chọn switch→ Thực hiện

26/09/2019 163

163

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


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

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).

26/09/2019 164

164

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

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


#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();
}
26/09/2019 165

165

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


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

Cấu trúc lựa chọn switch →Thực hiện

26/09/2019 166

166

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

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


Có thể sử dụng đặc điểm Không có lệnh
break chương trình sẽ tự động chuyển
xuống thực hiên các câu lệnh tiếp sau để
viết chung mã lệnh cho các trường hợp
khác nhau nhưng được xử lý như nhau

Ví dụ:Trong một năm các tháng có 30 ngày là 4, 6,


9, 11 còn các tháng có 31 ngày là 1, 3, 5, 7, 8, 10,
12. Riêng tháng hai có thể có 28 hoặc 29 ngày.
Hãy viết chương trình nhập vào 1 tháng, sau đó
đưa ra kết luận tháng đó có bao nhiêu ngày
26/09/2019 167

167

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


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

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


#include <conio.h>
#include <stdio.h>
void main () {
int thang; clrscr();
printf("\nNhap vao thang trong nam "); sanf("%d",&thang);
switch(thang) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12: printf("\n Thang %d co 31 ngay ",thang);
break;
26/09/2019 168

168

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

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


case 4:
case 6:
case 9:
case 11: printf("\n Thang %d co 30 ngay ",thang);
break;
case 2: printf ("\ Thang 2 co 28 hoac 29 ngay");
break;
default : printf("\n Khong co thang %d", thang);
break;
}
getch();
}

26/09/2019 169

169

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


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

Cấu trúc lựa chọn switch→Lưu ý

• Giá trị của biểu thức trong cấu trúc


switch phải là số nguyên (kiểu đếm được)
– Phải có kiểu dữ liệu là char, int, long
• Các giá trị sau từ khóa case (gia_tri_1,
gia_tri_2,.. ) cũng phải là số nguyên

Điều kiện trong cấu trúc if / if..else cho phép


làm việc với các kiểu dữ liệu khác số
nguyên
26/09/2019 170

170

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

Các ví dụ
1. Viết chương trình tính cước Taxi theo công
thức:
• 1 km đầu tiên có cước là 10000đ,
• 30 km tiếp theo có giá là 8000đ/1km
• Các km sau đó có giá là 6000đ/1km.
2. Viết chương trình giải phương trình bậc hai
ax2 + bx + c = 0
3. Viết chương trình giải hệ phương trình bậc
nhất a1 x + b1 y = c1

a2 x + b2 y = c2
26/09/2019 171

171

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


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

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


#include <stdio.h>
#include <math.h> //Để sử dụng hàm toán học ceil
void main() {
unsigned long sotien;
float sokm;
printf("\nBan hay cho biet so km da di duoc : ");
scanf("%f", &sokm);
if (sokm <= 1.0)
sotien = 10000;
else
if (sokm <= 31.0)
sotien = 10000 + (ceil(sokm) - 1.0 ) * 8000;
else
sotien = 250000 + (ceil(sokm) - 31) * 6000;
printf("\nSo tien can tra = %lud", sotien);
}
26/09/2019 172

172

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

Ví dụ 1 → Thực hiện chương trình

sotien= sokm <=1.0 ? 10000 : sokm <= 31 ? 10000 + (ceil(sokm) -


1.0 ) * 8000 : 250000+(ceil(sokm) - 31) * 6000;
26/09/2019 173

173

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


4.2 Cấu trúc rẽ nhá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",
(-b + sqrt(delta))/(2*a), (-b - sqrt(delta))/(2*a) );
}
26/09/2019 174

174

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

Ví dụ 2→ Thực hiện chương trình

26/09/2019 175

175

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


4.2 Cấu trúc rẽ nhá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!");
}26/09/2019 176

176

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

Ví dụ 3 → Thực hiện chương trình

26/09/2019 177

177

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


4.2 Cấu trúc rẽ nhá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
26/09/2019 178

178

89
Chương 4: Cấu trúc điều khiển
Nội dung chính
1. Cấu trúc lệnh khối
2. Cấu trúc rẽ nhánh
– Cấu trúc if, if … else
– Cấu trúc lựa chọn switch
3. Cấu trúc lặp
– Vòng lặp for
– Vòng lặp while và 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
26/09/2019 179

179

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


4.3 Cấu trúc lặp

Các cấu trúc lặp

• Vòng lặp for

• Vòng lặp while

• Vòng lặp do while

26/09/2019 180

180

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

for

26/09/2019 181

181

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


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([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

26/09/2019 182

182

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

Sơ đồ cú pháp

26/09/2019 183

183

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


4.3 Cấu trúc lặ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++)
26/09/2019 184

184

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

Ví dụ 1 : Đưa ra các số nguyên lẻ nhỏ hơn 100


1. #include <stdio.h>
2. #include <conio.h>
3. void main(){
4. int i;
5. for(i = 1;i<100;i++) {
6. if(i%2 == 1) printf(“%5d”,i);
7. if((i+1)%20 ==0) printf(“\n”);
8. }
9. getch();
10. }
26/09/2019 185

185

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


4.3 Cấu trúc lặp

Ví dụ 2 : Đưa ra các số nguyên lẻ nhỏ hơn 100


1. #include <stdio.h>
2. #include <conio.h>
3. void main(){
4. int i;
5. for(i = 99;i > 0;i-=2) {
6. printf(“%5d”,i);
7. if( (i-1) % 20 == 0) printf(“\n”);
8. }
9. getch();
10. }
26/09/2019 186

186

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

Ví dụ 3→ Nhập n và đưa ra n!
#include <stdio.h>
#include <conio.h>
void main()
{
long P = 1;
int n, i;
printf(“Nhap n : “);scanf(“%d”,&n);
for(i = 1;i<=n;i++)
P = P * i;
printf(“Ket qua là %ld “,P);
getch();
} Nhap n : 6
Ket qua là 720
26/09/2019 187

187

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


4.3 Cấu trúc lặp

Ví dụ 4 → Nhập n và tính tổng 1 +1/2+..+1/n


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

188

94
Chương 4: Cấu trúc điều khiển
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


#include <stdio.h>
#include <conio.h>
void main()
{int i, a, b, c;
for(i = 100;i<1000;i++){
a = i / 100; 153
b = i % 100 / 10; 370
c = i % 100 % 10;
371
if(a*a*a+b*b*b+c*c*c == i)
printf(“%d \n”,i);
407
}//for
getch();
}26/09/2019 189

189

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


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


#include <stdio.h>
#include <conio.h>
void main()
{ int a, b, c;
for(a = 1;a<=9;a++)
for(b = 0;b<=9;b++)
for(c = 0;c<=9;c++)
if(a*a*a+b*b*b+c*c*c==100*a+10*b+c)
printf(“%d \n”,100*a+10*b+c);
getch();
}
26/09/2019 190

190

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

Chú ý
Không nhất thiết phải có đầy đủ các
thành phần trong vòng lặp for

int getchar(): đọc ký tự từ vùng đệm bàn


phím. Nếu vùng đệm rỗng, đợi người dùng
gõ dãy ký tự (cho tới khi ấn phím Enter), sẽ
trả về ký tự đầu
putchar(int c): đưa ký tự ra màn hình
26/09/2019 191

191

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


4.3 Cấu trúc lặp

Chú ý
1. Biểu thức khởi tạo
Hello world
char c; int i=0;
Hello world
for( ; (c=getchar())! = '\n’ ; i++) So ky tu: 11
putchar(c);
printf(“\nSo ky tu: %d”,i);
2. Biểu thức điều khiển
for(i=0 ; ; c=getchar(), i++) Hello world
if(c==‘\n’) break;
So ky tu: 12
printf(“\nSo ky tu: %d”,i);
3. Thân vòng lặp
for(i=0 ; getchar() != ‘\n’, i++); Hello world
printf(“\nSo ky tu: %d”,i); So ky tu: 11
26/09/2019 192

192

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

while

26/09/2019 193

193

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


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(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
Biểu_thức_điều_kiện luôn đúng  lặp vô hạn lần 194
•26/09/2019
194

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

Sơ đồ cú pháp

Tính toán giá trị của


Biểu thức điều kiên

Lệnh

Biểu thức != 0
Đúng

Sai

26/09/2019 195

195

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


4.3 Cấu trúc lặp

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


#include <stdio.h>
#include <conio.h>
void main(){
long S = 0;
int n;
printf(“Nhap n : “);scanf(“%d”,&n);
while (n > 0){
S = S + n; while (n> 0)
n = n – 1; S += n--;
}
printf(“Ket qua là %ld “,S);
getch();
}

26/09/2019 196

196

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

Tìm số nguyên lớn nhất thỏa mãn 3n5-317n < 5

#include <stdio.h>
#include <conio.h>
#include <math.h>
void main() n = 10
{ while (3*pow(n,5)-317*n >= 5)
clrscr(); n--;
int n=0;
while (3* pow(n,5) - 317*n < 5) n++;
printf("%4d",n-1);
getch();
} n= 3
26/09/2019 197

197

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


4.3 Cấu trúc lặp

Cho biết kết quả thực hiện chương trình


#include <stdio.h>
#include <conio.h>
void main()
{
clrscr();
int i=3;
while (i > 1){
if(i % 2==0) i = i / 2;
else i = i * 3 + 1;
printf("%4d",i);
}
getch(); 10 5 16 8 4 2 1
}
26/09/2019 198

198

99
Chương 4: Cấu trúc điều khiển
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){
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);
} 26/09/2019 199

199

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


4.3 Cấu trúc lặp

do..while

26/09/2019 200

200

100
Chương 4: Cấu trúc điều khiển
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:
do{
lenh;
}while(bieu_thuc_dieu_kien);
• Chương trình kiểm tra điều kiện sau khi lặp
• 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
26/09/2019 201

201

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


4.3 Cấu trúc lặp

Sơ đồ cú pháp

Lệnh

Tính toán giá trị của


Biểu thức điều kiên

Đúng
Biểu thức != 0

Sai
26/09/2019 202

202

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

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


#include <stdio.h>
#include <conio.h>
void main(){
long S = 0;
int n;
printf(“Nhap n : “);scanf(“%d”,&n);
do { do
S = S + n; S += n--;
n = n – 1; while (n> 0);
}while (n > 0);
printf(“Ket qua là %ld “,S);
getch();
} Nhap n : 96
Ket qua là 4656
26/09/2019 203

203

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


4.3 Cấu trúc lặp

Ví dụ

• Nhập vào điểm của một sinh viên, nếu


điểm đó không  [0, 10] thì thông báo cho
người dùng nhập lại.
• Thực hiện:
– Nếu dùng lệnh if
→ Chỉ kiểm tra được 1 lần
– Sử dụng for
Chưa biết trước số lần lặp.
→ Sử dụng vòng lặp không cần xác định trước
số lần lặp: while / do while
26/09/2019 204

204

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

Dùng vòng lặp while


#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);
}
26/09/2019 205

205

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


4.3 Cấu trúc lặp

Dùng vòng lặp while → Kết quả

26/09/2019 206

206

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

Dùng vòng lặp do…while


#include <stdio.h>
void main() {
float diem; clrscr();
printf(“Chuong trinh nhap diem sinh vien\n");
do {
printf("Nhap diem (0<=diem<=10):");
scanf("%f",&diem);
if (diem < 0 || diem > 10)
printf("\nBan nhap khong dung!\n");
} while (diem < 0 || diem > 10);
printf("\nDiem ban vua nhap la: %.2f“, diem);
}
26/09/2019 207

207

Ví dụ: Nhập số và kiểm tra số hoàn hảo


1. #include <stdio.h> fflush(): xóa vùng đệm bàn phím
2. #include <ctype.h>
3. #include <conio.h> toupper(): chuyển sang chữ hoa
4. void main(){
5. long int n, tong, i; getche(): Đọc ký tự tự vùng đệm & hiện
6. char ch; thị lên màn hình (getch() thì không)
7. do {
8. tong = 0;
9. printf("\n\nNhap vao mot so nguyen: "); scanf("%ld",&n);
10. printf("Cac uoc so cua %ld la: ",n);
11. for(i = 1;i<n;i++)
12. if(n % i == 0){
13. printf("%5d",i);
14. tong = tong + i;
15. }//if & for
16. printf("\nTong cac uoc so cua %ld bang %ld",n,tong);
17. if(tong == n) printf("\n %5ld LA so hoan hao“,n);
18. else printf("\n %5ld KHONG LA so hoan hao“,n);
19. printf("\nBan co muon thuc hien lai(c/k)? ");
20. fflush(stdin);
21. }while(toupper(getche()) !='K');
22. printf("\n\nAn phim bat ki de ket thuc ..."); getch();
23. }
26/09/2019 208

208

104
26/09/2019 209

209

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. }
26/09/2019 210

210

105
26/09/2019 211

211

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’

26/09/2019 212

212

106
#include <stdio.h>
#include <conio.h>
void main() {
int a, b;
char ch;
int Fin = 0;
clrscr();
printf("Nhap cac so a, b "); scanf("%d%d",&a,&b);
do{
printf("\nToan tu (+ ; - ; * ; / ; %) "); ch=getche();
switch(ch){
case '+': printf(" Co ket qua: %d\n",a+b); break;
case '-': printf(" Co ket qua: %d\n",a-b); break;
case '*': printf(" Co ket qua: %d\n",a*b); break;
26/09/2019 213

213

case '%': if (b==0) printf(" Chia cho 0\n");


else printf(" Co ket qua: %d\n",a%b);
break;
case '/': if (b==0) printf(" Chia cho 0\n");
else printf(" Co ket qua: %d\n",a/b);
break;
case 'q':
case 'Q': Fin=1; break;
default: printf(" khong co toan tu nay\n");
}
}while(Fin==0);
printf("\nKet thuc, an mot phim...");
getch();
}
26/09/2019 214

214

107
26/09/2019 215

215

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);
26/09/2019 216

216

108
Nhập chuỗi ký tự cho đến khi gặp ký tự ’*’
Tính tần suất xuất hiện nguyên âm ‘a’
1. #include <stdio.h>
2. #include <conio.h>
3. #include <ctype.h>
4. void main(){
5. char c; int n, d;
6. do{
7. printf("\n\n");
8. d=0; n=0;
9. while( (c=getche()) !='*'){
10. n++;
11. if (c=='a') d++;
12. }
13. if(n==0)
14. printf("\nChuoi ky tu rong\n");
15. else
16. printf("\ntan suat xuat hien ky tu 'a' la %5.2f%%\n",(float)100*d/n);
17. printf("Tiep tuc <C/K>?: ");
18. }while(toupper(getche()) != 'K');
19. }
26/09/2019 217

217

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

Ví dụ: Nhập một số nguyên, kiểm tra là số nguyên tố không?


#includ <stdio.h>
#include <math.h>
void main()
{ int N, i, OK = 1;
printf("\nNhap gia tri N : "); scanf("%d", &N);
if (n<2) printf("\nSo %d khong phai so nguyen to",N);
else {
for
for (i=2;
(i=2; i < N;
i<=(int)sqrt(N); i++)i++)
if (N%i == 0) {
OK = 0;
break; i <= (int)sqrt(N)
}
if (OK) printf("\nSo %d la so nguyen to.", N);
else printf("\nSo %d la hop so.", N);
} i= 2;
getch(); while (N % i != 0) i++;
} if (i == N) printf(« so ng to »)
26/09/2019 218

218

109
Chương 4: Cấu trúc điều khiển
Nội dung chính
1. Cấu trúc lệnh khối
2. Cấu trúc rẽ nhánh
– Cấu trúc if, if … else
– Cấu trúc lựa chọn switch
3. Cấu trúc lặp
– Vòng lặp for
– Vòng lặp while và 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
26/09/2019 219

219

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

Mục đích
• Các vòng lặp while/ do ... while/ for sẽ kết
thúc quá trình lặp khi biểu thức điều kiện
của vòng lặp không còn được thỏa mãn.
• Tuy nhiên trong lập trình đôi khi ta cũng cần
thoát khỏi vòng lặp ngay cả khi biểu thức
điều kiện của vòng lặp vẫn còn được thỏa
mãn.
• Để hỗ trợ người lập trình làm việc đó, ngôn
ngữ C cung cấp 2 câu lệnh là continue và
break
26/09/2019 220

220

110
Chương 4: Cấu trúc điều khiển
Continue >< break

26/09/2019 221

221

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

• 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

26/09/2019 222

222

111
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

Ví dụ 1
#include <stdio.h>
#include <conio.h>
void main()
Tính tổng 100 số nguyên đầu tiên
{ ngoại trừ các số chia hết cho 5
int i;
int sum = 0;
for(i = 1;i<=100;i++)
{
if(i % 5 == 0) for(i=1;i<=100;i++)
continue; if (i % 5 != 0)
sum += i; sum += i;
}
}
26/09/2019 223

223

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

break
Thoát khỏi vòng lặp ngay cả khi biểu
thức điều kiện của vòng lặp vẫn còn
được thỏa mãn.
Chú ý:
• break dùng để thoát ra khỏi khối lặp
hiện tại
• break cũng dùng để thoát ra khỏi
lệnh rẽ nhánh switch

26/09/2019 224

224

112
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

Ví dụ 2
#include <stdio.h>
#include <conio.h>
void main() {
int n;
do {
printf(" \nEnter the number :"); scanf("%d", &n);
if (n < 0) {
break;
}
if (n >10) {
printf("Skip the value\n");
continue;
}
printf("The number is: %d", n);
} while (n!= 0);
}26/09/2019 225

225

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

Ví dụ 3
#include <stdio.h>
#include <conio.h>
void main()
{
int i;
for(i = 1;i<=10;i++)
{
if(i == 5) continue;
printf(“%5d”,i);
if(i==7) break;
}
getch();
}
26/09/2019 226

226

113
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

Ví dụ 4
#include <stdio.h>
#include <conio.h>
void main()
{ int i,j;
clrscr();
for(i = 0;i<10;i++) {
for (j=0; j < 10; j ++) {
if(j > i){
break;
}//if
}//for _ j
printf("i:%d j:%d\n",i,j);
}//for_i
getch();
}
26/09/2019 227

227

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

Ví dụ tổng hợp
Viết chương trình thực hiện các công việc
sau
• Nhập vào một dãy số cho tới khi
– Tổng của dãy lớn hơn 1550 hoặc là
– Số phần tử trong dãy lớn hơn 100
• Đưa ra số lượng phần tử nằm trong
khoảng (35, 70)
• Đưa ra trung bình cộng của các phần tử
chia hết cho 7

26/09/2019 228

228

114
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

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

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

26/09/2019 229

229

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

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>


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

26/09/2019 230

230

115
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

Nhập một dãy số cho tới khi thỏa mãn….


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

Kết thúc
26/09/2019 231

231

Đưa ra TBC của các phần tử chia hết cho 7(1)


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

void main(){
i0
int a, i=0,S7=0,d7=0; S70
do{ d70

printf("Nhap vao soNhập nguyen:");


số a
scanf("%d",&a);
i++; i  i+1

if(a%7==0){ đ d7d7+1
a % 7=0
d7++; S7S7+a

S7+=a; s
} i > 100
s
}while (i <= 100); đ
if(d7==0) s đ Thông báo: Không
TBC là: S7/d7 d7=0
printf(“Khong co so chia het có sốcho 7);
chia hết cho 7

else
printf(“Ket qua la %.4f“,(float)
Kết thúc
S7/d7);
}
26/09/2019 232

232

116
Đưa ra TBC của các phần tử chia hết cho 7(2)
#include <stdio.h> Bắt đầu

void main(){
int a, i=0,S7=0,d7=0,S=0; i0 S70
S0 d70
do{
printf("Nhap vaoNhập so sốnguyen:");
a
scanf("%d",&a);
i++; S+=a; i  i+1 SS+a

if(a%7==0){ đ d7d7+1
d7++; a % 7=0
S7S7+a
S7+=a; s
} i > 100
s S > 1550 s
}while ( (i <=100)&&(S <= đ 1550) ); đ
if(d7==0)
printf(“Khong
TBC là: co
S7/d7so chia
s het cho
d7=0 7); báo: Không
đ Thông
có số chia hết cho 7
else
printf(“Ket qua la %.4f“,(float) S7/d7);
Kết thúc
}
26/09/2019 233

233

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

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

#include <stdio.h> i0 S70


void main(){ S0 d70 d0

int a, i=0,S7=0,d7=0,S=0, Nhập số a d = 0;


i  i+1 SS+a
do{
printf("Nhap vao aso đ d7d7+1
nguyen:"); scanf("%d",&a);
% 7=0
S7S7+a
i++; S+=a; s
if(a%7==0){ đ
a>35 &a<70 dd+1
d7++;
s
S7+=a;
s S > 1550 s
} i > 100

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

234

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

Bài tập tại lớp

1. Cho hàm số f ( x) = x 5 + 5 x Lập trình tính và đưa


ra màn hình các cặp giá trị <x,f(x)> với x lấy dãy giá trị -
10;-9.9;-9.8; …..; 4.9;5.0.
2. Đọc vào dãy số cho tới khi gặp một số dương chia hết
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ị đó
3. Nhập vào dãy cho tới khi gặp số 0. Tính trung bình cộng
các số chẵn đã đọc (không tính số 0)
4. Lập trình thực hiện trò chơi bốc sỏi với máy tính
– 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
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
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)

26/09/2019 235

235

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


4.3 Cấu trúc 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
2. #include <math.h> không là số nguyên
3. void main(){ • fabs(x) trả về trị tuyệt đối của x
4. float x, fx; khi là số thực
Có sai số khi x=0.0
5. for(x=-10.0; x<=5.0; x+=0.1){
6. if(x==0) for(int i=-100;i<50;i++){
7. fx = 0.0; x=(float)i/10;
8. else …….
9. fx = pow(x,5)+x/fabs(x) * pow(fabs(x), 0.2);
10. printf("<%4.1f,%7.2f>\n",x,fx);
11. }
12. }
26/09/2019 236

236

118
Chương 4: Cấu trúc điều khiển
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


1. #include <stdio.h>
2. #include <limits.h>

3. void main(){
4. int a, d=0, max = INT_MIN;
5. do {
6. printf("Nhap mot so : "); scanf("%d",&a);
7. if( a > max){
8. max = a;
9. d = 1;
10. }else
11. if (a == max) d++;
12. }while ( a < 0 || a%5 !=0);
13. printf(“Max: %d; Co %d gia tri",max,d);
14. }
26/09/2019 237

237

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


4.3 Cấu trúc lặp

Bài tập

Viết chương trình đọc x và n vào từ bàn phím rồi tính

S = x + x + x +  + x n dâ' u c ăn
x 2 x3 xn
S = 1+ x + + ++
2 3 n
2 3
x x xn
S = 1+ x + + ++
2! 3! n!
x 2
x 3
(−1) n x n
S = 1− x + − ++
2! 3! n!

26/09/2019 238

238

119
Viết chương trình đọc x và n vào từ bàn phím rồi tính
1. #include <stdio.h>
x 2 x3 xn
2. #include <conio.h> S = 1+ x + + ++
3. void main(){ 2! 3! n!
4. int n, i;
5. float x, u = 1.0,S=1.0;
6. clrscr();
7. printf("Nhap vao so nguyen n : "); scanf("%d",&n);
8. printf("Nhap vao so thuc x : "); scanf("%f",&x);
9. for(i = 1; i <= n; i ++){
10. u *= x/i;
11. S += u;
12. }
13. printf("Ket qua la %.8f",S);
14. getch();
15. }
26/09/2019 239

239

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


4.3 Cấu trúc lặp

Bài tập (Tính tổng vô hạn)

Đọc x và eps từ bàn phím và tính biểu thức sau với


độ chính xác nhỏ hơn eps

x 2 x3 (−1) n x n
S1 = 1 − x + − +  + +
2! 3! n!
x3 x5 (−1) n 2 n +1
S2 = x − + +  + x +  // sin( x)
3! 5! (2n + 1)!
x2 x4 (−1) n 2 n
S3 = 1 − + +  + x +  // cos( x)
2! 4! (2n)!

26/09/2019 240

240

120
Nhập x và  và tính với độ chính xác nhỏ hơn 
x 2 x3 (−1) n x n
S = 1− x + − ++ +
2! 3! n!

26/09/2019 241

241

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


Tổng kết
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
26/09/2019 242

242

121
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
• Chương 3: Vào ra dữ liệu
• Chương 4: Cấu trúc điều khiển
• Chương 5: Mảng, con trỏ và xâu ký tự
• Chương 6: Cấu trúc
• Chương 7: Hàm
• Chương 8: Tệp dữ liệu
26/09/2019 243

243

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


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ự
• Mảng xâu ký tự
26/09/2019 244

244

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

Giới thiệu
Bài toán:
• Nhập điểm thi (số nguyên) môn Tin đại cương cho lớp gồm
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
• Tên biến là tên sinh viên
Ví dụ: int An, Anh, Binh1, Binh2, Cuong,….. Van, Viet;
• Tên biến dạng “dx” với x là chỉ số thứ tự của SV trong lớp
Ví dụ: int d1, d2, d3,……,d50;
Nhận xét 1: Không hợp lý
• Có quá nhiều biến (Điểm thi cho toàn trường.. !?)
• Khó khăn cho các thao tác duyệt toàn bộ danh sách
– Số SV học lại: if(d1 <5) d++; if(d2 <5) d++; ……if(d50 <5) d++;

Nhận xét 2: Các biến có chung ý nghĩa, tính chất


26/09/2019 245

245

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


5.1 Mảng

Giới thiệu
• Trong thực tế, thường gặp các đối tượng có
tính chất chung
– Tháng trong năm
– Điểm trung bình của sinh viên trong lớp
• Các đối tượng được nhóm lại dưới một tên
• Đối tượng được đặc trưng bởi tên nhóm và
thứ tự trong nhóm
– Tháng thứ 3 trong năm: Tháng 3
– Sinh viên thứ 17 trong lớp:…
• Số thứ tự của đối tương trong nhóm là chỉ
số phần tử
26/09/2019 246

246

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

Khái niệm mảng


• Kiểu mảng là một kiểu dữ liệu gồm
– 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ở
hay là kiểu thành phần.
• Mỗi phần tử của mảng được tham khảo
thông qua
– Tên mảng và
– Chỉ số của phần tử trong mảng
Ví dụ:
– <d7>: Điểm thi tin của sinh viên thứ tự 7 trong lớp
26/09/2019 247

247

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


5.1 Mảng

Khai báo mảng

Kiểu_dữ_liệu Tên_Mảng[Kích thước];

• Kiểu_dữ_liệu: kiểu của các phần tử trong


mảng (nguyên, thực, ký tự, chuỗi, mảng,…)
• Tên_mảng: tên của mảng
• Kích_thước_mảng: số phần tử trong mảng
Ví dụ
// khai báo mảng 50 phần tử có kiểu dữ liệu int
int DiemTin[50];
float A[10]; // Mảng 10 phần tử kiểu số thực
26/09/2019 248

248

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

Cấp phát bộ nhớ cho mảng


• Các phần tử trong mảng được cấp phát các
ô nhớ kế tiếp nhau trong bộ nhớ
• Kích thước của mảng bằng kích thước một
phần tử nhân với số phần tử
Ví dụ:
int A[10];//Mảng A gồm 10 phần tử nguyên
A[0] A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8] A[9]

Kích thước của mảng A: 10 x 2 = 20 bytes

26/09/2019 249

249

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


5.1 Mảng

Truy nhập đến thành phần của mảng


• Biến mảng lưu trữ địa chỉ ô nhớ đầu tiên
trong vùng nhớ được cấp phát
• Ngôn ngữ C đánh chỉ số các phần tử trong
mảng bắt đầu từ 0
• Các phần tử của mảng được truy nhập
thông qua
– Tên mảng và
– Chỉ số của phần tử của phần tử trong mảng

Tên_Mang[Chỉ_số_phần_tử];
26/09/2019 250

250

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

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


int A[10];//Mảng A gồm 10 phần tử nguyên
7
A[0] 5
A[1] A[2] A[3] 7
A[4] A[5] A[6] A[7] A[8] A[9]
A

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

A[0] = 7;
A[1] = 5;
A[4] = 7;
int N = A[1] + A[4]; → N = 12

26/09/2019 251

251

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


5.1 Mảng

Ví dụ
int A[10];
for(int i = 0; i < 10; i++) A[i]= 2* i;

0? 2? 4? 6
? 8? 10
? 12
? 14
? 16
? 18
?

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

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

252

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

Mảng nhiều chiều


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

Kiểu Tên[Chiều_1] [Chiều_2]… [Chiều_N];

• 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ố
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
phần tử thuộc kiểu Kiểu
26/09/2019 253

253

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


5.1 Mảng

Mảng nhiều chiều


int t[3][4] ;

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]

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

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

26/09/2019 254

254

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

Mảng nhiều chiều→Ví dụ


int b[3][4][5]; b[2][2][4]
b[2]
b[1]
b[0]

b[0][1][2]

• Mảng b gồm 3 phần tử b[0], b[1], b[2]


• Mỗi phần tử là mảng hai chiều gồm 4 hàng
(hàng 0, 1, 2, 3) và 5 cột (0, 1, 2, 3, 4)
• Mỗi phần tử có kiểu nguyên có dấu, 2 byte
26/09/2019 255

255

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


5.1 Mảng

Khởi tạo giá trị cho mảng


Các phần tử của mảng có thể được khởi tạo
giá trị ngay khi khai báo
Ví dụ
int a[4] = {1,4,6,2};
int b[2][3]={ {1,2,3}, {4,5,6} };
int t[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
26/09/2019
}; 256

256

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

Khởi tạo giá trị cho mảng → Chú ý


• Số lượng giá trị khởi tạo không được lớn
hơn số lượng phần tử trong mảng
– Nếu số lượng này nhỏ hơn, các phần tử còn lại
được khởi tạo giá trị 0
int A[3][4] = { {1}, {4,5} };
int A[3][4] = { };Tất cả đều mang giá trị 0
• 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
mảng
int A1 [8] = {2, 4, 6, 8, 10, 12, 14, 16};
int A2 [] = {2, 4, 6, 8, 10, 12, 14, 16};
26/09/2019 257

257

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


5.1 Mảng

Các thao tác thường gặp


• Nhập/Xuất dữ liệu cho mảng
– Mảng 1 chiều, ma trận
• Bài toán đếm
– Đếm số phần tử
– Tính toán trên các phần tử..
• Tìm kiếm phần tử
– Lớn nhất/nhỏ nhất/bất kỳ
• Sắp xếp phần tử trong mảng
– Theo thứ tự, theo nguyên tắc
• Chèn thêm phần tử, xóa phần tử
26/09/2019 258

258

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

Nhập dữ liệu
Dùng hàm scanf()
Ví dụ: int Table[10];
• Nhập dữ liệu cho một phần tử
scanf(“%d”,&Table[2]);phần tử thứ 3 của mảng
• Nhập dữ liệu cho cả mảng
– Dùng vòng lặp for
for(i = 0; i < 10; i++)
scanf(“%d”,&Table[i]);
– Nên in ra chỉ số phần tử khi nhập
26/09/2019
printf(“Table[%d] : ”,i); scanf(“%d”,&Table[i]) 259

259

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


5.1 Mảng

Nhập dữ liệu→Ví dụ 1
Nhập vào lượng mưa (mm) trong năm
#include <stdio.h>
#define MONTHS 12
int main(){
int rainfall[MONTHS], i;
for ( i=0; i < MONTHS; i++ ){
printf(“Nhap luong mưa tháng %d: “, i+1);
scanf("%d", &rainfall[i] );
}
return 0;
}
26/09/2019 260

260

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

Nhập dữ liệu→Lưu ý
• Nếu số phần tử của mảng chỉ được biết tại
thời điểm thực hiện chương trình (nhưng biết
số phần tử tối đa)
– Khai báo mảng với kích thước tối đa
– Sử dụng biến nguyên lưu số phần tử thực sự của
mảng.
Ví dụ:
• Nhập vào mảng không quá 100 số thực
– Khai báo mảng thực Table có tối đa 100 phần tử.
– 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)
26/09/2019 261

261

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


5.1 Mảng

Nhập dữ liệu→Ví dụ 2
#include<stdio.h>
void main(){
float A[100];
int n, i;
do{
printf(“\n Cho biet so phan tu cua mang: “);
scanf(“%d”,&n);
}while (n>100 || n<=0);
for(i = 0; i < n; i++){
printf(“A[%d] = ", i); scanf("%f",&A[i]);
}
}
26/09/2019 262

262

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

Xuất dữ liệu trong mảng


Dùng hàm printf()
Ví dụ: int Table[10];
• Hiện thị phần tử thứ 5:
printf(“%d”,Table[4]);
• Để hiển thị tất cả các phần tử:
for(i = 0; i < 10; i++)
printf(“%4d”,Table[i]);
Các kiểu xuất dữ liệu
– Hiển thị tất cả/một phần theo dòng/cột..
– Hiển thị từng k phần tử trên một dòng…
26/09/2019 263

263

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


5.1 Mảng

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


#include <stdio.h>
#define MAX 12
void main(){
int A[MAX], i;
for ( i=0; i < MAX; i++ ){ //Nhập dữ liệu
printf(“A[%d]: “, i+1); scanf("%d", &A [i] );
}
for ( i=0; i < MAX; i++ ){
)
printf( "%4d”
"%4d ”,,,A[i]);
"%d\n” A[i]);
A[i]);
if( (i+1) %4==0) printf(“\n”);
}
}26/09/2019 264

264

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

Xuất dữ liệu trong mảng→Ví dụ 1→Thực hiện

26/09/2019 265

265

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


5.1 Mảng

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. }
18. }
26/09/2019 266

266

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

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

26/09/2019 267

267

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


5.1 Mảng

Đế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);

26/09/2019 268

268

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

Ví dụ: Nhập mảng, đưa ra TBC các số chia hết cho 7


#include<stdio.h>
void main(){
int A[100];
int n, i, d = 0, S=0;
printf(“\n So phan tu cua mang (<100) : “); scanf(“%d”,&n);
for(i = 0; i < n; i++){
printf("A[%d] = ", i); scanf("%d",&A[i]);
}
for(i = 0; i < n; i++)
if(A[i] %7==0){
d++;
S+= A[i];
}
if(d > 0) printf(”TBC so chia het cho 7: %7.2f”,(float)S/d);
else printf(”Trong day khong co so chia het cho 7”);
}26/09/2019 269

269

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


5.1 Mảng

Tìm kiếm phần tử


Tìm phần tử lớn nhất (nhỏ nhất)
– Giả sử phần tử đó là phần tử đầu tiên
– Lần lượt so sánh với các phần tử còn lại
• Nếu phần tử mới của dãy lớn hơn coi đây là phần
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ế
Ví dụ: Tìm tháng có lượng mưa nhiều nhất trong năm
max = rainfall[0];
for(i = 1; i < MONTHS; i++)
if(rainfall[i] > max)
max = rainfall[i];
printf("\n Luong mua nhieu nhat la: %d", max);
26/09/2019 270

270

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

Tìm kiếm phần tử


• Tìm kiếm các phần tử thỏa mãn điều kiện
(giống bài toán đếm)
– Dùng for duyệt toàn bộ
– Nếu cần thiết, dùng thêm mảng ghi lại chỉ số

Ví dụ: Đưa ra danh sách các tháng có lượng


mưa nhiều hơn 50mm
printf(“Thang co luong mua lon hon 500mm”)
for(i = 0; i < MONTHS; i++)
if(rainfall[i] > 50)
printf("\nThang %d", i+1);
26/09/2019 271

271

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


5.1 Mảng

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


• Tìm phần tử đầu tiên của danh sách
– Dùng vòng lặp for kết hợp với break;
– Dùng vòng lặp while

Ví dụ
Đưa ra phần tử đầu của mảng có giá trị
bằng k;

26/09/2019 272

272

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

Tìm kiếm phần tử →Ví dụ


int Table[100]
int N, i, k, f;//N: số phần tử, k phần tử cần tìm
Dùng for
for(i = 0; i < N; i++)
if(Table[i] == k) break;
if(i< N) printf(“Tim thay tai vi tri %d“,i);
Dùng while
i=0; f =0; //f: found. f = 1  k is found
while(i < N && f==0){
if(Table[i] == k) f = 1;
else i++;}
if (f==1) printf(“Tim thay tai vi tri %d”,i);
26/09/2019 273

273

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


5.1 Mảng

Bài tập 1
1. Nhập vào dãy (<100) số, tính và đưa ra màn hình
• Tổng và tích của dãy số
• Các số chia hết cho 3 và lớn hơn 10
• Đếm các số nằm trong đoạn [100,1000)
2. Nhập vào một dãy số; tìm số chẵn nhỏ nhất dãy
3. Nhập dãy số; đếm xem có bao nhiêu bộ 3 số thỏa
mãn điều kiện xi=(xi-1+xi+1)/2
4. Viết chương trình nhập vào từ bàn một dãy số (<100
phần tử). Đưa ra số bé nhất và vị trí những số bằng
số bé nhất
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
2 i +1
a) i i b) i i c) 2 yi +1
i =1 i =1 1
26/09/2019 274

274

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

Bài 1

26/09/2019 275

275

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


5.1 Mảng

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)
– ….
26/09/2019 276

276

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

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ố
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)
– 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í…

26/09/2019 277

277

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


5.1 Mảng

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

Dãy Lượt 1 Lượt 2 Lượt 3 Lượt 4

3 3
2
1 1 1 1 1
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
26/09/2019 278

278

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

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


//Khai báo các biến
int A[100]; //Mảng chứa dữ liệu
int N, i, j, tmp;
//Sắp xếp
for(i = 0; i < N – 1; i++)
for(j = i + 1; j < N; j++)
if(A[i] > A[j]) {
tmp = A[i];
A[i] = A[j];
A[j] = tmp;
}
26/09/2019 279

279

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


5.1 Mảng

Ví dụ

Nhập vào từ bàn phím một mảng các số


nguyên không quá 100 phần tử
Hiển thị dãy số vừa nhập
Sắp xếp dãy theo thứ tự giảm dần
Hiện thị dãy tại mỗi lượt sắp xếp

26/09/2019 280

280

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

Ví dụ
1. #include<stdio.h>
2. void main(){
3. int A[100] ;
4. int N, i, j , t;
5. printf("So phan tu [< 100]: "); scanf("%d",&N);
6. printf("Hay nhap day so...\n");
7. for(i=0; i < N; i++){
8. printf("A[%d] = ",i+1); scanf("%d",&A[i]);
9. }
10. printf("\nDay vua nhap...\n");
11. for(i=0; i < N; i++)
12. printf("%4d", A[i]);
13. printf("\n\n");
26/09/2019 281

281

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


5.1 Mảng

Ví dụ
14. printf("Sap xep day theo thuat toan lua chon");
15. for(i=0; i < N-1; i++){
16. for(j=i+1; j < N; j++)
17. if(A[i] < A[j]) {
18. t = A[i];
19. A[i] = A[j];
20. A[j] = t;
21. }//if & for_j
22. printf("\nLuot %d : ",i+1);
23. for(j=0; j < N; j++)
24. printf("%4d", A[j]);
25. }//for_i
26. }//main
26/09/2019 282

282

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

Ví dụ→Kết quả

26/09/2019 283

283

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


5.1 Mảng

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
26/09/2019 284

284

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

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

2
5 for(i = k+1; i < N; i++)
k
8
3 A[i-1] = A[i];

3
9 N= N - 1;
N 4
9
4

26/09/2019 285

285

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


5.1 Mảng

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
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à
các số còn lại. Đưa cả 2 dãy ra màn hình.
2. Đọc vào dãy số có n phần từ (n<100). Đọc số x và số k
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. 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
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ử
chia hết cho 5 và đưa kết quả ra màn hình

26/09/2019 286

286

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

Bài chữa
#include<stdio.h>
void main(){
int A[100];
int N, i;
//Nhập dữ liệu
printf("So phan tu : "); scanf("%d",&N);
for(i=0; i < N; i ++){
printf("A[%d] = ",i);scanf("%d",&A[i]);
}
//Các thao tác xử lý mảng: chèn, xóa, sắp xếp,…
//Đưa Dữ liệu ra
for(i=0; i < N; i ++)
printf("%4d",A[i]);
}
26/09/2019 287

287

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


5.1 Mảng

Bài chữa → Sắp xếp số chẵn chia hết 3 lên đầu dãy..
1. { int d = 0, t;
2. for(i=0;i < N; i++)
3. if(A[i]%6==0){
4. t=A[i]; A[i]=A[d]; A[d] = t;
5. d++;
6. }
7. for(i=d; i < N; i++)
8. if(A[i]%3 != 0){
9. t=A[i]; A[i]=A[d]; A[d] = t;
10. d++;
11. }
12. }
26/09/2019 288

288

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

Bài chữa → Sắp xếp tăng dần và chèn đúng vị trí


1. { int k = 0,i, j, t;
2. for(i=0;i < N - 1; i++)//Sắp xếp lựa chọn
3. for(j=i+1;j < N ; j++)
4. if(A[i] > A[j]){
5. t = A[j]; A[j] = A[i]; A[i]=t;
6. }
7. printf("Phan tu moi:"); scanf("%d",&k);//Nhập p/tử mới
8. i = N; //Chèn đúng vị trí
9. while( (i > 0) &&(A[i-1] > k) ){
10. A[i] = A[i-1];
11. i--;
12. }
13. A[i] = k;
14. N++;
15. }
26/09/2019 289

289

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


5.1 Mảng

Bài chữa → Xóa các phần tử chia hết cho 5..

1. { // PP: Giữ lại các phần tử không chia hết cho 5


2. int d = 0, i;
3. for(i=0;i < N; i++)
4. if(A[i] % 5 != 0){
5. A[d] = A[i];
6. d++;
7. }
8. N = d;
9. }

26/09/2019 290

290

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

Xóa các phần tử chia hết cho 5 →Kết quả

26/09/2019 291

291

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


5.1 Mảng

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
26/09/2019 292

292

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

Nhập vào một ma trận vuông,..


#include <stdio.h>
void main(){
int A[20][20], N,i,j;
printf("Nhap kich thuoc : "); scanf("%d",&N);
printf("\n");
for ( i=0; i < N; i++ )
for(j=0; j < N; j++) {
printf("Nhap phan tu [%d,%d]:", i+1,j+1);
scanf("%d", &A[i][j] );
}
printf("\n\n MA TRAN DA NHAP \n\n");
for ( i=0; i < N; i++ ){
for(j=0; j < N; j++)
printf( "%4d" ,A[i][j]);
printf("\n");
}
26/09/2019 293

293

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


5.1 Mảng

Đưa ra ma trân tam giác trên, dưới


printf("\n\n MA TRAN TAM GIAC TREN \n\n");
for ( i=0; i < N; i++ ){
for(j=0; j < N; j++)
if(j >= i)
printf( "%4d" ,A[i][j]);
else
printf("%4c",32); //32 là mã ASCII của dấu cách
printf("\n");
}
printf("\n\n MA TRAN TAM GIAC DUOI \n\n");
for ( i=0; i < N; i++ ){
for(j=0; j <= i; j++)
printf( "%4d" ,A[i][j]);
printf("\n");
}
}//main
26/09/2019 294

294

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

Thực hiện

26/09/2019 295

295

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


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ự
• Mảng xâu ký tự
26/09/2019 296

296

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

Giới thiệu

• Là một khái niệm “mạnh“ 00000


00001
trong C
– Cho phép tính toán trên con trỏ
– Sử dụng con trỏ hàm
Biến
• Cho phép truy nhập gián tiếp
tới một đối tượng có địa chỉ
(biến, hàm)
Con trỏ
– Truy nhập trực tiếp→ thông
qua tên FFFFF
Bộ nhớ
26/09/2019 297

297

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


5.2 Con trỏ

Địa chỉ
• Bộ nhớ gồm dãy các ô nhớ
– Mỗi ô nhớ là một byte
– Mỗi ô nhớ có một địa chỉ riêng
• Các biến trong chương trình được lưu tại vùng
nhớ nào đó trong bộ nhớ
• Khi khai báo biến, tùy thuộc vào kiểu, biến sẽ
được cấp một số ô nhớ liên tục nhau
– Biến int được cấp 2 bytes, float được cấp 4 bytes,..
– Địa chỉ của biến, là địa chỉ của byte đầu tiên trong số
các byte được cấp
– Khi gán giá trị cho biến, nội dung các byte cung cấp cho
biến sẽ thay đổi
26/09/2019 298

298

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

Địa chỉ →Ví dụ


int N;
float x; Địa chỉ biến N
?
E8
char Arr[4]; 03
?
N
Địa chỉ biến X
?
00
?
00
?
X
N = 1000;//03E8 1B
Địa chỉ biến Arr ?
41
X=9.6875;//411B0000 ?
01
?
05
for(i=0;i<4;i++) ?
09
Arr
Arr[i]= 4*i+1; ?
0D

Địa chỉ của một biến là địa chỉ byte


nhớ đầu tiên được cung cấp cho Bộ nhớ
biến để lưu trữ dữ liệu
26/09/2019 299

299

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


5.2 Con trỏ

Con trỏ
• Con trỏ là một biến mà 0000
giá trị của nó là địa chỉ Biến nhớ
của một vùng nhớ EB03 ABCD
– Vùng nhớ này có thể dùng
để chứa các biến có kiểu cơ
bản (nguyên, thực, ký tự,…)
hay có cấu trúc (mảng, bản
ghi,..)
• Con trỏ dùng “trỏ tới” một ABCD EFCD
biến nhớ Biến con trỏ
– Có thể trỏ tới một hàm FFFF
– Có thể trỏ tới con trỏ khác Bộ nhớ
26/09/2019 300

300

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

Con trỏ →Khai báo

Kiểu * Tên;
• Tên: Tên của một biến con trỏ
• Kiểu: Kiểu của biến mà con trỏ “Tên” trỏ tới
– Giá trị của con trỏ có thể thay đổi được
• Trỏ tới các biến khác nhau, có cùng kiểu
– Kiểu biến mà con trỏ trỏ tới không thay đổi được
• Muốn thay đổi phải thực hiện “ép kiểu”
Ví dụ:
int * pi; //Con trỏ, trỏ tới một biến kiểu nguyên
char * pc; //Con trỏ, trỏ tới một biến kiểu ký tự
26/09/2019 301

301

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


5.2 Con trỏ

Toán tử địa chỉ (&)


• Ký hiệu: & 0000

• Là toán tử một ngôi, trả Biến N


về địa chỉ của biến ABCD

– Địa chỉ biến có thể được


gán cho một con trỏ, trỏ tới
đối tượng cùng kiểu
Ví dụ
ABCD EFCD
int N; // &N→ ABCD Biến pi
int * pi;
FFFF
pi = &N; // piABCD Bộ nhớ
26/09/2019 302

302

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

Toán tử nội dung (*)


• Ký hiệu: *
0000
• Là toán tử một ngôi, trả về giá
Biến N
trị (nội dung) của vùng nhớ mà ABCD
20
10
con trỏ đang trỏ tới
Ví dụ
int N;
int * pi;
pi = &N; N= 10; *pi = 10; ABCD EFCD
N = 10;//Vùng nhớ mà pi trỏ tới
Con trỏ pi
mang giá trị 10; Vậy *pi=10
*pi = 20;// Vùng nhớ pi trỏ tới được FFFF
gán giá trị 20; Vậy N= 20 Bộ nhớ
26/09/2019 303

303

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


5.2 Con trỏ

Gán giá trị cho con trỏ


• Con trỏ được gán địa chỉ của một biến
– Biến cùng kiểu với kiểu mà con trỏ trỏ tới
• Nếu không, cần phải ép kiểu
• Con trỏ được gán giá trị của con trỏ khác
– Hai con trỏ sẽ trỏ tới cùng một biến(do cùng địa chỉ)
– Hai con trỏ nên cùng kiểu trỏ đến
• Nếu không, phải ép kiểu
• Con trỏ được gán giá trị NULL
Ví dụ: int *p; p = 0;
• Gán nội dung vùng nhớ 2 con trỏ trỏ tới.
Ví dụ: int *p1, *p2; *p1 = *p2;
26/09/2019 304

304

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

Ví dụ
#include <stdio.h> #include <stdio.h>
void main(){ void main(){
int N=5, M=10; int N=5, M=10;
int *p1 = &N; int *p1 = &N;
int *p2 = &M; int *p2 = &M;
*p1 = *p2; p1 = p2;
printf("%d %d",*p1,*p2); printf("%d %d",*p1,*p2);
} }
10 10 10 10

26/09/2019 305

305

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


5.2 Con trỏ

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

6. *p1 = *p2; ABCF


ABCD
7. printf("%d %d",*p1,*p2);
8. }
FFFF
Bộ nhớ
26/09/2019 306

306

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

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

p2 p1
6. p1 = p2; ABCF
7. printf("%d %d",*p1,*p2); ABCD
ABCF
8. }

FFFF
Bộ nhớ
26/09/2019 307

307

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


5.2 Con trỏ

Các phép toán trên con trỏ


• Cộng con trỏ với một số nguyên
– Kết quả: Con trỏ cùng kiểu
• Trừ con trỏ với một số nguyên
– Kết quả: Con trỏ cùng kiểu
• Trừ 2 con trỏ cùng kiểu cho nhau
– Kết quả: Một số nguyên
• Khoảng cách giữa 2 con trỏ được đo bằng số phần tử
thuộc kiểu dữ liệu mà con trỏ trỏ tới

26/09/2019 308

308

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

Các phép toán trên con trỏ→Ví dụ


0000
int N=1000, M=2000,P=3000;
E8 ABC0
int * p1 = &P, *p2 = &N; P 03 ABC1
D0 ABC2
p1 - p2 → -2 M 07 ABC3
B8 ABC4
N 0B ABC5
* (p2-1) → 2000 ABC6

* ++ p1 → 2000 p2 ABC4
p1 ABC0
ABC2
Ghi chú:
• Kiểu int, các phần tử cách nhau 2 bytes FFFF

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

309

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


5.2 Con trỏ

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ỏ
hằng chứa địa chỉ của phần tử đầu tiên của
mảng T (&T [0])
– Không tồn tại phép tính trên tên mảng, hoặc gán
giá trị cho tên mảng (VD: T=…; T++)
• Có thể sử dụng một con trỏ để duyệt mảng
nếu nó được gán giá trị bằng địa chỉ của
mảng (địa chỉ của phần tử đầu tiên)

26/09/2019 310

310

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

Ví dụ
int A[10];
int * p = A; // int *p = &A[0]

for(i = 0; i < 10; i ++)


printf(“%d ”, *(p + i) );
for(i = 0; i < 10; i ++)
printf(“%d ”, p[i]);
for(i = 0; i < 10; i ++)
printf(“%d ”, *(p++) );
26/09/2019 311

311

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


5.2 Con trỏ

Con trỏ void


void * Tên_con_trỏ
• 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
dữ liệu bất kỳ
– 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
Ví dụ:
void * p, *q;
int n; float x;
p = & n; q= & x; \\Các câu lệnh hợp lệ
26/09/2019 312

312

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

Câu hỏi 1

#include<stdio.h>
int main() 30
{
int a=3, *p;
p = &a;
printf("%d\n", a * *p * a + *p);
return 0;
}

26/09/2019 313

313

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


5.2 Con trỏ

Câu hỏi 2
#include<stdio.h>
int main(){
int arr[2][2][2] = {10, 2, 3, 4, 5, 6, 7, 8};
int *p, *q;
p = &arr[1][1][1];
q = (int *) arr;
8, 5
printf("%d, %d\n", *p, *(q+4) );
return 0;
}

26/09/2019 314

314

157
Chương 5: Mảng, con trỏ và xâu ký tự
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ự
• Mảng xâu ký tự
26/09/2019 315

315

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


5.3 Xâu ký tự

Khái niệm xâu ký tự


• Xâu kí tự (string) là một dãy các kí tự viết
liên tiếp nhau
– Độ dài xâu là số kí tự có trong xâu
– Xâu không có kí tự nào: Xâu rỗng
• Ví dụ: “Tin hoc”, “String”
• Lưu trữ: kết thúc xâu bằng kí tự ‘\0’ hay
NULL (mã ASCII là 0)

‘T’ ‘i’ ‘ n ‘ ‘ ‘ ‘h’ ‘o’ ‘c’ ‘\0’


26/09/2019 316

316

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

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


• Xâu kí tự >< mảng kí tự
– 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ự)
giống như truy nhập vào một phần tử của mảng:
Tên[Chỉ_số]
– 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
• Xâu kí tự độ dài 1 >< kí tự (“A” =’A’ ?)
– ‘A’ là 1 kí tự, được lưu trữ trong 1 byte
– “A” là 1 xâu kí tự, ngoài kí tự ‘A’ còn có kí tự ‘\0’
=> được lưu trữ trong 2 byte
26/09/2019 317

317

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


5.3 Xâu ký tự

Khai báo
char tên_xâu [số_kí_tự_tối_đa];

• Để lưu trữ một xâu có n kí tự chúng ta cần


một mảng có kích thước n+1
– Phần tử cuối cùng chứa ký tự NULL
Ví dụ
• Để lưu trữ xâu “Tin hoc” chúng ta phải khai
báo xâu có số phần tử tối đa ít nhất là 8
char str[8] = “Tin hoc”;

‘T’ ‘i’ ‘ n ‘ ‘ ‘ ‘h’ ‘o’ ‘c’ ‘\0’


26/09/2019 318

318

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

Truy nhập phần tử của xâu


Giống như truy nhập tới một phần tử của
mảng ký tự
tên_xâu [chỉ_số_của_kí_tự]
Ví dụ: char Str[10] = “Tin hoc”;

T i n - h o 1 \0
c \0 ? ?

Str[0] → ‘T’ Str[3] = ‘-’;


Str[3] → ‘ ’ Str[7] = ‘ ’;
Str[7] → ‘\0 ‘ Str[8] = ‘1 ‘ ;
Str[8] → ? Str[9] = ‘\0’; Str: Tin-hoc 1
26/09/2019 319

319

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


5.3 Xâu ký tự

Ví dụ: Nhập xâu và đếm số ký tự ‘*’


#include <stdio.h> Tính chiều dài của xâu
void main(){ d=0;
char Str[100]; while(Str[d] != '\0') d++;
int d=0, i=0;
printf("Nhap xau ky tu: "); gets(Str);
while(Str[i] != '\0'){
if(Str[i]=='*')
d++;
i++;
}
printf("Ket qua : %d",d);
}
26/09/2019 320

320

160
Chương 5: Mảng, con trỏ và 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


1. #include <stdio.h>
2. void main(){
3. char S[100];
4. int i=0;
5. printf("Nhap xau: "); gets(S);
6. while(S[i] != '\0'){ //32 là mã ASCII của phím space
7. if(S[i] != 32 && S[i+1]==32) printf("%c\n",S[i]);
8. else if(S[i] != 32) printf("%c",S[i]);
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
26/09/2019 321

321

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


5.3 Xâu ký tự

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

Tệp tiêu đề : ctype.h


#include <ctype.h>

26/09/2019 322

322

161
Chương 5: Mảng, con trỏ và 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


• int toupper(char ch):
– Chuyển kí tự thường thành kí tự hoa
toupper(‘a’) => ‘A’
• int tolower(char ch)
– Chuyển kí tự hoa thành kí tự thường
tolower(‘B’) => ‘b’
Ví dụ
do{
……….
printf(“Tiep tuc <C/K>? :”); fflush(stdin);
}while(toupper(getche()) !='K');
26/09/2019 323

323

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


5.3 Xâu ký tự

Các hàm xử lý ký tự →Kiểm tra chữ hoa/thường

• int islower(char ch)


– Kiểm tra chữ thường:
• Hàm trả về giá trị khác 0 nếu ch là chữ
thường, ngược lại trả về 0
• Ví dụ: printf("%d ",islower('A'));  0
• int isupper(char ch):
– 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
• Ví dụ: printf("%d ",isupper('A'));  ≠ 0 (1 !?)
26/09/2019 324

324

162
Chương 5: Mảng, con trỏ và 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ố


• int isalpha(char ch):
– Kiểm tra kí tự trong tham số có phải chữ cái
không (‘a’…’z’,’A’,..’Z’). Hàm trả về khác 0 nếu
đúng, ngược lại trả về giá trị bằng 0
– Ví dụ: printf("%d ",isalpha('A'));  ≠ 0 (1 !?)
• int isdigit(char ch):
– Kiểm tra kí tự trong tham số có phải chữ số
(‘0‘,‘1‘,..‘9‘) không. Hàm trả về khác 0 nếu đúng,
ngược lại trả về giá trị bằng 0
– Ví dụ: printf("%d ",isdigit('A'));  0

26/09/2019 325

325

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


5.3 Xâu ký tự

Khái niệm xâu ký tự→Kiểm tra ký tự đặc biệt


• int iscntrl(char ch)
– Kiểm tra kí tự điều khiển (0-31).
– Hàm trả về khác 0 nếu đúng, ngược lại trả về
giá trị bằng 0

• int isspace(char ch)


– Kiểm tra kí tự dấu cách (mã 32), xuống dòng
(‘\n’ 10), đầu dòng (‘\r’ 13), tab ngang (‘\t’ 9), tab
dọc (‘\v’ 11).
– Hàm trả về khác 0 nếu đúng, ngược lại trả về
giá trị bằng 0
26/09/2019 326

326

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

Ví dụ: Nhập xâu, chuyển thành xâu chữ hoa


1. #include <stdio.h>
2. #include <ctype.h>
3. void main(){
4. int i =0;
5. char S[50];
6. printf("Nhap mot xau: "); gets(S);
7. printf("\n\nXau ban dau : %s. ",S);
8. while(S[i] != '\0'){
9. S[i] = toupper(S[i]);
10. i = i + 1;
11. }
12. printf("Xau ket qua : %s",S);
13. }
26/09/2019 327

327

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


5.3 Xâu ký tự

Ví dụ: Nhập xâu và đếm từ, phân cách bởi dấu trắng
#include <stdio.h>
#include <conio.h>
#include <ctype.h>
int main(){
char Str[100]; int d=0, i=0;
printf("Nhap xau ky tu: "); gets(Str);
if(Str[0] == '\0') printf(“ Xau rong ");
else{
if( ! isspace(Str[0]) ) d=1;
i=1;
while(Str[i] != '\0'){
if( isspace(Str[i-1] ) && (! isspace(Str[i])) ) d++;
i++;
}
printf("Ket qua : %d",d);
}
}
26/09/2019 328

328

164
Chương 5: Mảng, con trỏ và xâu ký tự
5.3 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 đề: stdio.h
• Nhập xâu kí tự
– gets(tên_xâu);
– scanf(“%s”,&tên_xâu);
• Hiển thị xâu kí tự
– puts(tên_xâu);
– printf(“%s”,tên_xâu);

Sự khác nhau giữa gets và scanf?


26/09/2019 329

329

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


5.3 Xâu ký tự

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

Tệp tiêu đề: string.h


#include <string.h >
Chú ý:
char str[100] = “Hello world”;
char * p = str;
• p là con trỏ, trỏ tới mảng các ký tự/xâu ký tự
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”
•26/09/2019
Xâu ký tự, có thể được khai báo char * 330

330

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

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


size_t strlen(char * xâu)
– Trả về độ dài xâu
printf("%d ",strlen("Hello world"));  11
char * strcpy(char * đích, char * nguồn)
– sao chép nội dung xâu nguồn vào xâu đích,
trả về giá trị xâu nguồn
char Str[20];
printf("%s ",strcpy(Str,"Hello"));  Hello
printf("%s", Str);  Hello
Chú ý: Phép gán Str = “Hello” là không hợp lệ
26/09/2019 331

331

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


5.3 Xâu ký tự

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


int strcmp(char * xâu_1, char * xâu_2)
– So sánh hai xâu.
– Trả về giá trị 0 nếu hai xâu giống nhau;
– Giá trị < 0: xâu_1 < xâu_2
– Giá trị >0: xâu_1 > xâu_2
Ví dụ
char Str[20];
strcpy(Str,“hello“);
printf(“%d”, strcmp(Str,”hello”));→0
printf(“%d”, strcmp(Str,”hello!”); →-1 (!?)
printf(“%d”, strcmp(Str,”Hello”); → 1 (!?)
26/09/2019 332

332

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

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


char * strcat(char * xđích, char * nguồn)
– Ghép nối xâu nguồn vào ngay sau xâu đích, trả
lại xâu kết quả
Ví dụ
char Str[20];
strcpy(Str,"Hello ");
printf("%s ",strcat(Str,"world"));  Hello world
printf("\n%s",Str);  Hello world

26/09/2019 333

333

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


5.3 Xâu ký tự

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


char * strchr (char * s, int c)
– Trả về con trỏ trỏ tới vị trí xuất hiện đầu tiên
của ký tự c trong s. Nếu không có trả về con
trỏ null
strcpy(Str,"Hello world");
printf("%s ",strchr(Str,‘o'));  o world
char* strstr(char * s1, char * s2)
– 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
26/09/2019 334

334

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

Các hàm xử lý xâu ký tự (tiếp)


Tệp tiêu đề: stdlib.h
• int atoi(char * str):
– Chuyển một xâu kí tự thành một số nguyên
tương ứng
– Ví dụ: atoi(“1234”) →1234
• int atol(char * str):
– Chuyển xâu kí tự thành số long int
• float atof(char * str):
– Chuyển xâu kí tự thành số thực
– Ví dụ: atof(“123.456E-2”) →1.23456
• Thất bại cả 3 hàm: trả về 0
26/09/2019 335

335

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


5.3 Xâu ký tự

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>
2. #include <string.h>
3. void main(){
4. int d =0;
5. char S1[50],S2[20], *p;
6. printf("Nhap xau thu nhat: "); gets(S1);
7. printf("Nhap xau thu hai: "); gets(S2);
8. p = strstr(S1,S2);
9. while(p !=NULL ){
10. d = d + 1;
11. p = strstr(p+1,S2);//vi tri tim kiem ke tiep
12. }
13. printf("Xau \“ %s\" x/hien trong xau \"%s \“ %d lan",S2,S1,d);
14. }
26/09/2019 336

336

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

Ví dụ 2: Kiểm tra xâu đối xứng


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

337

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


5.3 Xâu ký tự

Ví dụ 3: Đảo ngược xâu ký tự


#include<stdio.h>
#include<string.h>
main(){
char s[100],c;
int i, n;
printf("Nhap xau: ");gets(s);
n =strlen(s);
for(i=0;i <n/2;i++){
c = s[i];
s[i] = s[n-i-1];
s[n-i-1]=c;
}
printf("%s",s);
}

26/09/2019 338

338

169
Chương 5: Mảng, con trỏ và 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


#include<stdio.h>
#include<ctype.h>
#include<string.h>
main(){
char s[20];
int dem[26] = {};
int i,n;
puts("Nhap vao xau ki tu:");gets(s);
n=strlen(s);
for(i=0;i<n;i++)
if(isalpha(s[i]))
dem[ tolower(s[i ]) - 'a‘ ]++;
for(i=0;i<26;i++)
if(dem[i]!=0)
printf("Ki tu %c xuat hien %d lan\n",'a'+i,dem[i]);
}26/09/2019 339

339

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


5.3 Xâu ký tự

Mảng xâu ký tự
• Xâu ký tự có thể là kiểu phần tử của mảng
• Khai báo
char DS[100][30];
Mảng có tối đa 100 phần tử, các phần tử là
xâu có độ dài tối đa 30
• Sử dụng
– Như một mảng bình thường
– Mỗi phần tử mảng được sử dụng như một xâu
ký tự

26/09/2019 340

340

170
Chương 5: Mảng, con trỏ và 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
#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
}26/09/2019 341

341

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


5.3 Xâu ký tự

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

26/09/2019 342

342

171
Nhập dãy (<100) xâu cho tới khi gặp xâu “***”
Đưa ra màn hình xâu có độ dài lớn nhất
1. #include <stdio.h>
2. #include <string.h>
3. void main(){
4. int i, n = 0, d=0;
5. char DS[100][30], s[30]="";
6. do{
7. printf("Nhap xau thu [%d]: ",n+1); gets(DS[n]);
8. if( strcmp(DS[n],"***")) n= n + 1;//Không tính xâu “***”
9. else break;
10. }while(1);
11. for(i = 0; i < n; i++)
12. if(strlen(DS[i]) > d){
13. d = strlen(DS[i]);
14. strcpy(s,DS[i]);
15. }
16. printf("\n\nXau dai nhat la: %s, co do dai :%d\n",s,d);
17. }
26/09/2019 343

343

Chương 5: Mảng, con trỏ và 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


#include <stdio.h>
#include <string.h>
void main(){
int i, j, N;
char DS[100][30], str[30];
//Nhap DS sinh viên
printf("So sinh vien : "); scanf("%d",&N);
fflush(stdin);
for(i=0;i < N;i++){
printf("Ten sinh vien[%d]: ",i);
gets(DS[i]);
}
26/09/2019 344

344

172
Chương 5: Mảng, con trỏ và 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


//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
26/09/2019 345

345

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


5.3 Xâu ký tự

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

26/09/2019 346

346

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

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


//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);
}
}
26/09/2019 347

347

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


5.3 Xâu ký tự

Ví dụ

26/09/2019 348

348

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

Bài tập
1. Nhập vào 2 xâu S1, S2 và một số nguyên k. Hãy
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)
2. Một văn bản gồm không quá 60 dòng, mỗi dòng
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 đó
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ó.
2. Thay tất cả các chuỗi « hanoi » (nếu có) bằng chuỗi
« HANOI »
3. Đếm xem trong văn bản có bao nhiêu từ (các từ phân
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
26/09/2019 349

349

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
• Chương 3: Vào ra dữ liệu
• Chương 4: Cấu trúc điều khiển
• Chương 5: Mảng, con trỏ và xâu ký tự
• Chương 6: Cấu trúc
• Chương 7: Hàm
• Chương 8: Tệp dữ liệu
26/09/2019 350

350

175
Chương 6: Cấu trúc
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ụ
26/09/2019 351

351

Chương 6: 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

Để quản lý cần lưu trữ các thông tin


• Số báo danh: Số nguyên không dấu
• Họ tên sinh viên: Chuỗi ký tự không quá 30
• Khối thi: Ký tự (A,B,C..)
• Tổng điểm 3 môn thi: kiểu thực
Do vậy với mỗi sinh viên cần các biến
unsigned SBD;
char Ten[30];
char KhoiThi;
float KetQua;
26/09/2019 352

352

176
Chương 6: 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)

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


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

#define MAX 1000


unsigned DS_SBD[MAX];
char DS_Ten[MAX][30];
char DS_KhoiThi[MAX];
float DS_KetQua[MAX];

26/09/2019 353

353

Chương 6: 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)


DS_SBD
123 456 789

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

DS_KhoiThi
A D A
DS_KetQua
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
26/09/2019 354

354

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

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


Dùng nhiều mảng
- Khó quản lý, dễ nhầm lẫn
- Không thể hiện cấu trúc thông tin dành cho từng
thí sinh
Cấu trúc thông tin
Mảng các cấu
dành cho một thí sinh
trúc thông tin
dành cho thí sinh THÔNGTIN TINTHÍ
THÍSINH
SINH
THÔNG
SốSốbáo
báodanh:…………………
danh:…....123………
THÔNG TIN THÍ SINH
HọvàvàTên:……………………
THÔNG TIN Tên:..Nguyễn
THÍ SINH Văn An..
Họ
SốSốbáo
báodanh:…………………
danh:…………………
Khốithi:……………………….
thi:…………A………….
Khối
HọvàvàTên:……………………
Tên:……………………
Kếtquả:……………………….
quả:………24.5……….
Họ Kết
Khối thi:……………………….
Khối thi:……………………….
Kếtquả:……………………….
quả:………………………. Mỗi phần tử của mảng
Kết là một cấu trúc thông355
tin
26/09/2019

355

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


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

Khái niệm

• Cấu trúc là kiểu dữ liệu phức hợp, do người


dụng tự định nghĩa
– Kiểu cấu trúc bao gồm nhiều thành phần có thể
thuộc các kiểu dữ liệu khác nhau
– Các thành phần: gọi là trường dữ liệu (field)
– Các thành phần, không được truy nhập theo chỉ
số (như mảng) mà theo tên của trường.
Có thể coi một biến cấu trúc là một tập hợp của một
hay nhiều biến rời rạc, thường có kiểu khác nhau
thành một biến có một tên duy nhất để dễ dàng
quản lý và sử dụng
26/09/2019 356

356

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

Khái niệm → Ví dụ

• Kết quả học tập của sinh viên


– TenSV: Chuỗi ký tự
– MaSV: Chuỗi số/ số nguyên
– Điem: Số thực

• Điểm trong mặt phẳng


– Tên điểm: Ký tự (A, B, C..)
– Hoành độ: Số thực
– Tung độ: Số thực

26/09/2019 357

357

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


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ụ
26/09/2019 358

358

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

Khai báo kiểu cấu trúc


struct Tên_kiểu_cấu_ trúc {
<Khai báo các trường dữ liệu>
};

• struct: từ khóa, cho phép người dùng khai báo


kiểu dữ liệu mới: kiểu cấu trúc
• 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
• Khai báo các trường dữ liệu: Danh sách các
khai báo thành phần (trường:field) của cấu trúc
– Giống khai báo biến
– Các trường có thể có kiểu bất kỳ
26/09/2019 359

359

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


6.2 Khai báo cấu trúc

Khai báo kiểu cấu trúc → Ví dụ


Thẻ sinh viên struct SinhVien{
Số hiệu:…(Chuỗi ký tự)..
char SHSV[10];
Tên sinh viên: (Chuỗi ký tự) char Ten[30];
Năm sinh:…(Số nguyên)… int NS;
Khóa:……(Số nguyên)……. int Khoa;
char Lop [10];
Lớp:…… :.(Chuỗi ký tự). …
};

Point2D
struct Point{
Hoành độ (x)…(Số thực).. float x, y;
Tung độ (y)…..(Số thực).. };
26/09/2019 360

360

180
Chương 6: 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 kiểu cấu trúc nhằm tạo định nghĩa


toàn thể cho các cấu trúc sẽ được dùng
sau này
– Không cung cấp không gian nhớ cho kiểu
• Khai báo biến cấu trúc nhằm yêu cầu
chương trình tạo vùng nhớ để lưu trữ các
dữ liệu cho biến cấu trúc
– Chứa dữ liệu của các trường của cấu trúc

26/09/2019 361

361

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


6.2 Khai báo 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
struct Kiểu_cấu_ trúc Tên_biến;
Khai báo trực tiếp
struct {
<Khai báo các trường dữ liệu>
}Tên_biến;
Kết hợp với khai báo kiểu
struct Kiểu_cấu_ trúc {
<Khai báo các trường dữ liệu>
}Tên_biến;
26/09/2019 362

362

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

Khai báo biến cấu trúc → Ví dụ


Tồn tại định nghĩa kiểu cấu trúc
struct SinhVien SV1, SV2, Thu khoa;
Khai báo trực tiếp
struct {
float x, y; //Tọa độ trên mặt phẳng
}A, B; //Khai báo 2 điểm A, B
Kết hợp với khai báo kiểu
struct Point_3D{
float x, y, z;// Tọa độ không gian
}A, B;
26/09/2019 363

363

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


6.2 Khai báo cấu trúc

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

Các cấu trúc có thể được khai báo lồng nhau


struct diem_thi {
float dToan, dLy, dHoa;
}
struct thi_sinh{
char SBD[10];
char ho_va_ten[30];
struct diem_thi ket_qua;
} thi_sinh_1, thi_sinh_2;
26/09/2019 364

364

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

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ủa một cấu trúc bên trong cấu trúc khác
struct thi_sinh{
char SBD[10];
char ho_va_ten[30];
struct{
float dToan, dLy, dHoa;
} ket_qua;
} thi_sinh_1, thi_sinh_2;
26/09/2019 365

365

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


6.2 Khai báo cấu trúc

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

Có thể gán giá trị khởi đầu cho một biến cấu
trúc, theo nguyên tắc như kiểu mảng
Ví dụ: struct SinhVien{
struct Date{ char Ten[20];
int day; struct Date{
int month; int day;
int year; int month;
}; int year;
struct SinhVien{ } NS;
char Ten[30]; } SV = {“Tran Anh", 20,12,1990 };
struct Date NS;
} SV = {“Tran Anh", 20, 12, 1990 };
26/09/2019 366

366

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

Định nghĩa kiểu dữ liệu với typedef


typedef <tên_cũ> <tên_mới>;
Mục đích
• Đặt tên mới đồng nghĩa với tên của một kiểu
dữ liệu đã được định nghĩa
– Thường được sử dụng cho kiểu cấu trúc
• Giúp cho khai báo trở nên quen thuộc và ít bị sai hơn
Ví dụ
typedef char Str80[80] ;
typedef long mask;
Str80 str="Bonjour tout le monde !";
26/09/2019
mask a, b; 367

367

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


6.2 Khai báo cấu trúc

Định nghĩa kiểu dữ liệu với typedef

Thường được kết hợp với kiểu cấu trúc để


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
typedef struct { //Định nghĩa một cấu trúc
char SHSV[10];
char Ten[30];
int NS;
int Khoa;
char Lop [10];
} SinhVien; //Đặt tên cho cấu trúc là SinhVien
SinhVien SV; //Tạo một biến cấu trúc
26/09/2019 368

368

184
Chương 6: 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ú ý


Cho phép đặt tên mới trùng với tên cũ
Ví dụ typedef struct {
struct point_3D{ float x, y, z;
float x, y, z; }point_3D;
} point_3D M;
struct point_3D M; point_3D N;
typedef struct point_3D point_3D;
point_3D N;

26/09/2019 369

369

Chương 6: 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ú ý

typedef struct point_2D {


float x, y;
}point_2D, diem_2_chieu, ten_bat_ki;
point_2D X;
diem_2_chieu Y;
ten_bat_ki Z;
Chú ý:
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
26/09/2019 370

370

185
Chương 6: Cấu trúc
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ụ
26/09/2019 371

371

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


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

Truy cập các trường dữ liệu

• Cú pháp
tên_biến_cấu_trúc.tên_trường
• Lưu ý
– Dấu “.” là toán tử truy cập vào trường
dữ liệu trong cấu trúc
– Nếu trường dữ liệu là một cấu trúc =>
sử dụng tiếp dấu “.” để truy cập vào
thành phần mức sâu hơn

26/09/2019 372

372

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

Ví dụ
#include <stdio.h>
void main(){
struct{
char Ten[20];
struct Date{
int day;
int month;
int year;
} NS;
} SV = {"Tran Anh", 20,12, 1990 };
printf(" Sinh vien %s (%d/%d/%d)",
SV.Ten,SV.NS.day,SV.NS.month,SV.NS.year);
}
26/09/2019 373

373

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


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

Ví dụ

Bài toán: Xây dựng một cấu trúc biểu diễn


điểm trong không gian 2 chiều.
– Nhập giá trị cho một biến kiểu cấu trúc này
– Hiển thị giá trị các trường dữ liệu của biến này
ra màn hình.
Thực hiện:
– Cấu trúc gồm: tên điểm, tọa độ x, tọa độ y
– Nhập, hiển thị từng trường của biến cấu trúc
như các biến dữ liệu khác

26/09/2019 374

374

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

Ví dụ
#include<stdio.h>
#include<conio.h>
typedef struct{
char ten[5];
int x,y;
}toado;
void main(){
toado t;
printf("Nhap thong tin toa do\n");
printf("Ten diem: ");gets(t.ten);
printf("Toa do x: ");scanf("%d",&t.x);
printf("Toa do y: ");scanf("%d",&t.y);
printf("Gia tri cac truong\n");
printf("%-5s%3d%3d\n",t.ten,t.x,t.y);
getch();
}26/09/2019 375

375

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


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

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


• C cho phép gán hai biến cấu trúc cùng kiểu:
Biến_cấu_trúc_1 = biến_cấu_trúc_2
• Ví dụ
– Xây dựng cấu trúc gồm họ tên và điểm TĐC của
sinh viên
– Khai báo 3 biến cấu trúc: a, b, c
– Nhập giá trị cho biến a.
– Gán biến a cho biến b
– gán từng trường của a cho c.
– So sánh a, b và c ?
26/09/2019 376

376

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

Ví dụ
#include<stdio.h>
typedef struct{
char hoten[20];
int diem;
}sinhvien;
void main(){
sinhvien a,b,c;
printf("Nhap thong tin sinh vien\n");
printf("Ho ten: ");gets(a.hoten);
printf("Diem:");scanf("%d",&a.diem);
26/09/2019 377

377

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


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

Ví dụ
b=a; //Gán biến cấu trúc
strcpy(c.hoten,a.hoten); //Gán từng trường
c.diem=a.diem;
printf(“Bien a: ");
printf("%-20s%3d\n",a.hoten,a.diem);
printf(“Bien b: ");
printf("%-20s%3d\n",b.hoten,b.diem);
printf(“Bien c: ");
printf("%-20s%3d\n",c.hoten,c.diem);
}
26/09/2019 378

378

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

Ví dụ →Kết quả

26/09/2019 379

379

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


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ụ
26/09/2019 380

380

190
Chương 6: Cấu trúc
6.4 Một số ví dụ

Một số ví dụ
1. Nhập vào 2 số phức và đưa ra tổng và tích của chúng
2. Nhập vào một danh sách (<100) sinh viên gồm họ tên, năm
sinh. Kết thúc nhập khi gặp SV có tên là rỗng
• Đưa danh sách vừa nhập ra màn hình.
• Đưa ra màn hình sinh viên lớn tuổi nhất
3. Nhập danh sách có N (N < 100, nhập từ bàn phím) thí sinh
gồm họ tên, số báo danh, khoa dự thi và điểm thi
• Đưa ra DSSV đã sắp xếp theo kết quả thi
• Đưa ra danh sách sinh viên dự thi khoa CNTT có điểm
thi từ 22.5 trở lên
• Nhập vào một số báo danh 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 « không tìm thấy »
26/09/2019 381

381

Ví dụ 1
#include <stdio.h>
typedef struct {float re, im;} Complex;
void main(){
Complex R, R1, R2;
printf("Phan thuc & phan ao cho so thu nhat :");
scanf("%f%f",&R1.re,&R1.im);
printf("Phan thuc & phan ao cho so thu hai :");
scanf("%f%f",&R2.re,&R2.im);
R.re = R1.re+R2.re; R.im = R1.im+R2.im; //phép cộng số ảo
printf("(%.1f+%.1fi)+(%.1f+%.1fi)=(%.1f+%.1fi)\n",
R1.re,R1.im,R2.re,R2.im,R.re,R.im);
R.re = R1.re*R2.re - R1.im*R2.im; //nhân số ảo
R.im = R1.re*R2.im + R1.im*R2.re;
printf("(%.1f+%.1fi)*(%.1f+%.1fi)=(%.1f+%.1fi)\n",
R1.re,R1.im,R2.re,R2.im,R.re,R.im);
}
26/09/2019 382

382

191
Ví dụ 2
1. #include <stdio.h> for(nfor(i =0;
=0;i<100;
n<100;i++){
n++){
2. #include <string.h> printf("Nhap du lieu cho sinh vien %d: \n", n+1);
i+1);
3. typedef struct{ printf("Ho ten : "); fflush(stdin); gets(SV.Ten);
gets(SV[n].Ten);
4. char Ten[30]; if (strlen(SV[n].Ten)
(strlen(SV.Ten) ==0) ==0)
break;
break;
5. int NS; printf("Nam sinh :");scanf("%d", &SV[n].NS);
&SV.NS);
6. }SinhVien; } DS[n] = SV; n = n + 1;
7. void main(){ }
8. SinhVien DS[100], SV;
9. int n=0,i;
10. do{
11. fflush(stdin);
12. printf("Nhap du lieu cho sinh vien %d: \n", n+1);
13. printf("Ho ten : "); gets(SV.Ten);
14. if (strlen(SV.Ten) >0) {
15. printf("Nam sinh :");scanf("%d", &SV.NS);
16. DS[n] = SV; n = n + 1;
17. }
18. } while (strlen(SV.Ten) > 0);
26/09/2019 383

383

Ví dụ 2
19. //In danh sach sinh vien
20. printf("\n\n");
21. printf(" HO & TEN NAM SINH\n");
22. for(i=0; i < n;i++)
23. printf("%-3d%-30s %6d\n",i+1,DS[i].Ten,DS[i].NS);
24. printf("\n\n");
25. //Tim sinh vien lon tuoi nhat
26. SV = DS[0];
27. for(i=0; i < n;i++)
28. if(DS[i].NS < SV.NS)
29. SV = DS[i];
30. printf("Sinh vien: %s sinh nam: %d lon tuoi nhat",SV.Ten,SV.NS);
31. }//main
26/09/2019 384

384

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

26/09/2019 385

385

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

26/09/2019 386

386

193
Ví dụ 3 (2/5): Nhập dữ liệu từ bàn phím
13. printf("Nhap so thi sinh : "); scanf("%d",&N);
14. for ( i=0; i < N; i++ ){
15. printf("Nhap du lieu cho thi sinh %d: \n", i+1);
16. printf("So bao danh : "); scanf("%d",&DS[i].SBD);
17. printf("Ho ten : ");
18. fflush(stdin); gets(DS[i].Ten);
19. printf("Khoa dang ky : ");
20. fflush(stdin); gets(DS[i].Khoa);
21. printf("Ket qua thi : ");scanf("%f", &DS[i].Diem);
22. printf("\n"); C scanf: floating point format not linked

23. }//for
24. printf("\n\nNhan phim bat ky de xem ket qua thi...");
25. fflush(stdin); getch();
26/09/2019 387

387

Ví dụ 3 (3/5): Danh sách sắp xếp theo điểm thi


26. for(i=0; i < N - 1; i ++) //Sắp xếp DS theo điểm thi
27. for(j=i+1; j < N; j ++)
28. if(DS[i].Diem > DS[j].Diem) {
29. SV=DS[i];
30. DS[i]=DS[j];
31. DS[j]=SV;
32. }
33. printf("\n\n KET QUA THI \n\n");
34. for(i=0; i < N; i ++)
35. printf("%-3d BKA- %-6d %-24s %-6s %-6.1f\n",
++d, DS[i].SBD, DS[i].Ten, DS[i].Khoa, DS[i].Diem);
36. printf("\n\nNhan phim bat ky de xem DSSV khoa CNTT");
37. fflush(stdin); getch();
26/09/2019 388

388

194
Ví dụ 3 (4/5): Danh sách trúng tuyển khoa CNTT
//Dua ra danh sach du thi khoa CNTT
38. d = 0;
39. printf("\n\nDanh sach thi sinh trung tuyen khoa CNTT\n\n");
40. for(i=0; i < N; i ++)
41. if(strcmp(DS[i].Khoa,"CNTT")==0 && DS[i].Diem >=22.5)
42. printf("%-3d BKA%-6d %-24s %-f\n",
++d,DS[i].SBD,DS[i].Ten,DS[i].Diem);

43. printf("\n\nNhan phim bat ky de bat dau tim kiem theo so bao danh");
44. fflush(stdin); getch();

26/09/2019 389

389

Ví dụ 3 (5/5): Tìm kiếm sinh viên


45. do{
46. printf("\nNhap so bao danh can tim : "); scanf("%d",&SBD);
47. for(i=0; i < N; i++)
48. if(DS[i].SBD == SBD){
49. printf("So bao danh : %d \n",SBD);
50. printf("Ho ten : %s \n",DS[i].Ten);
51. printf("Khoa du thi : %s \n", DS[i].Khoa);
52. printf("So bao danh : %.1f \n",DS[i].Diem);
53. break;
54. }
55. if (i == N)
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
26/09/2019 390

390

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

26/09/2019 391

391

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

26/09/2019 392

392

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

26/09/2019 393

393

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


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ó
26/09/2019
nhiều người bằng điểm nhau; loại cả 394

394

197
Bài tập 1
1. #include <stdio.h>
2. #include <string.h>
3. typedef struct{
4. char Ten[30];
5. int NS;
6. }SinhVien;
7. void main(){
8. SinhVien DS[100], SV;
9. int N, i, j, d=0;
10. char ten[30];
11. printf("Nhap so sinh vien : "); scanf("%d",&N);
12. for ( i=0; i < N; i++ ){
13. printf("Nhap du lieu cho sinh vien %d: \n", i+1);
14. printf("Ho ten : "); fflush(stdin);gets(DS[i].Ten);
15. printf("Nam sinh : ");scanf("%d", &DS[i].NS);
16. }
26/09/2019 395

395

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


17. printf("\n\nSINH VIEN SINH NAM 1990\n\n");
18. for(i = 0; i < N; i ++)
19. if(DS[i].NS ==1990)
20. printf("%s\n",DS[i].Ten);

21. printf("\n\nTim SV : "); fflush(stdin); gets(Ten);


22. for(int i=0;i <N; i++)
23. if(strcmp(Ten,DS[i].Ten)==0){
24. printf("Sinh vien: %s\nSinh nam %d\n", DS[i].Ten,DS[i].NS);
25. d = d + 1;
26. } Tìm kiếm chỉ theo tên ?
strcmp(Ten,strrchr(DS[i].Ten,32)+1))
27. if(d==0)
28. printf("Khong co sinh vien: %s trong danh sach\n",Ten);

26/09/2019 396

396

198
Bài tập 1 (tiếp)
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

26/09/2019 397

397

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


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

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

26/09/2019 398

398

199
Bài tập 2 (1/5)
#include <stdio.h>
#include <string.h>

typedef struct{
char Ten[30];
struct{
int T, L, H, S; //S = T+L+H
} DT;
}SinhVien;

void main(){
SinhVien DS[100], TK, SV;
int N,i,j,K;
float C;

26/09/2019 399

399

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


N = 0; //N chứa số sinh viên đã nhập
do{
printf("\nNhap DL cho sv thu %d\n",N+1);
printf("Ten SV : ");
fflush(stdin); gets(DS[N].Ten);
if(strlen(DS[N].Ten)==0) //Độ dài bằng 0  xâu rỗng
break;
else{
printf(« Nhập điểm thi T L H cua SV %s : ",DS[N].Ten);
scanf("%d%d%d",&DS[N].DT.T,&DS[N].DT.L,&DS[N].DT.H);
DS[N].DT.S = DS[N].DT.T + DS[N].DT.L + DS[N].DT.H;
N++;
}
}while(1);
26/09/2019 400

400

200
Bài tập 2 (3/5)
//In ra danh sách vừa nhập
printf("\n\n DANH SACH SINH VIEN\n\n");
printf(" Ten SV Toan Ly Hoa Tong \n");
for(i = 0; i < N; i ++)
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);
//In danh sách trúng tuyển theo điểm chuẩn
printf("\n\nDiem Chuan : ");scanf("%f",&C);
printf("\n\n DANH SACH SINH VIEN TRUNG TUYEN \n\n");
for(i = 0; i < N; i ++)
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);

26/09/2019 401

401

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

//Tìm điểm của thủ khoa, bỏ qua tường hợp điểm liệt
TK = DS[0];
for(i = 1; i < N; i ++)
if(DS[i].DT.S > TK.DT.S)
TK = DS[i];
//Đưa ra danh sách thí sinh có điểm bằng điểm cao nhât
for(i = 0; i < N; i ++)
if(DS[i].DT.S == TK.DT.S)
printf("\n\n THU KHOA: %s \n\n",TK.Ten);

26/09/2019 402

402

201
Bài tập 2 (5/5)
printf("\nSo nguoi trung tuyen:"); scanf("%d",&K);
for(i = 0; i < N - 1; i ++) //Sắp xếp theo tổng điểm thi
for(j = i+1; j < N; j ++)
if(DS[i].DT.S < DS[j].DT.S ){
SV= DS[i];
DS[i]=DS[j];
DS[j] = SV;
}
while((K>0)&&(DS[K-1].DT.S==DS[K].DT.S))K--;
if(K>0){
printf("Diem Chuan La : %4d",DS[K-1].DT.S);
printf("\n\n Danh Sach sinh vien trung tuyen \n");
for(i=0; i < K; i++)
printf("%s\n",DS[i].Ten);
}
}//main
26/09/2019 403

403

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


Bài tập

Bài tập 1
Lập trình thực hiện các công việc sau
▪ Đọc vào từ bàn phím một danh sách thuốc gồm
▪ Tên thuốc (chuỗi không quá 20 ký tự)
▪ Năm hết hạn
▪ Số lượng còn
▪ Đơn giá
Kết thúc nhập khi gặp thuốc có tên »*** »
▪ Đưa danh sách thuốc ra màn hình
▪ Đưa ra danh sách các thuốc đã hết hạn
▪ Xóa khỏi danh sách những thuốc đã hết hạn.
Đưa danh sách mới ra màn hình
▪ Tính tổng giá trị các thuốc đã hết hạn
▪ Đưa ra DS thuốc được sắp xếp theo năm hết hạn
26/09/2019 404

404

202
Chương 6: Cấu trúc
Bài tập

Bài tập 2
Cho một danh sách thành tích thi đấu bóng đá của 32
đội tuyển bao gồm: Tên đội bóng, số bàn thắng, số
bàn thua, số thẻ đỏ, số thẻ vàng
Viết chương trình thực hiện
• Nhập dữ liệu vào từ bàn phím
• Nhập vào tên đội bóng,
• Đưa ra thành thích của đội này
• Nếu không tồn tại, thông báo: không tìm thấy
• Tính và đưa ra màn hình số điểm của các đội nếu
• Mỗi bàn thắng được tính 10 điểm
• Mỗi bàn thua bị phạt 5 điểm, mỗi thẻ vàng trừ 2 điểm,
thẻ đỏ trừ 5 điểm
26/09/2019 405

405

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


Câu hỏi

1. Kết quả đưa ra màn hình


#include<stdio.h> a 12 Mai
typedef struct { b 12 Nam
int SHSV; c 13 Nam
char Ten[25];
d 13 Minh
}SV;
e 14 Minh
void main(){
SV DS[] = { {12, "Mai"},
{13, "Nam"},
{14, "Minh"}};
printf("%d ", DS[1].SHSV);
printf("%s\n", (*(DS+2)).Ten);
}26/09/2019 406

406

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

2. Chỉ ra câu trả lời đúng


Chỉ ra khai báo hợp lệ cho biến SV có kiểu cấu trúc chỉ gồm
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 {


char Ten[20]; char Ten[20];
unsigned NS; unsigned NS;
}; } SinhVien;
SinhVien SV; struct SinhVien SV;
c struct { d typedef struct {
unsigned NS; unsigned NS;
char Ten[20]; char Ten[20];
} SV; } SV;
e Không có câu trả lời nào đúng
26/09/2019 407

407

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
• Chương 3: Vào ra dữ liệu
• Chương 4: Cấu trúc điều khiển
• Chương 5: Mảng, con trỏ và xâu ký tự
• Chương 6: Cấu trúc
• Chương 7: Hàm
• Chương 8: Tệp dữ liệu
26/09/2019 408

408

204
Chương 7: Hàm
Nội dung chính
1. Khái niệm hàm
• Khái niệm chương trình con
• Phân loại: hàm và thủ tục
2. Khai báo và sử dụng hàm
• Khai báo và sử dụng
3. Phạm vi của biến
• Toàn cục và địa phương
• Biến static, biến register
4. Truyền tham số
• Truyền theo giá trị, truyền theo địa chỉ
26/09/2019 409

409

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

Khái niệm & Vai trò

• Khái niệm
– Là một chương trình nằm trong một chương
trình lớn hơn nhằm thực hiện một nhiệm vụ cụ
thể
• Vai trò
– Chia nhỏ chương trình ra thành từng phần để
quản lý
• Phương pháp lập trình có cấu trúc
– Có thể sử dụng lại nhiều lần: printf(), scanf()…
– Chương trình dễ dàng đọc và bảo trì hơn

26/09/2019 410

410

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

Phân loại
Hàm chuẩn – Có
Hàm trong thư viện
(function)
Hàm (người dùng)
Chương Có trả về giá trị tự định nghĩa
trình con
Thủ tục
(procedure)
Không trả về giá trị

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


• Chỉ cho phép khai báo chương trình con là hàm.
• Sử dụng kiểu “void” với ý nghĩa “không là kiểu
dữ liệu nào cả” để chuyển thủ tục về dạng hàm
26/09/2019 411

411

Chương 7: Hàm
Nội dung chính
1. Khái niệm hàm
• Khái niệm chương trình con
• Phân loại: hàm và thủ tục
2. Khai báo và sử dụng hàm
• Khai báo và sử dụng
3. Phạm vi của biến
• Toàn cục và địa phương
• Biến static, biến register
4. Truyền tham số
• Truyền theo giá trị, truyền theo địa chỉ
26/09/2019 412

412

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

Ví dụ
#include<stdio.h>
int bp(int x){
Khai báo int y;
chương y = x * x;
trình con
return y;
}
void main(){
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");
}
26/09/2019 413

413

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

Định nghĩa hàm

Cú pháp
Dòng đầu hàm
Kiểu_hàm Tên_hàm(DS khai báo tham số)
{
Thân hàm

[<Các khai báo cục bộ>]


[<Các câu lệnh>]
}

26/09/2019 414

414

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

Dòng đầu hàm

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


• Mô tả các thông tin được trao đổi giữa bên
trong và bên ngoài hàm.
– Tên 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.
26/09/2019 415

415

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

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

Là tên do người sử dụng tự định nghĩa

• Tuân theo quy tắc đặt tên đối tượng

• Nên mang ý nghĩa gợi ý chức năng của hàm

26/09/2019 416

416

208
Chương 7: 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

• Khai báo các thông tin cần cho hoạt động


của hàm và các thông tin, kết quả tính toán
được hàm trả lại.
– Tham số chứa dữ liệu vào cung cấp cho hàm
– Tham số chứa dữ liệu ra mà hàm tính toán được.
• Các tham số sử dụng trong khai báo hàm là
tham số hình thức.
– Nguyên tắc khai báo tham số hình thức như
giống như khai báo một biến
kiểu_dữ_liệu_của_tham_số tên_của_tham_số

26/09/2019 417

417

Chương 7: 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

• Các tham số cung cấp cho hàm trong quá


trình thực hiện hàm là tham số thực sự
– Kiểu dữ liệu của tham số thực phải giống kiểu dữ
liệu của tham số hình thức tương ứng với tham
số thực sự đó,.
• Một hàm có thể có một, nhiều hoặc không có
tham số nào cả
– Nếu có nhiều tham số, phải được phân cách với
nhau bằng dấu phẩy.
– không có tham số vẫn phải có cặp dấu ngoặc
đơn sau tên hàm
26/09/2019 418

418

209
Chương 7: 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ề


• Thông thường hàm sau khi được thực hiện
sẽ trả về một giá trị kết quả tính toán nào đó.
• Để sử dụng được giá trị đó cần phải biết nó
thuộc kiểu dữ liệu gì.
– Kiểu dữ liệu của đối tượng tính toán được hàm
trả về được gọi là kiểu dữ liệu trả về của hàm.

26/09/2019 419

419

Chương 7: 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ề


• Trong C, kiểu dữ liệu trả về của hàm có thể
là kiểu dữ liệu bất kì (kiểu dữ liệu có sẵn
hoặc kiểu dữ liệu do người dùng tự định
nghĩa) nhưng không được là kiểu dữ liệu
mảng.
• 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.
26/09/2019 420

420

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

Thân hàm

• Danh sách các câu lệnh


• Thường có ít nhất một lệnh return
Họat động của 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
thân hàm
– Gặp lệnh return
• Cú pháp chung
return [biểu_thức];

26/09/2019 421

421

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

Thân hàm (tiếp)

Khi gặp lệnh return biểu_thức


• Tính toán giá trị của biểu_thức,
• Lấy kết quả tính toán được làm giá trị trả về cho
lời gọi hàm
• Kết thúc việc thực hiện hàm, trở về chương trình
đã gọi nó.
Nếu return không có phần biểu_thức,
– Kết thúc thực hiện hàm mà không trả về giá trị
nào cả.
• Dùng khi hàm được khai báo có kiểu trả về là void

26/09/2019 422

422

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

Sử dụng hàm

Tên_hàm (DS_tham_số_thực _sự);


Ví dụ:
N = bp(1);N= bp(3);,…
Lưu ý:
• 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ự).
• Nếu hàm nhận nhiều tham số thì các tham số ngăn cách
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ừ
tham số truyền vào
• Sau khi thực hiện xong, trở về điểm mà hàm được gọi
26/09/2019 423

423

Chương 7: 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


#include<stdio.h>
3
int fun(int a){ fun(3)
a++; 4
return a;
fun(4)
}
5
int main(){ fun(5)
printf("%d\n", fun(fun(fun(3))));
return 0; 6
}
26/09/2019 424

424

212
Chương 7: 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


#include<stdio.h> fun(5)

int fun(int n){


5 * fun(4)
if(n==0) return 1; 4 * fun(3)
else return n*fun(n-1);
} 3 * fun(2)

int main(){ 2 * fun(1)


printf("%d\n", fun(5));
1 * fun(0)
return 0;
} 120 1
26/09/2019 425

425

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

Ví dụ 1: Tính TBC f(a),f(b), f(c) nếu f(x) = f ( x) = x 5 + 5 x

#include <stdio.h>
#include <math.h>
float f(float x){
if(x==0.0)
return 0;
else
return pow(x,5)+x/fabs(x) * pow(fabs(x), 0.2);
}
void main(){
float a, b, c;
printf("So 3 so thuc : "); scanf("%f%f%f",&a,&b,&c);
printf("Ket qua %f \n",(f(a)+f(b)+f(c))/3);
}26/09/2019 426

426

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

Ví dụ 2: Tìm ƯSCLN của dãy số


1. # include <stdio.h>
2. int uscln(int a, int b) {
3. while (a !=b){
4. if(a > b) a = a- b;
5. else b = b - a;
6. }
7. return a;
8. }
9. void main(){
10. int A[100], N, i, r;
11. printf("So phan tu : "); scanf("%d",&N);
12. for(i=0; i < N; i++){
13. printf("A[%d] = ",i+1); scanf("%d",&A[i]);
14. }
15. r = A[0];
16. for(i = 1; i < N; i++)
17. r = uscln(r,A[i]);
18. printf("Ket qua %d \n",r);
19. }
26/09/2019 427

427

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

Giải phương trình f(x)=0 trên đoạn [a,b]


1. #include <stdio.h> Giải phương trình x3-x-1=0
2. #include <math.h>
y
3. float f(float x){
4. return x*x*x-x-1; 1 2
5. } x
6. void main(){
7. float a =1.0, b= 2.0, c, eps = 1.0e-6;
8. do{
9. c =(a+b)/2;
10. if( f(a) * f(c) < 0) b = c;
11. else a = c;
12. }while(fabs(b-a) > eps);
13. printf("Nghiem la : %.6f",(b+a)/2);
14.}
26/09/2019 428

428

214
Chương 7: 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…

#include <stdio.h>
#include <math.h>
typedef struct{
float x, y;
}Point;

float kc(Point A, Point B){


return sqrt(pow(A.x-B.x,2)+pow(A.y-B.y,2));
}
26/09/2019 429

429

Chương 7: 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…


void main(){
Point A, B, C;
float AB,BC,CA,p,S;
printf("Toa do A (x,y) :"); scanf("%f%f",&A.x,&A.y);
printf("Toa do B (x,y) :"); scanf("%f%f",&B.x,&B.y);
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);
p= (AB + BC + CA)/2;
S = sqrt(p*(p-AB)*(p-BC)*(p-CA));
printf("Dien tich ABC %f",S);
}
26/09/2019 430

430

215
Bài tập 1
Cho hàm f(x) được định nghĩa như sau
𝟐𝒙+𝟏 + 𝟏 + 7
𝑓 𝑥 = ൝ 5𝒆 3
𝑘ℎ𝑖 𝑥 ≤ 2
𝑥 + 5𝑥 + 𝑥 + 1 𝑘ℎ𝑖 𝑥 > 2
Hãy viết chương trình thực hiện các công việc sau
• Viết chương trình con tính hàm trên
• Nhập vào từ bàn phím 2 số thực x, y, tính và đưa ra
màn hình (f(x)+f(y))2
• Đưa ra màn hình theo dòng các cặp <x, f(x)> (định
dạng đưa ra là các số thực tĩnh có 2 chữ số sau dấu
chấm) trong đó giá trị của x lần lượt là -5.0; -4.9;
-4.8;…..2.8; 2.9; 3.0.
26/09/2019 431

431

Bài tập 2
• 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ố
– Dùng từ 250 đến 400 số: 3000 đồng/số
– Dùng từ 400 đến 500 số: 4000 đồng/số
– Dùng từ 500 số trở lên: 5000đ/số
• Hãy viết hàm TienDien, trả về số tiền điện phải trả
với tham số vào là số điện năng đã tiêu thụ
• Nhập vào danh sách sử dụng điện của các hộ gia
đình (tên chủ hộ, số điện tiêu thụ), Kết thúc nhập
khi đã đủ 100 hộ hoặc nhập tên chủ hộ là “***”
• Đưa ra màn hình hộ trả tiền điện ít nhât
• Sắp xếp danh sách theo thứ tự tăng của tiền phải trả
26/09/2019 432

432

216
Bài tập 3
Cho hàm f(x) được định nghĩa như sau
3
4 − 𝑥2 + 1 Khi |x| < 2
𝑓 𝑥 = 7 𝐾ℎ𝑖 |𝑥| = 2
3 +1
𝑒𝑥 + log 5 𝑥 2 − 1 𝐾ℎ𝑖 |𝑥| > 2
Hãy viết chương trình thực hiện các công việc sau
• Viết chương trình con tính hàm trê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.
• Nhập vào từ bàn phím một dãy các số thực cho tới khi nhập
đủ 100 số hoặc cho tới khi gặp một giá trị x thỏa mãn f(x) lớn
hơn giá trị lớn nhất trong câu trên.

26/09/2019 433

433

Chương 7: Hàm
Nội dung chính
1. Khái niệm hàm
• Khái niệm chương trình con
• Phân loại: hàm và thủ tục
2. Khai báo và sử dụng hàm
• Khai báo và sử dụng
3. Phạm vi của biến
• Toàn cục và địa phương
• Biến static, biến register
4. Truyền tham số
• Truyền theo giá trị, truyền theo địa chỉ
26/09/2019 434

434

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

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

435

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

Phân loại biến

• Biến toàn cục:


– Biến được khai báo trong chương trình chính,
được đặt sau khai báo tệp tiêu đề.
• Biến cục bộ:
– biến được khai báo trong lệnh khối hoặc
chương trình con, được đặt trước các câu lệnh.
Ghi chú
– Hàm main() cũng là một chương trình con
nhưng là nơi chương trình được bắt đầu
– Biến khai báo trong hàm main() cũng là biến
cục bộ, chỉ có phạm vi trong hàm main().
26/09/2019 436

436

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

Biến static

• Biến cục bộ ra khỏi phạm vi thì bộ nhớ


dành cho biến được giải phóng
• Yêu cầu lưu trữ giá trị của biến cục bộ một
cách lâu dài => sử dụng từ khóa static
Cú pháp:
static <kiểu_dữ_liệu> tên_biến;

26/09/2019 437

437

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

Ví dụ→Kết quả
#include <stdio.h>
# include <conio.h>
void fct() {
static int count = 1;
printf("\n Day la lan goi ham fct lan thu %2d", count++);
}
void main(){
int i;
for(i = 0; i < 10; i++) fct();
getch();
}
26/09/2019 438

438

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

Ví dụ

26/09/2019 439

439

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

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
26/09/2019 440

440

220
Chương 7: Hàm
Nội dung chính
1. Khái niệm hàm
• Khái niệm chương trình con
• Phân loại: hàm và thủ tục
2. Khai báo và sử dụng hàm
• Khai báo và sử dụng
3. Phạm vi của biến
• Toàn cục và địa phương
• Biến static, biến register
4. Truyền tham số
• Truyền theo giá trị, truyền theo địa chỉ
26/09/2019 441

441

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

Ví dụ
# include <stdio.h>
void swap(int a, int b) {
int x = a;
a = b;
b = 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;
}
26/09/2019 442

442

221
Chương 7: Hàm
74 Truyền tham sô

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

• Truyền theo trị


– Dựa trên nguyên tắc truyền những bản sao của
biến được truyền
– Những câu lệnh thay đổi giá trị tham số hình
thức sẽ không ảnh hưởng tới biến được truyền
• Truyền theo biến
– Tham số được truyền sẽ thực sự là biến và các
thao tác sẽ thi hành trực tiếp với biến
– Những câu lệnh thay đổi giá trị tham số hình
thức sẽ ảnh hưởng tới biến được truyền

26/09/2019 443

443

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

Truyền theo biến

• Thực chất là truyền theo địa chỉ của biến


• Khi khai báo hàm [tham số có kiểu “địa chỉ”]:
– Khai báo là một con trỏ, trỏ tới một đối tượng có
kiểu muốn truyền vào
– Ví dụ: void swap (int *pa, int *pb);
• Khi truyền tham số
– Địa chỉ của biến được truyền
Ví dụ: swap(&a,&b)
– Có thể truyền tên của mảng
• Tên mảng là hằng địa chỉ
26/09/2019 444

444

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

Ví dụ 1: Truyền theo địa chỉ của biến


# 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;
}
26/09/2019 445

445

Ví dụ 2: Nhập danh sách các xâu cho tới khi gặp xâu rỗng
Đưa ra xâu có tần xuất xuất hiện nguyên âm lớn nhất

26/09/2019 446

446

223
Chương 6: 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


#include<stdio.h> a 0210
void fun(int n){ b 0102
if(n > 0) { c 1120
fun(--n);
d 0120
printf("%d ", n);
e 0201
fun(--n);
}
}
int main(){
fun(3);
return 0;
}26/09/2019 447

447

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


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

Câu hỏi 2: Kết quả đưa ra màn hình


#include<stdio.h> a 5, 2
void fun(int *i, int *j){ b 2, 5
*i = *i * *i; c 10, 4
*j = *j * *j; d 4, 25
} e 25, 4
int main(){
int i=5, j=2;
fun(&i, &j);
printf("%d, %d", i, j);
return 0;
}
26/09/2019 448

448

224
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


#include<stdio.h> a AB
void fun(char*); b AC
int main(){ c BC
char a[10]="ABCDEF";
d BD
fun(&a[0]);
e CD
return 0;
}
void fun(char *a){
printf("%c", *++a);
a++;
printf("%c", *a);
}26/09/2019 449

449

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
• Chương 3: Vào ra dữ liệu
• Chương 4: Cấu trúc điều khiển
• Chương 5: Mảng, con trỏ và xâu ký tự
• Chương 6: Cấu trúc
• Chương 7: Hàm
• Chương 8: Tệp dữ liệu
26/09/2019 450

450

225
Chương 8: Tệp dữ liệu
Nội dung chính
1. Tệp và phân loại tệp
• Khái niệm và phân loại
• Tệp và mảng
• Tổ chức tệp
2. Các thao tác với tệp
• Khai báo
• Mở tệp
• Đóng tệp
• Truy nhập tệp văn bản
• Truy nhập tệp nhị phân
26/09/2019 451

451

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


8.1 Tệp và phân loại tệp

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

452
26/09/2019

452

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

Phân loại
• Tệp văn bản
– Được tổ chức theo từng dòng
• Trên mỗi dòng là các ký tự ASCII hiện thị được như
chữ cái, chữ số, dấu câu,…
– Cuối mỗi dòng là các ký tự điều khiển
• CR: Carriage Return - mã ASCII 13
• LF:Line Feed- Mã ASCII 10
• Tệp nhị phân
– Các phần tử của tệp là các số nhị phân dung
mã hóa thông tin
– Thông tin được mã hóa: số, cấu trúc dữ liệu,..
453
26/09/2019

453

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


8.1 Tệp và phân loại tệp

Tệp dữ liệu và mảng


• Mảng
– Được lưu trong bộ nhớ →dữ liệu bị mất đi khi tắt
máy
– Truy nhập trực tiếp tới một phần tử qua số hiệu
– Kích thước mảng xác định trước
• Tệp
– Lưu trữ trên thiết bị lưu trữ ngoài→dữ liệu được
lưu trữ lâu dài, không bị mất đi khi tắt máy
– Không truy nhập trực tiếp qua số hiệu phần tử
– Kích thước có thể rất lớn và không cần xác định
trước
454
26/09/2019

454

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

Tổ chức tệp
Phần tử dữ liệu ngay sau khi mở file Ký hiệu đánh dấu kết thúc file

EOF

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ệp là dãy các phần tử kế tiếp nhau
– Sử dụng phần tử đặc biệt (EOF) để đánh dấu kết thúc tệp
• Con trỏ tệp:
– Xác định vị trí phần tử hiện có thể truy cập
– Khi mở file, con trỏ tệp luôn ở vị trí phần tử đầu
– 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
455
26/09/2019

455

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


Nội dung chính
1. Tệp và phân loại tệp
• Khái niệm và phân loại
• Vai trò của tệp
• Tổ chức tệp
2. Các thao tác với tệp
• Khai báo
• Mở tệp
• Đóng tệp
• Truy nhập tệp văn bản
• Truy nhập tệp nhị phân
26/09/2019 456

456

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

Quy trình

• Khai báo biến tệp

• Mở tệp để làm việc


– Phân biệt các loại tệp và các mục đích mở tệp

• Truy nhập tệp


– 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
26/09/2019

457

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


8.2 Thao tác với tệp

Khai báo biến tệp

FILE * Con_Trỏ_Tệp

• Tệp được truy nhập qua con_trỏ_tệp

• Ví dụ
– FILE * f1, *f2;

458
26/09/2019

458

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

Mở tệp
Con_Trỏ_Tệp = fopen(Tên_Tệp, Chế_độ mở)
• 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
– Tên đầy đủ của tệp hoặc tệp trên thư mực hiện thời
• 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
– Kiểu tệp: t: text file; b: binary file
– Chế độ: + Vừa đọc/ vừa ghi
- r : Mở để đọc; Báo lỗi nếutệp chưa tồn tạ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
•26/09/2019
Trả về NULL nếu có lỗi mở tệp 459

459

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


8.2 Thao tác với tệp

Đóng tệp

int fclose(FILE * Con_Trỏ_Tệp)

• Hàm fclose() khi báo trong thư viện stdio.h


• Con_trỏ_tệp: Tên biến tệp

• Kết quả trả về


– 0: Nếu đóng tệp thành công

– EOF: Nếu có lỗi

460
26/09/2019

460

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

Truy nhập tệp văn bản


• Tương tự như với bàn phím/ màn hình
• Yêu cầu chỉ rõ nguồn/đích thông tin
• Các thao tác
– Đọc dữ liệu từ tệp : fscanf() / fgets() /getc()
– Ghi dữ liệu ra tệp : fprintf() / fputs() /putc()
– Dịch chuyển con trỏ tệp : fseek() / rewind()
– Kiểm tra kết thúc tệp : feof()
• Ví dụ:
– fprintf(FILE *fptr, Xâu_định dạng [,DS giá trị])
– fgets(char * Xâu ký tự, int n, FILE *fptr)
461
26/09/2019

461

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


8.2 Thao tác với tệp

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

Đọc dữ liệu
int fread(void * Địa_Chỉ_Đích, int Kích_thước,
int số_phần_tử, FILE *fptr)
– Đọc từ file xác đinh bởi biến fptr một khối dữ liệu
kích thước Số_Phần_Tử x Kích_Thước vào
vùng nhớ xác định bởi Địa_Chỉ_Đích
– Nếu đọc thành công: Trả về số phần tử đọc được
– Nếu không thành công: Trả về giá trị 0
• Ví dụ: int Buf[100]; FILE * fptr =fopen(“so.dat”,”rb”)
fread( Buf, sizeof(int), 100, fptr);
462
26/09/2019

462

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

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

Ghi dữ liệu
int fwrite(void * Đ_Chỉ_Nguồn, int Kích_thước,
int số_phần_tử, FILE *fptr)
– Ghi từ vùng nhớ xác định bởi Địa_Chỉ_nguồn
một khối dữ liệu có kích thước Số_Phần_Tử x
Kích_Thước ra file được xác đinh bởi biến fptr
– Nếu ghi thành công: Trả về số phần tử đã ghi
– Nếu không thành công: Trả về giá trị 0
• Ví dụ: int Buf[100]; FILE * fptr =fopen(“so.dat”,”wb”)
fwrite(Buf, sizeof(int), 100, fptr);
463
26/09/2019

463

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


8.2 Thao tác với tệp

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


Dịch chuyển con trỏ file
int fseek(FILE *fptr, long int N, int Vị_Trí_Đầu)
– Dịch chuyển con trỏ file của file fptr đi một
khoảng N so với Vị_Trí_Đầu
• SEEK_SET / 0: Vị trí đầu là đầu tệp
• SEEK_CUR / 1: Vị trí đầu là vị trí con trỏ file hiện thời
• SEEK_END / 2: Vị trí đầu là cuối tệp
– void rewind(FILE *fptr): Đưa con trỏ về đầu tệp
Kiểm tra kết thúc file
int feof(FILE *fptr) Chú ý khi dùng, có thể lỗi
– Trả về 0 nếu con trỏ file vẫn còn trỏ tới một phần
tử dữ liệu, 1 nếu con trỏ file đang trỏ tới EOF
26/09/2019
464

464

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

Ví dụ 1

• Tạo file Songuyen.dat ghi 100 số lẻ đầu tiên.

#include <stdio.h>
void main(){
FILE * f = fopen(“SoNguyen.Dat”,”wb”);
int i, n;
for(i = 0; i <100; i++){
n = 2*i+1;
fwrite(&n, sizeof(int), 1, f);
}
fclose(f);
}
465
26/09/2019

465

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


8.2 Thao tác với tệp

Ví dụ 2
• Đọ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>
void main(){
FILE * f = fopen("SoNguyen.Dat","rb");
int n;
fseek(f,50*sizeof(int),SEEK_SET);
while(!feof(f)){
fread(&n,sizeof(int),1,f);
printf("%4d",n);
}
fclose(f);
}
26/09/2019
466

466

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

Ví dụ 3
• Nhập vào từ bàn phím 100 số thực và ghi file nhị phân
SO_DUONG.DAT các số thực dương trong các số đã nhập
• Đọc từ file SO_DUONG.DAT và đưa ra màn hình số thực
có giá trị lớn nhất

467
26/09/2019

467

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


8.2 Thao tác với tệp

Ví dụ 4
• Nhập danh sách từ bàn phím các thí sinh dự thi, mỗi thí
sinh gồm họ tên, số báo danh, khoa dự thi và điểm thi. Dữ
liệu nhập được ghi vào file ThiSinh.dat. Kết thúc nhập khi
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
« không tìm thấy » 468
26/09/2019

468

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

Ví dụ 4
#include <stdio.h>
#include <string.h>
typedef struct{
char Ten[30];
long SBD;
char Khoa[10];
float Diem;
}SinhVien;
void main(){
FILE * f1,* f2;
SinhVien SV;
int i, SBD;
//Nhap thong tin cho file ThiSinh.Dat
//Tao file CNTT.Dat
}
26/09/2019
469

469

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


8.2 Thao tác với tệp

Ví dụ 4
//Nhap thong tin cho file ThiSinh.Dat
f1 = fopen("ThiSinh.Dat","wb");
i = 1;
do{
printf("Thi sinh %d :\n", i);
printf(" Ho Ten : "); fflush(stdin); gets(SV.Ten);
if(strcmp(SV.Ten,"***")==0)break;
printf(" So Bao Danh: "); scanf("%d",&SV.SBD);
printf(" Khoa : "); fflush(stdin); gets(SV.Khoa);
printf(" Diem : "); scanf("%f",&SV.Diem);
fwrite(&SV,sizeof(SinhVien),1,f1);
i++;
}while(1);
26/09/2019 fclose(f1);
470

470

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

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

471

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


8.2 Thao tác với tệp

Ví dụ 3
printf("\n\n Tao file CNTT.Dat\n");
i = 0;
rewind(f1);
f2 = fopen("CNTT.Dat","wb");
while(fread(&SV,sizeof(SinhVien),1,f1) > 0)
if(strcmp(SV.Khoa,"CNTT")==0 )
fwrite(&SV,sizeof(SinhVien),1,f2);
fclose(f2);
f2 = fopen("CNTT.Dat","rb"); //doc lai file
while(fread(&SV,sizeof(SinhVien),1,f2) > 0)
printf("%-3d %-5d %-20s %-5.1f\n",
++i, SV.SBD, SV.Ten, SV.Diem);
fclose(f2);
472
26/09/2019

472

236
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
26/09/2019

473

237

You might also like