Thuậ ể ữ ệ ấ ữ ệ KI U D LI U, C U TRÚC D LI U VÀ THU T ...

19
0 K K THU THU T L T L P TRÌNH P TRÌNH KIU DLIU, CU TRÚC DLIU VÀ THUT TOÁN 1 N N I DUNG I DUNG Thut toán Kiudliu và cu trúc dliu Mi liên hgia thut toán và cu trúc dliu Kiu con trtrong C Sdng kiu array trong C Kiu xâu kí ttrong C Sdng struct trong C 2 KH KH Á Á I NI I NI M THU M THU T TO T TO Á Á N N Thut toán (gii thut) là mt quy tc để vi nhng dliu ban đầu đã cho, tìm đượcli gii sau mt khong thi gian huhn Bài toán Thut toán Máy tính Dliu vào Kết qura 3 Tính kết thúc (tính dng) Tính xác định Tính phdng Tính hiu quThc hin nhanh Tiêu phí ít tài nguyên máy tính (bnh) C C Á Á C Đ C Đ C TRƯNG C C TRƯNG C A THU A THU T TO T TO Á Á N N

Transcript of Thuậ ể ữ ệ ấ ữ ệ KI U D LI U, C U TRÚC D LI U VÀ THU T ...

0

KKỸỸ THUTHUẬẬT LT LẬẬP TRÌNHP TRÌNH

KIỂU DỮ LIỆU, CẤU TRÚC DỮ LIỆU VÀ THUẬT TOÁN

1

NNỘỘI DUNGI DUNG

Thuật toán

Kiểu dữ liệu và cấu trúc dữ liệu

Mối liên hệ giữa thuật toán và cấu trúc dữ liệu

Kiểu con trỏ trong C

Sử dụng kiểu array trong C

Kiểu xâu kí tự trong C

Sử dụng struct trong C

2

KHKHÁÁI NII NIỆỆM THUM THUẬẬT TOT TOÁÁNN

Thuật toán (giải thuật) là một quy tắc để với những dữliệu ban đầu đã cho, tìm được lời giải sau một khoảngthời gian hữu hạn

Bài toán

Thuật toán

Máy tính Dữ liệu vào Kết quả ra

3

Tính kết thúc (tính dừng)

Tính xác định

Tính phổ dụng

Tính hiệu quả• Thực hiện nhanh

• Tiêu phí ít tài nguyên máy tính (bộ nhớ)

CCÁÁC ĐC ĐẶẶC TRƯNG CC TRƯNG CỦỦA THUA THUẬẬT TOT TOÁÁNN

4

CCÁÁC ĐC ĐẶẶC TRƯNG CC TRƯNG CỦỦA THUA THUẬẬT TOT TOÁÁNN

Thuật toán tìm UCLN của hai số nguyên dương1. Nhập vào hai số nguyên dương a, b

2. So sánh hai số, chọn số nhỏ nhất gắn cho UCLN

3. Nếu một trong hai số a, b không chia hết cho UCLN thì thựchiện bước 4, ngược lại thì thực hiện bước 5

4. Giảm UCLN một đơn vị và quay lại bước 3

5. In UCLN. Kết thúc

? Các đặc trưng của thuật toán trên

5

TIÊU CHUTIÊU CHUẨẨN ĐN ĐÁÁNH GINH GIÁÁ THUTHUẬẬT TOT TOÁÁNN

Lựa chọn thuật toán nào cho bài toán?

Tiêu chuẩn 1: Thuật toán đơn giản, dễ hiểu, dễ cài đặt

Tiêu chuẩn 2: Thuật toán sử dụng tiết kiệm tài nguyênmáy tính (dung lượng không gian nhớ, thời gian)

6

NGÔN NGNGÔN NGỮỮ THUTHUẬẬT TOT TOÁÁNN

Ngôn ngữ dùng để mô tả thuật toán? Tại sao phải dùng ngôn ngữ diễn đạt thuật toán

? Đặc điểm của ngôn ngữ diễn đạt thuật toán

• Ngôn ngữ liệt kê từng bước (Ngôn ngữ tự nhiên)

• Sơ đồ khối

• Ngôn ngữ “giả code”: Tựa Pascal, tựa C, …– Các bước trong chương trình nên được đánh số thứ tự

– Có thể bỏ qua phần khai báo dữ liệu, thay vào đó là đặc tả cấu trúc dữ liệutrước khi viết giải thuật

Mô tả thuật toán• Thuật toán: <Tên thuật toán>

• Vào (Input): <Dữ liệu vào của thuật toán, mô tả rõ kiểu dữ liệu>

• Ra (Output): <Các dữ liệu ra - Kết quả>

7

NGÔN NGNGÔN NGỮỮ THUTHUẬẬT TOT TOÁÁNN

Ngôn ngữ liệt kê từng bước• Thuật toán: Euclid

• Vào: m,n nguyên dương (m > n)

• Ra: gcd là ước chung lớn nhất của m và n

r: số nguyên dương

Bước 1. Nhập vào m, n

Bước 2. Nếu m, n >0 thì chuyển sang bước 3, ngược lại thì thông báo“Dữ liệu vào không hợp lệ” và kết thúc thuật toán

Bước 3. Nếu m > n thì chuyển sang bước 4. Ngược lại, hoán chuyểngiá trị của m, n

Bước 4. Nếu n = 0 thì gcd = m, in giá trị của gcd và kết thúc. Ngược lại, chuyển sang bước 5.

Bước 5. Tính r là phần dư của phép chia m cho n

Bước 6. Gán giá trị của n cho m và của r cho n. Quay lại bước 4.

8

NGÔN NGNGÔN NGỮỮ THUTHUẬẬT TOT TOÁÁNN

Sơ đồ khối

ĐiĐiềềuu kikiệệnn

LLệệnhnh NNúútt thaothao ttáácc

ChChỉỉ hưhướớngng truytruyềềnn thôngthông tintin

NNúútt điđiềềuu kikiệệnn

NNúútt bbắắtt đđấấuu, , nnúútt kkếếtt ththúúcc

9

NGÔN NGNGÔN NGỮỮ THUTHUẬẬT TOT TOÁÁNN

Thuật toán Euclid

Sai

Sai

Đúng

Đúng

Bắt đầu

Nhập m, n

m, n >0

m >= n

n = 0

gcd = m In gcd

r = m mod n m = n n = r

r = m m = n n = r

Kết thúc

Thông báo Dữ liệu vào

không hợp lệ

Sai Đúng

10

NGÔN NGNGÔN NGỮỮ THUTHUẬẬT TOT TOÁÁNN

Ngôn ngữ Tựa Pascal• Khai báo: Program < Tên chương trình>

Begin …….

End.

• Chú thích {….}

• Phép toán số học: +, - *, /, ↑(luỹ thừa)

• Phép toán so sánh: >, >=, <, <=, =, ≠

• Giá trị logic: true, false

• Phép toán logic: and, or, not

11

NGÔN NGNGÔN NGỮỮ THUTHUẬẬT TOT TOÁÁNN

Các câu lệnh• Câu lệnh gán V := E;

– V: biến, E: biểu thức

– Phép gán chung: V1 := V2 := E;

• Câu lệnh điều kiện if B then S1 [else S2];

• Câu lệnh tuyển Case B1: S1;

B2: S2;

….

Bn: Sn;

else Sn+1

end case;

12

NGÔN NGNGÔN NGỮỮ THUTHUẬẬT TOT TOÁÁNN

• Câu lệnh lặp– Số lần lặp biết trước for i := m to n do ….

for i := n down to m do….

– Số lần lặp không biết trước while B do S;

repeat S until B;

(B: biểu thức logic; S: dãy lệnh)

• Câu lệnh chuyểngo to n; (n:số hiệu của một bước trong chương trình)

• Câu lệnh vào raread(<danh sách biến>);

write(<danh sách biểu thức>)

13

NGÔN NGNGÔN NGỮỮ THUTHUẬẬT TOT TOÁÁNN

• Chương trình con

– Hàm

function <tên hàm>(<danh sách tham số>): <kiểu dữ liệu>

S

return <biểu thức>

– Thủ tục Procedure: không có kết quả ra

– Sử dụng Var đặt trước tham số cần giữ lại sự thay đổi giá trị saukhi kết thúc thực hiện hàm/thủ tục

– Lời gọi Hàm Tên_hàm(<danh sách tham số thực sự>)

– Lời gọi thủ tục Call <Tên thủ tục>(<danh sách tham số thực sự>)

14

Ngôn ngữ Tựa C

15

ĐĐỘỘ PHPHỨỨC TC TẠẠP THUP THUẬẬT TOT TOÁÁNN

Giải thuật nào hiệu quả nhất cho một bài toán?• Độ phức tạp thời gian

• Độ phức tạp không gian

? Đánh giá giải thuật khi chạy chương trình ???

Các yếu tố ảnh hưởng đến thời gian thực hiện thuật toán• Môi trường phần cứng: tốc độ xử lý, bộ nhớ,…

• Môi trường phần mềm: kiểu lệnh, ngôn ngữ, trình biên dịch

• Kích thước dữ liệu vào

Đánh giá độ phức tạp thời gian T(n) bằng tổng số phéptính cần phải thực hiện.

16

Độ tăng của hàm• Cho hai hàm f(x), g(x) xác định từ tập các số nguyên dương hoặc tập

số thực vào tập số thực. Ta nói f(x) là O(g(x)) nếu tồn tại hai hằng sốC và k sao cho: |f(x)| ≤ C.|g(x)|, với mọi x > k.

Ví dụ 1• f(x) = an xn +…. +a0, với ai là các số thực. Khi đó f(x) = O(xn).

• với x > 1 ta có

• Đặt C = |an| + |an−1| + … + |a0| và k = 1, suy ra f(x) = O(xn).

Ví dụ 2. • f(x) = 1+ 2+ 3 + … + n = n(n+1)/2 nên là O(n2).

ĐĐỘỘ PHPHỨỨC TC TẠẠP THUP THUẬẬT TOT TOÁÁNN

)....(

...(

...)(

01

01

01

1

aaaxxa

xa

ax

axaxaxf

nnn

nn

nn

nn

nn

+++≤

+++≤

+++≤

−−

17

ĐĐỘỘ PHPHỨỨC TC TẠẠP THUP THUẬẬT TOT TOÁÁNN

Các thuật ngữ thường dùng• Độ phức tạp O(1) gọi là độ phức tạp hằng số

• Độ phức tạp O(log(n)) gọi là độ phức tạp logarit

• Độ phức tạp O(n) gọi là độ phức tạp tuyến tính

• Độ phức tạp O(nlogn) gọi là độ phức tạp nlogn

• Độ phức tạp O(nk) gọi là độ phức tạp đa thức

• Độ phức tạp O(bn) , b>1, gọi là độ phức tạp hàm mũ

• Độ phức tạp O(n!) gọi là độ phức tạp giai thừa

18

ĐĐỘỘ PHPHỨỨC TC TẠẠP THUP THUẬẬT TOT TOÁÁNN

Ví dụ 1K:=0;

For i:=1 to n do

Begin

K:=K+i;

End;

Ví dụ 2K:=0;

For i:=1 to n do

For j:= 1 to n do

Begin

K := K + i * j ;

End;

19

ĐĐỘỘ PHPHỨỨC TC TẠẠP THUP THUẬẬT TOT TOÁÁNN

Ví dụ 3i :=1; K:=0;

while i <= n do

begin

K:= K+ i*i;

i := i * 2;

end;

Số phép toán cần thực hiện: (1 so sánh + 2 nhân + 1 cộng) * (1 + |log2n|) = 4 + 4 |log2n| là

O(log2n).

20

Ví dụ 4Searching(A[]: array of integer, n: integer, integer K): Boolean

Begin

i := 1; found := false;

while (i <=n and !found) do

begin

if A[i] = K then found:=true;

else i := i+1;

end;

return found;

end;

ĐĐỘỘ PHPHỨỨC TC TẠẠP THUP THUẬẬT TOT TOÁÁNN

21

ĐĐỘỘ PHPHỨỨC TC TẠẠP THUP THUẬẬT TOT TOÁÁNN

Độ phức tạp xấu nhất

Độ phức tạp trường hợp tốt nhất

Độ phức tạp trung bình

22

ĐĐỘỘ PHPHỨỨC TC TẠẠP THUP THUẬẬT TOT TOÁÁNN

Độ phức tạp trường hợp xấu nhất của A là số lớn nhấtcác phép toán cơ bản được thực hiện trong A trên bấtkỳ dữ liệu vào có kích cỡ xác định.

Độ phức tạp trường hợp tốt nhất của A là số bé nhấtcác phép toán cơ bản được thực hiện trong A trên bấtkỳ dữ liệu vào có kích cỡ xác định.

Độ phức tạp trung bình của A là giá trị trung bình củasố các phép toán cơ bản được thực hiện trong A trênbất kỳ dữ liệu vào có kích thước xác định.

23

ĐĐỘỘ PHPHỨỨC TC TẠẠP THUP THUẬẬT TOT TOÁÁNN

Ví dụ hàm Searching ở trên:• Độ phức tạp trong trường hợp xấu nhất là O(n)

• Độ phức tạp trong trường hợp tốt nhất là:O(1) khi K chính làphần tử đầu tiên của mảng.

• Độ phức tạp trung bình là: cỡ n/2 (khoảng ½ các phần tử củamảng được duyệt). Việc tính toán rất phức tạp dựa vào xácsuất K xuất hiện trong A.

Thường đánh giá thuật toán theo độ phức tạp thời gianxấu nhất. Hiệu quả sử dụng của thuật toán lại thể hiệnthông qua độ phức tạp trung bình.

24

Kiểu dữ liệu: • Trong ngôn ngữ bậc cao

• Là sự trừu tượng hóa các thuộc tính bản chất của các đốitượng trong thực tế và phù hợp với cách tổ chức thông tin trênmáy tính

• Kiểu số nguyên, số thực, kí tự,…

• Kiểu dữ liệu T = <V, O>, V là tập các giá trị hợp lệ của T và O là tập các phép toán trên kiểu T.

KIKIỂỂU DU DỮỮ LILIỆỆU VU VÀÀ CCẤẤU TRU TRÚÚC DC DỮỮ LILIỆỆUU

25

KIKIỂỂU DU DỮỮ LILIỆỆU VU VÀÀ CCẤẤU TRU TRÚÚC DC DỮỮ LILIỆỆUU

Cấu trúc dữ liệu: • Là các lưu trữ dữ liệu trên máy tính sao cho việc sử dụng

dữ liệu đó được hiệu quả. Đó chính là tổ chức các khái niệm toán học và logic về dữ liệu.

• Kiểu dữ liệu có cấu trúc được kết hợp nên từ các kiểu dữ liệucơ sở

• Ví dụ: Kiểu mảng, xâu kí tự, Bản ghi, File,…

Mối liên hệ giữa cấu trúc dữ liệu và Thuật toán

Chương trình = Cấu trúc dữ liệu + Thuật toán

26

KIKIỂỂU DU DỮỮ LILIỆỆU VU VÀÀ CCẤẤU TRU TRÚÚC DC DỮỮ LILIỆỆUU

Mô hình dữ liệu• Là mô hình toán học, có thể biểu diễn được trên máy tính, để

biểu diễn các đối tượng của bài toán và mối liên hệ giữa cácđối tượng

• Mô hình dữ liệu muốn cài đặt được trên máy tính phải có cáchtổ chức dữ liệu phù hợp.

• Ví dụ: Danh sách, Cây, Đồ thị, Quan hệ,. …

Các tiêu chuẩn chọn cấu trúc dữ liệu• Phản ánh đúng thực tế: quan trọng nhất, đảm bảo tính đúngđắn của phương án giải quyết

• Các thao tác phù hợp

• Tiết kiệm tài nguyên hệ thống27

KIKIỂỂU DU DỮỮ LILIỆỆU TRONG CU TRONG C

Kiểu dữ liệu cơ sở

• Kí tự (char, unsigned char)

• Số nguyên (int, unsigned int, long (int), unsigned long (int))

• Số thực, độ chính xác đơn (float)

• Số thực, độ chính xác kép (double)

– Lưu ý: Kích thước và phạm vi biểu diễn của các kiểu dữ liệu

Kiểu con trỏ

Kiểu enum

Kiểu mảng (array)

Kiểu cấu trúc (struct)

Kiểm tra kích thước của kiểu dữ liệu: dùng toán tử sizeof(), vídụ: sizeof(int),…

28

KIKIỂỂU CON TRU CON TRỎỎ

Biến con trỏ (Pointer)• Địa chỉ bộ nhớ của biến được gán cho con trỏ là giá trị của

biến con trỏ.

• Biến thông thường chứa một giá trị cụ thể (count = 7).

• Các con trỏ chứa địa chỉ của biến: biến được trỏ chứa giá trị cụthể (tham chiếu gián tiếp)

Con trỏ countPtr trỏ đến biến count, giá trịcủa biến con trỏ countPtr là địa chỉ củabiến count, giá trị của biến count là 7.

count

7

count

7countPtr

29

BiBiếếnn con con trtrỏỏ trongtrong ngônngôn ngngữữ CC

Con trỏ - Pointer

• Sức mạnh của ngôn ngữ lập trình C

• Tạo ra khả năng mềm dẻo khi lập trình

• Thuận lợi truyền tham số cho hàm (tham biến), xử lýmảng, xâu, bộ nhớ

• Con trỏ có quan hệ mật thiết giữa arrays và strings

• Lưu ý, thận trọng trong cách sử dụng: can thiệp vàobộ nhớ.

30

Định nghĩa và khởi tạo biến con trỏ• * được sử dụng định nghĩa biến pointer

int *myPtr;

• Định nghĩa biến con trỏ, trỏ tới vùng nhớ kiểu int

• Định nghĩa nhiều con trỏ yêu cầu sử dụng * trước mỗi biến con trỏ

int *myPtr1, *myPtr2;

• Có thể định nghĩa con trỏ kiểu dữ liệu bất kỳ

• Khởi tạo con trỏ là 0, NULL (con trỏ rỗng) hoặc một địa chỉ củamột biến cùng kiểu dữ liệu

BiBiếến con trn con trỏỏ trong ngôn ngtrong ngôn ngữữ CC

31

&Tenbien (trả về địa chỉ của tenbien)• Phép gán trả về địa chỉ của biến dữ liệu

int y = 5;

int *yPtr;

yPtr = &y; /* yPtr lấy địa chỉcủa y */

yPtr “trỏ tới” y

yPtr

y

5yptr

500000 600000

y

600000 5

địa chỉ của y

là giá trị củayptr

BiBiếếnn con con trtrỏỏ trongtrong ngônngôn ngngữữ CC

32

Sử dụng dấu * để tham chiếu giá trị trong vùng nhớ trỏ bởicon trỏ

• *yptr trả về giá trị của biến y (bởi vì yptr trỏ tới y)

• Dấu * có thể sử dụng trong lệnh gán làm thay đổi giá trịcủa biến dữ liệu.

*yptr = 7; /* thay đổi y bằng 7 */

* và & quan hệ đối ngược nhau- *p là dữ liệu được chứa trong vùng nhớ có địa chỉ là p

- &x là địa chỉ của biến x

int x; int *xptr; xptr = &x;

Khi đó, *xptr = x; &*xptr = *&xptr

BiBiếếnn con con trtrỏỏ trongtrong ngônngôn ngngữữ CC1 /* Fig. 7.4: fig07_04.c 2 Using the & and * operators */ 3 #include <stdio.h> 4 5 int main() 6 { 7 int a; /* a is an integer */ 8 int *aPtr; /* aPtr is a pointer to an integer */ 9 10 a = 7; 11 aPtr = &a; /* aPtr set to address of a */ 12 13 printf( "The address of a is %p" 14 "\nThe value of aPtr is %p", &a, aPtr ); 15 16 printf( "\n\nThe value of a is %d" 17 "\nThe value of *aPtr is %d", a, *aPtr ); 18 19 printf( "\n\nShowing that * and & are complements of " 20 "each other\n&*aPtr = %p" 21 "\n*&aPtr = %p\n", &*aPtr, *&aPtr ); 22 23 return 0; /* indicates successful termination */ 24 25 } /* end main */

Địa chỉ của biến a là giá trị củacon trỏ aPtr

* aPtr là giá trịcủa biến

Quan hệ giữa *

và & là bổ sung

The address of a is 0012FF7CThe value of aPtr is 0012FF7CThe value of a is 7The value of *aPtr is 7Showing that * and & are complements of each other.&*aPtr = 0012FF7C*&aPtr = 0012FF7C

34

BiBiếến con trn con trỏỏ trong ngôn ngtrong ngôn ngữữ CC

Con trỏ hằng (const pointers)• Trỏ tới vùng nhớ cố định

• Phải được khởi tạo khi định nghĩa

• int *const myPtr = &x;

– Kiểu int *const – con trỏ hằng trỏ đến vùng nhớ kiểu int

• const int *myPtr = &x;

– Con trỏ thông thường trỏ đến const int

• const int *const Ptr = &x;

– con trỏ const trỏ đến một vùng nhớ const int

– x có thể thay đổi, nhưng *Ptr thì không.

1 /* Fig. 7.13: fig07_13.c 2 Attempting to modify a constant pointer to non-constant data */ 3 #include <stdio.h> 4 5 int main() 6 { 7 int x; /* define x */ 8 int y; /* define y */ 9 10 /* ptr is a constant pointer to an integer that can be modified 11 through ptr, but ptr always points to the same memory location */ 12 int * const ptr = &x; 13 14 *ptr = 7; /* allowed: *ptr is not const */ 15 ptr = &y; /* error: ptr is const; cannot assign new address */ 16 17 return 0; /* indicates successful termination */ 18 19 } /* end main */

Compiling...FIG07_13.cD:\books\2003\chtp4\Examples\ch07\FIG07_13.c(15) : error C2166: l-value

specifies­ const objectError executing cl.exe.

FIG07_13.exe - 1 error(s), 0 warning(s)

Thay đổi *ptr được phép – x

không phải là hằng.

Thay đổi ptr là lỗi – ptr làcon trỏ hằng.

Con trCon trỏỏ hhằằngng

1 /* Fig. 7.14: fig07_14.c 2 Attempting to modify a constant pointer to constant data. */ 3 #include <stdio.h> 4 5 int main() 6 { 7 int x = 5; /* initialize x */ 8 int y; /* define y */ 9 10 /* ptr is a constant pointer to a constant integer. ptr always 11 points to the same location; the integer at that location 12 cannot be modified */ 13 const int *const ptr = &x; 14 15 printf( "%d\n", *ptr ); 16 17 *ptr = 7; /* error: *ptr is const; cannot assign new value */ 18 ptr = &y; /* error: ptr is const; cannot assign new address */ 19 20 return 0; /* indicates successful termination */ 21 22 } /* end main */

Ví dụ: những tình huống sử dụng con trỏ hằng, được phép và không được phép

Compiling...FIG07_14.cD:\books\2003\chtp4\Examples\ch07\FIG07_14.c(17) : error C2166: l-value

specifies­ const objectD:\books\2003\chtp4\Examples\ch07\FIG07_14.c(18) : error C2166: l-value

specifies­ const objectError executing cl.exe.

FIG07_12.exe - 2 error(s), 0 warning(s)

38

SSỬỬ DDỤỤNG KING KIỂỂU MU MẢẢNG TRONG CNG TRONG C

Các mảng

• Là cấu trúc gồm các phần tử dữ liệu có liên quanvới nhau

• Các thực thể tĩnh (Static) – kích thước không thayđổi trong suốt chương trình

(Phân biệt với: Cấu trúc dữ liệu động (Dynamic)

39

Khái niệm mảng• Nhóm của định vị bộ nhớ liên tiếp nhau

• Cùng chung tên và kiểu dữ liệu

Tham chiếu đến phần tử, cụ thể• Tên mảng

• Số vị trí

Định dạng:arrayname[ position number ]

• phần tử đầu tiên có vị trí 0

• n phần tử mảng với tên c:

– c[ 0 ], c[ 1 ]...c[ n – 1 ]

Tên của mảng (tấtcả các phần tử có

chung tên c)

Số vị trí củaphần tử trong

mảng c

c[6]

-45

6

0

72

1543

-89

0

62

-3

1

6453

78

c[0]

c[1]

c[2]

c[3]

c[11]

c[10]

c[9]

c[8]

c[7]

c[5]

c[4]

40

Các phần tử trong mảng giống như các biến

c[ 0 ] = 3;

printf( "%d", c[ 0 ] );

• Thực hiện thao tác trong ngoặc [] để xác định chỉ số.

+ Nếu x = 3 thì c[ 5 - 2 ] == c[ 3 ] == c[ x ]

+ Chỉ số của mảng có thể xác định bằng biểu thứctoán học

41

KhaiKhai bbááoo mmảảngng

Khi khai báo mảng• Tên mảng

• Kiểu mảng

• Số phần tử

Cú pháp: arrayType arrayName[ numberOfElements ];

• Ví dụ:int c[ 10 ];

float myArray[ 3284 ];

Khai báo nhiều mảng có cùng kiểu• Cú pháp tương tự như khai báo biến

• Ví dụ:

int b[ 100 ], x[ 27 ];

42

KhaiKhai bbááoo vvàà khkhởởii ttạạoo mmảảngng

Khởi tạo mảng: khai báo và gắn giá trị các phần tử

int n[ 5 ] = { 1, 2, 3, 4, 5 };

• Nếu không đủ các biến thì các phần tử bên phải nhất bằng 0

int n[ 5 ] = { 0 } // Tất cả các phần tử bằng 0

• Nếu quá nhiều phần tử thì báo lỗi cú pháp

• C không kiểm tra giới hạn của mảng

• Nếu bỏ qua kích thước, sử dụng mặc định số phần tử khởi tạo

int n[ ] = { 1, 2, 3, 4, 5 };

. Khởi tạo 5 phần tử, do đó mảng có 5 phần tử

1 /* Fig. 6.4: fig06_04.c 2 Initializing an array with an initializer list */ 3 #include <stdio.h> 4 5 /* function main begins program execution */ 6 int main() 7 { 8 /* use initializer list to initialize array n */ 9 int n[ 10 ] = { 32, 27, 64, 18, 95, 14, 90, 70, 60, 37 }; 10 int i; /* counter */ 11 12 printf( "%s%13s\n", "Element", "Value" ); 13 14 /* output contents of array in tabular format */ 15 for ( i = 0; i < 10; i++ ) { 16 printf( "%7d%13d\n", i, n[ i ] ); 17 } /* end for */ 18 19 return 0; /* indicates successful termination */ 20 21 } /* end main */

Element Value

0 32

1 27

2 64

3 18

4 95

5 14

6 90

7 70

8 60

9 37

Program OutputProgram Output

VVíí ddụụ: : KhaiKhai bbááoo vvàà khkhởởii ttạạoo mmảảngng

array = 0012FF78&array[0] = 0012FF78

&array = 0012FF78

1 /* Fig. 6.12: fig06_12.c 2 The name of an array is the same as &array[ 0 ] */ 3 #include <stdio.h> 4 5 /* function main begins program execution */ 6 int main() 7 { 8 char array[ 5 ]; /* define an array of size 5 */ 9 10 printf( " array = %p\n&array[0] = %p\n" 11 " &array = %p\n", 12 array, &array[ 0 ], &array ); 13 14 return 0; /* indicates successful termination */ 15 16 } /* end main */

Ví dụ: Tên của array chính là &array[ 0 ] (địa chỉ của phần tử đầu tiên trong mảng)

MMốốii liênliên hhệệ gigiữữaa mmảảngng vvàà con con trtrỏỏ trongtrong CC

45

MMảảngng nhinhiềềuu chichiềềuu

Mảng nhiều chiều• Bảng với các hàng và các cột (m hàng và n cột)

• Giống như ma trận: chỉ số đầu là hàng (row), sau đó là cột(column)

Row 0Row 1Row 2

Column 0 Column 1 Column 2 Column 3

a[ 0 ][ 0 ]

a[ 1 ][ 0 ]

a[ 2 ][ 0 ]

a[ 0 ][ 1 ]

a[ 1 ][ 1 ]

a[ 2 ][ 1 ]

a[ 0 ][ 2 ]

a[ 1 ][ 2 ]

a[ 2 ][ 2 ]

a[ 0 ][ 3 ]

a[ 1 ][ 3 ]

a[ 2 ][ 3 ]

Chỉ sô hàng-Row

Tên mảngChỉ số cột-Column

46

MMảảngng nhinhiềềuu chichiềềuu

Khởi tạo• int b[ 2 ][ 2 ] = { { 1, 2 }, { 3, 4 } };

• Khởi tạo theo hàng trong dấu {}

• Nếu không đủ, các phần tử còn lại nhận giá trị 0

int b[ 2 ][ 2 ] = { { 1 }, { 3, 4 } };

Tham chiếu các phần tử• Chỉ ra hàng và cột

printf( "%d", b[ 0 ][ 1 ] );

• Nhập giá trị cho phần tử (i,j) của mảng

scanf(“%d”, &b[i][j]);

1 2

3 4

1 0

3 4

1 /* Fig. 6.21: fig06_21.c 2 Initializing multidimensional arrays */ 3 #include <stdio.h> 4 5 void printArray( const int a[][ 3 ] ); /* function prototype */ 6 7 /* function main begins program execution */ 8 int main() 9 { 10 /* initialize array1, array2, array3 */ 11 int array1[ 2 ][ 3 ] = { { 1, 2, 3 }, { 4, 5, 6 } }; 12 int array2[ 2 ][ 3 ] = { 1, 2, 3, 4, 5 }; 13 int array3[ 2 ][ 3 ] = { { 1, 2 }, { 4 } }; 14 15 printf( "Values in array1 by row are:\n" ); 16 printArray( array1 ); 17 18 printf( "Values in array2 by row are:\n" ); 19 printArray( array2 ); 20 21 printf( "Values in array3 by row are:\n" ); 22 printArray( array3 ); 23 24 return 0; /* indicates successful termination */ 25 26 } /* end main */ 27

Ví dụ: Khởi tạo mảng đa chiều

Program OutputProgram Output

Values in array1 by row are:1 2 34 5 6Values in array2 by row are:1 2 34 5 0Values in array3 by row are:1 2 04 0 0

28 /* function to output array with two rows and three columns */ 29 void printArray( const int a[][ 3 ] ) 30 { 31 int i; /* counter */ 32 int j; /* counter */ 33 34 /* loop through rows */ 35 for ( i = 0; i <= 1; i++ ) { 36 37 /* output column values */ 38 for ( j = 0; j <= 2; j++ ) { 39 printf( "%d ", a[ i ][ j ] ); 40 } /* end inner for */ 41 42 printf( "\n" ); /* start new line of output */ 43 } /* end outer for */ 44 45 } /* end function printArray */

49

XâuXâu kkíí ttựự trong Ctrong C

Mảng ký tự• Xâu “first” là một mảng các ký tự

• Mảng các ký tự có thể được khởi tạo bởi một xâu

char string1[ ] = "first"– Kết thúc của xâu ký tự '\0' (Null)

– string1 thực tế có 6 phần tử

– Có thể viết tương ứng như sau:

char string1[ ] = { 'f', 'i', 'r', 's', 't', '\0' };

• Có thể truy cập đến từng ký tự : string1[ 3 ] là ký tự ‘s’• Tên mảng thể hiện địa chỉ của mảng, vì vậy không cần sử dụng ký

tự “&” trong lệnh scanf

scanf( "%s", string2 );

– Đọc các ký tự đến khi gặp ký tự trắng / dấu cách

1 /* Fig. 6.10: fig06_10.c 2 Treating character arrays as strings */ 3 #include <stdio.h> 4 5 /* function main begins program execution */ 6 int main() 7 { 8 char string1[ 20 ]; /* reserves 20 characters */ 9 char string2[] = "string literal"; /* reserves 15 characters */ 10 int i; /* counter */ 11 12 /* read string from user into array string2 */ 13 printf("Enter a string: "); 14 scanf( "%s", string1 ); 15 16 /* output strings */ 17 printf( "string1 is: %s\nstring2 is: %s\n" 18 "string1 with spaces between characters is:\n", 19 string1, string2 ); 20 21 /* output characters until null character is reached */ 22 for ( i = 0; string1[ i ] != '\0'; i++ ) { 23 printf( "%c ", string1[ i ] ); 24 } /* end for */ 25 51

Xâu kXâu kíí ttựự trong Ctrong C

Khai báo String

• Giống như khai báo một mảng ký tự hoặc một biến kiểu char *char color[] = "blue";

char *colorPtr = "blue";

Đọc vào xâu

• Sử dụng scanf()scanf("%s", word);

– Sao chép vào word[]

– Không cần & (vì tên xâu là con trỏ)

• Sử dụng gets( )

Xác định độ dài xâu:

size_t strlen( const char *s ): Trả về số ký tự trong xâu s

52

KKíí ttựự vvàà xâu kxâu kíí ttựự trong Ctrong C

Thư viện các hàm về kí tự và xâu kí tự• Thư viện xử lý ký tự: <ctype.h>

• Sử dụng các hàm vào/ra ký tự và xâu (thư viện stdio.h).

• Sử dụng các hàm chuyển đổi xâu (thư viện stdlib.h).

• Sử dụng các hàm xử lý string (thư viện string.h).

53

Thư viThư việện chun chuẩẩn cn cáác hc hààm xm xửử lý ký tlý ký tựự

Prototype Description int isdigit( int c ); Returns true if c is a digit and false otherwise. int isalpha( int c ); Returns true if c is a letter and false otherwise. int isalnum( int c ); Returns true if c is a digit or a letter and false otherwise. int isxdigit( int c ); Returns true if c is a hexadecimal digit character and false otherwise. int islower( int c ); Returns true if c is a lowercase letter and false otherwise. int isupper( int c ); Returns true if c is an uppercase letter; false otherwise. int tolower( int c ); If c is an uppercase letter, tolower returns c as a lowercase letter. Otherwise, tolower

returns the argument unchanged. int toupper( int c ); If c is a lowercase letter, toupper returns c as an uppercase letter. Otherwise, toupper

returns the argument unchanged. int isspace( int c ); Returns true if c is a white-space character—newline ('\n'), space (' '), form feed

('\f'), carriage return ('\r'), horizontal tab ('\t'), or vertical tab ('\v')—and false otherwise

int iscntrl( int c ); Returns true if c is a control character and false otherwise. int ispunct( int c ); Returns true if c is a printing character other than a space, a digit, or a letter and false

otherwise. int isprint( int c ); Returns true value if c is a printing character including space (' ') and false otherwise.

int isgraph( int c ); Returns true if c is a printing character other than space (' ') and false otherwise.

54

Các hàm chuyển đổi• Trong <stdlib.h> (thư viện chuẩn)

Chuyển đổi string của các số thành các số nguyên (int) và số thực (float)

Function prototype Function description double atof( const char *nPtr ); Converts the string nPtr to double.

int atoi( const char *nPtr ); Converts the string nPtr to int. long atol( const char *nPtr ); Converts the string nPtr to long int. double strtod( const char *nPtr, char **endPtr );

Converts the string nPtr to double. long strtol( const char *nPtr, char **endPtr, int base );

Converts the string nPtr to long. unsigned long strtoul( const char *nPtr, char **endPtr, int base );

Converts the string nPtr to unsigned long.

55

Các hàm thư viện I/O chuẩn <stdio.h>

Function prototype Function description int getchar( void ); Inputs the next character from the standard input and re-

turns it as an integer. char *gets( char *s ); Inputs characters from the standard input into the array s

until a newline or end-of-file character is encountered. A terminating null character is appended to the array.

int putchar( int c ); Prints the character stored in c. int puts( const char *s ); Prints the string s followed by a newline character. int sprintf( char *s, const char *format, ... );

Equivalent to printf, except the output is stored in the array s instead of printing it on the screen.

int sscanf( char *s, const char *format, ... );

Equivalent to scanf, except the input is read from the array s instead of reading it from the keyboard.

56

Thư viện điều khiển string có các hàm:• Thao tác dữ liệu string

• Tìm kiếm trên string

• Xác định độ dài string

Function prototype Function description char *strcpy( char *s1, const char *s2 )

Copies string s2 into array s1. The value of s1 is returned. char *strncpy( char *s1, const char *s2, size_t n )

Copies at most n characters of string s2 into array s1. The value of s1 is returned.

char *strcat( char *s1, const char *s2 )

Appends string s2 to array s1. The first character of s2 overwrites the terminating null character of s1. The value of s1 is returned.

char *strncat( char *s1, const char *s2, size_t n )

Appends at most n characters of string s2 to array s1. The first character of s2 overwrites the terminating null character of s1. The value of s1 is returned.

57

So sánh các string• Máy tính so sánh mã số ASCII của ký tự trong xâu

• Xem bảng mã các ký tự (sách lập trình C)

int strcmp( const char *s1, const char *s2 );

• So sánh xâu s1 với s2

• Kết quả trả về của hàm là số âm nếu s1 < s2, 0 nếu s1 == s2hoặc số dương nếu s1 > s2

int strncmp(const char *s1, const char *s2, size_t n );

• So sánh n ký tự của xâu s1 với s2

• Giá trị kết quả trả về giống hàm strcmp()

58

Các hàm tìm kiếm String từ thư viện chuẩn

Function prototype Function description

char *strchr( const char *s, int c );

Locates the first occurrence of character c in string s. If c is found, a pointer to c in s is returned. Otherwise, a NULL pointer is returned.

size_t strcspn( const char *s1, const char *s2 );

Determines and returns the length of the initial segment of string s1 consisting of characters not contained in string s2.

size_t strspn( const char *s1, const char *s2 );

Determines and returns the length of the initial segment of string s1 consisting only of characters contained in string s2.

char *strpbrk( const char *s1, const char *s2 );

Locates the first occurrence in string s1 of any character in string s2. If a character from string s2 is found, a pointer to the character in string s1 is returned. Otherwise, a NULL pointer is returned.

char *strrchr( const char *s, int c );

Locates the last occurrence of c in string s. If c is found, a pointer to c in string s is returned. Otherwise, a NULL pointer is returned.

char *strstr( const char *s1, const char *s2 );

Locates the first occurrence in string s1 of string s2. If the string is found, a pointer to the string in s1 is returned. Otherwise, a NULL pointer is returned.

char *strtok( char *s1, const char *s2 );

A sequence of calls to strtok breaks string s1 into “tokens”—logical pieces such as words in a line of text—separated by characters contained in string s2. The first call contains s1 as the first argument, and subsequent calls to continue tokenizing the same string contain NULL as the first argument. A pointer to the current token is returned by each call. If there are no more tokens when the function is called, NULL is returned.

59

Hàm Memory• Trong <stdlib.h>

• Thao tác, so sánh, tìm kiếm khối của memory

• Có thể thao tác bất kỳ khối dữ liệu nàoFunction prototype Function description void *memcpy( void *s1, const void *s2, size_t n );

Copies n characters from the object pointed to by s2 into the object pointed to by s1. A pointer to the resulting object is returned.

void *memmove( void *s1, const void *s2, size_t n );

Copies n characters from the object pointed to by s2 into the object pointed to by s1. The copy is performed as if the characters were first copied from the object pointed to by s2 into a temporary array and then from the temporary array into the object pointed to by s1. A pointer to the resulting object is returned.

int memcmp( const void *s1, const void *s2, size_t n );

Compares the first n characters of the objects pointed to by s1 and s2. The function returns 0, less than 0 or greater than 0 if s1 is equal to, less than or greater than s2.

void *memchr( const void *s, int c, size_t n );

Locates the first occurrence of c (converted to unsigned char) in the first n characters of the object pointed to by s. If c is found, a pointer to c in the object is returned. Otherwise, NULL is returned.

void *memset( void *s, int c, size_t n );

Copies c (converted to unsigned char) into the first n characters of the object pointed to by s. A pointer to the result is returned.

60

MMảảng , Con trng , Con trỏỏ vvàà Xâu kXâu kíí ttựự

Các phần tử của array có thể là con trỏ

Ví dụ: array của các xâu (strings)char *suit[ 4 ] = { "Hearts", "Diamonds", "Clubs", "Spades" };

• Strings là các con trỏ tới ký tự đầu tiên

• char * : mỗi phần tử của suit là một con trỏ char

• Các string được lưu trữ là mảng suit

• Mảng suit có kích thước cố định, nhưng con trỏ string có thể là kích thước bất kỳ

suit[3]

suit[2]

suit[1]

suit[0] ’H’ ’e’ ’a’ ’r’ ’t’ ’s’ ’\0’

’D’ ’i’ ’a’ ’m’ ’o’ ’n’ ’d’ ’s’ ’\0’

’C’ ’l’ ’u’ ’b’ ’s’ ’\0’

’S’ ’p’ ’a’ ’d’ ’e’ ’s’ ’\0’

61

Ví dụ 716: Viết chương trình tính kích thước của array float gồm 20 phần tử và kích thước của con trỏ đến array

sizeof

• Trả về kích thước là số byte của biến

• Nếu sizeof( int ) bằng 4 bytes, thì

– int myArray[ 10 ];

– printf( "%d", sizeof( myArray ) );

– sẽ in ra là 40

sizeof Có thể sử dụng với tham số là:

• Tên biến

• Tên kiểu

• Giá trị hằng số

HHààmm ttíínhnh kkííchch thưthướớcc ccủủaa bibiếếnn vvàà con con trtrỏỏ

1 /* Fig. 7.16: fig07_16.c 2 Sizeof operator when used on an array name 3 returns the number of bytes in the array. */ 4 #include <stdio.h> 5 6 size_t getSize( float *ptr ); /* prototype */ 7 8 int main() 9 { 10 float array[ 20 ]; /* create array */ 11 12 printf( "The number of bytes in the array is %d" 13 "\nThe number of bytes returned by getSize is %d\n", 14 sizeof( array ), getSize( array ) ); 15 16 return 0; /* indicates successful termination */ 17 18 } /* end main */ 19 20 /* return size of ptr */ 21 size_t getSize( float *ptr ) 22 { 23 return sizeof( ptr ); 24 25 } /* end function getSize */

The number of bytes in the array is 80The number of bytes returned by getSize is 4

1 /* Fig. 7.17: fig07_17.c 2 Demonstrating the sizeof operator */ 3 #include <stdio.h> 4 5 int main() 6 { 7 char c; /* define c */ 8 short s; /* define s */ 9 int i; /* define i */ 10 long l; /* define l */ 11 float f; /* define f */ 12 double d; /* define d */ 13 long double ld; /* define ld */ 14 int array[ 20 ]; /* initialize array */ 15 int *ptr = array; /* create pointer to array */ 16 17 printf( " sizeof c = %d\tsizeof(char) = %d" 18 "\n sizeof s = %d\tsizeof(short) = %d" 19 "\n sizeof i = %d\tsizeof(int) = %d" 20 "\n sizeof l = %d\tsizeof(long) = %d" 21 "\n sizeof f = %d\tsizeof(float) = %d" 22 "\n sizeof d = %d\tsizeof(double) = %d" 23 "\n sizeof ld = %d\tsizeof(long double) = %d" 24 "\n sizeof array = %d" 25 "\n sizeof ptr = %d\n",

26 sizeof c, sizeof( char ), sizeof s, 27 sizeof( short ), sizeof i, sizeof( int ), 28 sizeof l, sizeof( long ), sizeof f, 29 sizeof( float ), sizeof d, sizeof( double ), 30 sizeof ld, sizeof( long double ), 31 sizeof array, sizeof ptr ); 32 33 return 0; /* indicates successful termination */ 34 35 } /* end main */

sizeof c = 1 sizeof(char) = 1sizeof s = 2 sizeof(short) = 2sizeof i = 4 sizeof(int) = 4sizeof l = 4 sizeof(long) = 4sizeof f = 4 sizeof(float) = 4sizeof d = 8 sizeof(double) = 8

sizeof ld = 8 sizeof(long double) = 8sizeof array = 80

sizeof ptr = 4

65

Con trCon trỏỏ vvàà mmảảngng

Cấp phát động cho mảng (<alloc.h>)• Hàm cấp phát vùng bộ nhớ gồm n byte:

void *malloc(unsigned n)

• Giải phóng vùng nhớ

void free(void *ptr)

Ví dụ:

int *IntArray;

printf(“Size of array:”); scanf(“%d”, &n);

IntArray = (int*) malloc(n*sizeof(int));

66

KiKiểểuu bbảảnn ghighi

Dữ liệu kiểu bản ghi:• Tập hợp các biến có liên quan sử dụng chung 1 tên

– Tên biến “chung” có thể chứa các biến với các kiểu dữ liệukhác nhau

• Nhiều trường dữ liệu

• Kết hợp với con trỏ để tạo các danh sách liên kết, ngăn xếp, hàng đợi và cây

67

KiKiểểuu bbảảnn ghighi trongtrong CC

Ví dụ:

struct Student {

char name[40];

int grade;

};• struct mô tả định nghĩa cấu trúc Student

• Student là tên cấu trúc và được sử dụng để khai báo biến dữliệu có kiểu là cấu trúc

• chứa 2 trường dữ liệu

68

Cách định nghĩa:• Khai báo biến:

struct Student oneStudent, Class[ 50 ], *sPtr;• Kết hợp định nghĩa và khai báo biến:

struct Student {

char name[40];

int grade;

} oneStudent, Class[ 50 ], *sPtr;

69

Các thao tác hợp lệ trên cấu trúc• Gán một cấu trúc cho một cấu trúc cùng kiểu

• Lấy địa chỉ (&) của một cấu trúc

• Truy cập các thành phần của 1 cấu trúc

• Sử dụng hàm sizeof để xác định kích thước của cấu trúc

70

Khởi tạo cấu trúc sử dụng danh sách• Ví dụ:

struct Student oneStudent = { “Hoang Lan", 8 };

Các lệnh gán• Ví dụ:

struct Student myFriend = oneStudent;

• Có thể định nghĩa và khởi tạo biến myFriend như sau:

struct Student myFriend;

myFriend.name = “Hoang Lan”;

myFriend.grade = 8;

71

Truy cập các thành phần của cấu trúc

• Sử dụng dấu (.) đi kèm với tên biến cấu trúc

struct Student myFriend;

printf( "%s", myFriend.name );

• Mũi tên (->) được sử dụng cho con trỏ trỏ đếnbiến cấu trúc

struct Student *sPtr = &myFriend;

printf( "%s",sPtr->name );

• myFriend.name tương đương với

( *sPtr ).name

72

typedef : Định nghĩa kiểu

• Tạo ra tên khác (bí danh) cho một kiểu dữ liệu đã địnhnghĩa

• typedef không tạo ra kiểu dữ liệu mới

• Ví dụ:

typedef struct Student * StudentPtr;

StudentPtr sPtr;

> Định nghĩa tên kiểu mới StudentPtr có cùng kiểu với kiểu

struct Student *

• Ví dụ: typedef char line[80];

line str; // tương ứng char str[80];73

Đọc thêm: Kiểu union, kiểu enum trong ngôn ngữ lậptrình C

74

BBààii ttậậpp

Nhập vào một danh sách lớp sinh viên gồm 2 thông tin: Tên và điểm.

Hiển thị danh sách sinh viên

Tính điểm trung bình cộng điểm của các sinh viên.

Tìm và hiển thị tên các sinh viên đạt điểm lớn hơn hoặcbằng giá trị trung bình cộng vừa tính được.

Tìm và hiển thị tên sinh viên có điểm cao nhất lớp.

Yêu cầu:• Sử dụng kết hợp kiểu mảng và kiểu struct

• Cấp phát động cho mảng