Chương 7 Kiểu xâu kí tự Khai báo kiểu vμ biến Cú pháp khai báo kiểu xâu kí tự: TYPE tên kiểu = STRING ; hoặc TYPE tên kiểu = STRING [ độ dμi cực đại] ; Trong đó độ dμi cực đại lμ một
Trang 1đích Chọn phần tử nhỏ nhất trong dãy nguồn còn lại, đây lμ phần tử nhỏ thứ hai, xếp nó vμo vị tri thứ hai vμ cũng lμ vị trí cuối của dãy đích vμo lúc nμy Lặp lại việc nμy cho đến khi hết dãy nguồn
Để tiết kiệm chỗ, ta cũng xếp dãy đích vμ dãy nguồn liền nhau trong
mảng, giống như trong phương pháp trước Do đó, ở bước thứ i, thao tác
"xếp vμo cuối dãy đích" chính lμ "đổi chỗ cho a[i]"
Xuất phát
Dãy nguồn Dãy đích
rỗng
Bước 1: - Chọn phần tử bé nhất từ dãy nguồn,
- Đổi chỗ cho phần tử a[1]
Dãy đích Dãy nguồn
a1
Chọn phần tử min
Bước i:
- Chọn phần tử bé nhất từ dãy nguồn còn lại lμ a[i], a[i+1], , a[n]
- Đổi chỗ cho a[i]
Trang 2Dãy đích Dãy nguồn
ai
“ chọn phần tử min của dãy a[i],a[i+1], ,a[n] ”
“ đổi chỗ cho a[i]”
end
var i,j,k: integer;
x: real;
begin for i:=1 to size-1 do
begin k:=i; x:=a[i];
for j:=i+1 to size do
if a[j]<x then begin k:=j; x:=a[j];
a[k]:=a[i];
a[i]:=x;
Trang 32 Các khai báo kiểu mảng dưới đây đúng hay sai, mô tả rõ cấu trúc mảng
Array [10 0] of Real; Array ['0' '9'] of Real;
Array ['a' 'z'] of Char; Array [A Z] of Integer;
Array [(A,B,C)] of (-10 10); Array [Byte] of Boolean;
Array [Integer] of Integer; Array [Char] of Byte;
3 Để xử li mọi phần tử của mảng thường dùng vòng lặp gì? Có thể dùng những vòng lặp nμo?
4 Trong Pascal kiểu mảng có thể nhiều nhất lμ mấy chiều
5 Thế nμo lμ mảng sắp theo ưu tiên hμng, ưu tiên cột Mảng trong Pascal thuộc kiểu nμo?
Thực hμnh
1 Nhập dãy n số thực Tính trung bình cộng, tìm trung vị (median), tìm
phần tử lớn nhất, nhỏ nhất; tìm phần tử lớn thứ nhì; đếm số phần tử dương,
âm; Tìm chỉ số của phần tử âm đầu tiên, cuối cùng; kiểm tra dãy đan dấu
2 Nhập dãy số; trich ra dãy con lμ cấp số cộng, cấp số nhân có nhiều phần tử nhất
3 Cho số nguyên dương hệ 10, hãy in ra số đó ở hệ 2, 8, 16
4 Nhập dãy n giá trị quan trắc của một đại lượng ngẫu nhiên Tìm phương sai vμ độ lệch tiêu chuẩn
5 Tính tích vô hướng của hai véc tơ
6 Nhập dãy n số vμ một số x Tìm xem có bao nhiêu số trong dãy trùng với
x Chúng ở các vị trí nμo?
7 Cho ma trận các số nguyên A[1 7; 8 14] với A[i,j]:= i*j Tính tổng các
phần tử trên một cột, trên một hμng, trên đường chéo chính, trên đường chéo phụ
8 Cho ma trận vuông Tách thμnh hai ma trận tam giác trên vμ tam giác dưới rồi in ra mμn hình
9 Nhập từ bμn phím một dãy số nguyên, in ra các giá trị khác nhau kèm số lần xuất hiện
10 Viết chương trình sắp xếp một dãy số, dùng các thủ tục
a -) chèn trực tiếp,
b -) chọn trực tiếp,
Trang 4c -) đổi chỗ trực tiếp
11 Nhập hai dãy số nguyên cùng có n phần tử Kiểm tra xem có phải một
dãy chỉ lμ hoán vị của dãy kia hay không
12 Cho n điểm khác nhau p i = (x i , y i ) vμ đường gấp khúc khép kín nối các
điểm nμy theo thứ tự từ p 1 , p 2 , , p n , p 1
a) kiểm tra xem đường gấp khúc có tự cắt không
b) nếu đường gấp khúc không tự cắt thì có phải lμ đa giác lồi không
c) tìm các đỉnh tạo thμnh đa giác lồi bao bọc cả n điểm
Trang 5Chương 7 Kiểu xâu kí tự
Khai báo kiểu vμ biến
Cú pháp khai báo kiểu xâu kí tự:
TYPE tên kiểu = STRING ;
hoặc TYPE tên kiểu = STRING [ độ dμi cực đại] ;
Trong đó độ dμi cực đại lμ một số n nguyên dương, n <= 255 Độ
dμi của một biến xâu kí tự được hiểu lμ số kí tự của dãy, kể các các kí tự
khoảng trống xen giữa hoặc nằm ở hai đầu Với cách khai báo thứ nhất,
không ấn định độ dμi cực đại thì mặc định lμ độ dμi cực đại bằng 255
Trang 6Một hằng xâu kí tự lμ một dãy kí tự ASCII nằm trong cặp dấu nháy
đơn Cú pháp ngôn ngữ Pascal quy định viết giá trị xâu kí tự trong cặp dấu nháy đơn (single quote) Ví dụ, ‘Turbo Pascal’, ‘Dai hoc Quoc gia Ha Noi”, v.v
Xâu rỗng lμ xâu không có kí tự nμo vμ có độ dμi bằng 0 Viết xâu rỗng chỉ có cặp dấu nháy đơn liền nhau, không có kí tự nμo bên trong Cần chú ý phân biệt xâu rỗng với xâu chỉ gồm các kí tự khoảng trống
Có thể in biểu thức xâu kí tự ra mμn hình, máy in hay tệp văn bản bằng
các lệnh Write Thủ tục Write (St) sẽ in ra nguyên văn xâu kí tự St, kể cả
các dấu trống ở đầu vμ cuối xâu
Ví dụ: Giả sử Dòng1, Dòng2 lμ hai biến xâu kí tự vμ ta thực hiện
Chi tiết hơn về sử dụng thủ tục Write để viết ra vμ quy cách định dạng
viết ra đã được trình bμy trong Chương 3
Trang 7Ví dụ, nếu giá trị của biến xâu kí tự SV1 lμ 'Nguyen Van A' thì
- Có thể truy cập vμo từng kí tự trong xâu, dùng tên biến vμ số thứ tự của nó trong xâu đặt trong dấu ngoặc vuông, giống như đối với mảng một
chiều Ví dụ, phép so sánh SV1 [8] = 'V' cho kết quả True
- Có thể lấy độ dμi thực sự của xâu kí tự St bất kì, thông qua mã ASCII của phần tử St[0], tức lμ độ dμi của xâu St bằng Ord (St[0]).
Lưu ý rằng ta cũng có hμm chuẩn cho biết độ dμi của xâu kí tự St lμ
Length (St)
Ví dụ
Viết chương trình nhập một xâu kí tự từ bμn phím vμ in ra xâu đảo
ngược từ phải sang trái
Uses crt;
Var Xau: String;
I: byte ;
BEGIN
Writeln('Cho mot xau ki tu: '); Readln( Xau );
For i:= lenght (Xau) downto 1 do write (Xau[i]); Readln;
END
Chú ý: Xâu kí tự khác với mảng một chiều các kí tự ở chỗ độ dμi thực
sự cuả biến xâu kí tự có thể thay đổi, chiếm vừa đủ chỗ cần thiết, trong khi mảng một chiều có dộ dμi cố định Điều nμy lμm cho các thao tác với biến xâu kí tự đơn giản vμ linh hoạt hơn nhiều so với mảng một chiều các kí tự
Trang 82 Thao tác với xâu kí tự
Ví dụ 1:
Biến SV1 có gía trị lμ ‘Nguyen Van A’ thì biểu thức ' Họ vμ tên: ' +
SV1 sẽ có giá trị lμ ' Ho va tên: Nguyen Van A '
Ví dụ 2:
Path:= 'C:\TP\bin\' ; FileName:= 'Turbo.exe' ; St:= Path + FileName;
sẽ nhận được St:= ' C:\ TP\bin\Turbo.exe '
Phép so sánh
So sánh bằng nhau “ = ” vμ khác nhau “ <> ”
Phép so sánh hai biểu thức xâu kí tự "bằng nhau" cho kết quả True
nếu từng cặp kí tự tương ứng ở hai xâu lμ trùng nhau Trái lại, phép so sánh
“bằng nhau” sẽ cho kết quả False
Ví dụ: Nếu biến kiểu xâu kí tự SV1 đã được gán giá trị như trong ví
dụ ở trên thì
SV1 = 'Nguyen Van A' cho giá trị True
SV1 = 'Nguyen Van A' cho giá trị False
Thứ tự của kiểu xâu kí tự
Xâu kí tự lμ kiểu có thứ tự Thứ tự của kiểu xâu lμ thứ tự từ điển Phép so sánh thứ tự hai xâu kí tự được thưc hiện qua so sánh lần lượt từng cặp kí tự tương ứng ở hai xâu, từ trái sang phải Thứ tự của xâu lμ thứ tự của cặp kí tự đầu tiên không trùng nhau
Ví dụ:
'abcd' < 'abed' cho giá trị True
'abc' < 'abcdef' cho giá trị True
2.2 Các thủ tục và hàm trên xâu kí tự
Trang 9Trong th− viện các hμm, thủ tục lμm sẵn của Pascal có một số hμm, thủ tục về xử lí xâu kí tự
2.2.1 Các thủ tục
Delete (St, Pos, Num):
- St lμ biến kiểu String
- Num, Pos lμ các giá trị nguyên
- Tác dụng: xoá khỏi xâu St một số l−ợng Num kí tự, bắt đầu từ vị trí
Pos, từ trái sang phải
- St2 lμ biểu thức kiểu String
- St1 lμ biến kiẻu String
- Pos lμ giá trị nguyên
Tác dụng: chèn thêm xâu St2 vμo xâu St1 tại vị trí Pos Nếu Pos
v−-ợt quá độ dμi xâu đích thì St2 sẽ đ−ợc nối thêm vμo đuôi
Ví dụ: insert('123' , St, 4); sẽ cho St = 'ABCD123EF'
insert('123' , St,10) ; sẽ cho St = 'ABCDEF123'
Str (Value, St);
- Value lμ biểu thức nguyên hay thực, có quy cách in ra
- St lμ biến kiểu String
Tác dụng: đổi gía trị số thμnh xâu kí số rồi gán cho xâu St
- Var lμ biến nguyên hay thực
- Code lμ biến nguyên
Tác dụng: đổi xâu chữ số (biểu diễn một số nguyên hay số thực) thμnh
ra một giá trị số vμ gán cho biến Var Code lμ cờ báo lỗi Nếu phép chuyển
đổi thực hiện đúng thì code = 0 Nếu sai, do St không biểu diễn đúng lμ một số, thì Code sẽ có giá trị lμ vị trí của kí tự sai trong xâu chữ số
Trang 10Length (St): cho biết độ dμi của xâu St
Copy (St, Pos, Num):
- St lμ biểu thức xâu kí tự,
- Pos, Num biểu thức kiểu nguyên
Tác dụng: trích ra một xâu con từ xâu con từ xâu St, bắt đầu từ vị trí
Pos vμ dμi Num kí tự Nếu Pos + Num lớn hơn độ dμi xâu St thì xâu kết
quả chỉ gồm các kí tự cuối trong xâu St Nếu Pos lớn hơn độ dμi của St thì
xâu kết quả lμ rỗng
Ví dụ: St:= 'ABCDEF' ;
St_con:= Copy (St, 3, 3) ; sẽ cho St_con = 'CDE'
St_con:= Copy (St, 4,4) ; sẽ cho St_con = 'DEF'
St_con:= Copy (St, 10,5) ; sẽ cho St_con = ' '
Concat (St1, St2, , Stn):
Ghép nối tất các xâu thμnh một xâu
- Nếu tổng chièu dμi các xâu > 255 máy sẽ báo lỗi
Câu hỏi vμ bμi tập
1 Mô tả cấu trúc của một biến kiểu xâu kí tự
2 Độ dμi cực đại của xâu kí tự lμ bao nhiêu
Trang 113 X©u kÝ tù kh¸c m¶ng kÝ tù nh− thÕ nμo T¹i sao sö dông kiÓu x©u l¹i tiÖn lîi h¬n dïng m¶ng kÝ tù
Thùc hμnh
1 T¹o mét dßng ch÷ ch¹y tõ tr¸i sang ph¶i (hoÆc tõ ph¶i sang tr¸i) trong mét khung h×nh ch÷ nhËt trªn mμn h×nh
2 Tù viÕt l¹i c¸c hμm thñ tôc xö lÝ x©u kÝ tù trong tiÕt 2
3 ViÕt ch−¬ng tr×nh chuyÓn n sè thùc d−íi d¹ng mét x©u c¸c ch÷ sè c¸ch nhau kho¶ng tr¾ng vμo mét m¶ng n sè thùc, kh«ng dïng hμm chuÈn
Val.(ChÝnh lμ thùc hiÖn c«ng viÖc cña readln (r, r2, , rn)),
Trang 12Chương 8 Kiểu bản ghi
1 Định nghĩa và khai báo
1.1 Định nghĩa
Các kiểu dữ liệu được xây dựng đều lμ mô hình hoá các loại dữ liệu từ
thế giới thực Các đối tượng thực tế thường phức tạp, hμm chứa nhiều thông
tin khác kiểu nhau Ví dụ, thông tin về một cán bộ bao gồm họ tên, quê quán
(có kiểu xâu kí tự), giới tính (kiểu logic), tuổi (kiểu số nguyên), mức lương
(kiểu số thực) Thông tin về một sản phẩm hμng hóa bao gồm mã số, tên
gọi (kiểu xâu kí tự), ngμy sản xuất (kiểu ngμy tháng), giá thμnh (kiểu số
thực),v.v
Để tiện xử lí các đối tượng nμy, cần có cơ chế ghép nhiều thμnh phần
dữ liệu có kiểu khác nhau thμnh một đơn vị thống nhất
Kiểu bản ghi - Record chính lμ cấu trúc dữ liệu đáp ứng đòi hỏi nμy
Một dữ liệu kiểu bản ghi tạo nên từ nhiều thμnh phần, gọi lμ các trường –
field Mỗi trường lμ một mục dữ liệu có thể khác kiểu nhau
1.2 Khai báo kiểu bản ghi
1.2.1
1.2.2
Cú pháp
Cú pháp khai báo kiểu bản ghi như sau
Type tên kiểu = Record
tên trường 1 : mô tả kiểu dữ liệu 1;
tên trường n : mô tả kiểu dữ liệu n ;
end ;
Ví dụ
Ví dụ 1: Kiểu ngμy- tháng- năm để ghi lại các mốc thời gian
Trang 13Ngay: 1 31 ;
Nam: Word ;
END ;
Ví dụ 2: Kiểu địa chỉ
TYPE Adress = RECORD
SoNha: Word ; Phố: String [20] ; Tỉnh: String [15] ;
Chú ý: - Có thể viết các định nghĩa kiểu bản ghi lồng nhau Nếu trước
đó ta chưa định nghĩa kiểu Date thì có thể viết lồng trực tiếp định nghĩa kiểu
Date bên trong định nghĩa kiểu HoSo như sau:
TYPE HoSo = RECORD
Trang 14Ví dụ
VAR KhơiCông, KhanhThanh, NgSinh_1, NgSinh_2 : Date ;
CanBo1, CanBo2: HoSo ;
2 Sử dụng
2.1 Truy cập từng thành phần
Kiểu bản ghi cho phép truy cập từng thμnh phần, tức lμ từng trường của nó
Cú pháp: tên biến, dấu chấm, tên trường dữ liệu muốn truy cập
Gán giá trị tên biến tên trường := giá trị;
Đọc giá trị vế trái:= tên biến tên trường;
2.2 Các phép toán với toàn bộ bản ghi
Có thể thực hiện một số phép toán với toμn bộ biến kiểu bản ghi như một toán hạng
2.2.1
2.2.2
Phép gán
Cho phép gán đối với hai biến bản ghi cùng kiểu
Tiếp tục ví dụ 1 ở trên có thể viết
CanBo1 NgaySinh := NgSinh_1 ;
Phép so sánh
Có thể so sánh bằng nhau “ = ”, khác nhau “<>”
Trang 15Phép so sánh "bằng nhau" thực hiện qua so sánh từng cặp các trường tương ứng Hai bản ghi lμ bằng nhau nếu các trường tương ứng trùng nhau hoμn toμn Trái lại lμ khác nhau
Ví dụ: Sau lệnh gán
thì phép so sánh CanBo1 = CanBo2 cho kết quả lμ true ;
- Kiểu bản ghi không có thứ tự, do đó không cho phép các so sánh < ,
> , >= , >=
2.2.3 Lưu ý về tên kiểu
Khi thực hiện các phép toán với toμn thể bản ghi như một toán hạng
cần phải đảm bảo tương thích hiển về kiểu Các phép toán sẽ bị coi lμ không
hợp lệ ngay cả khi thực chất lμ cùng kiểu nhưng ta dùng hai tên kiểu khác nhau hoặc ta khai báo biến kèm mô tả kiểu dữ liệu trực tiếp (tức lμ kiểu dữ liệu không tên)
Giả sử có các khai báo kiểu vμ biến dưới đây:
TYPE Date = RECORD
Ngay: 1 31;
Thang: 1 12 ; Nam: Word ;
END;
NgThang = RECORD
Ngay: 1 31;
Thang: 1 12 ; Nam: Word ;
END;
Các câu lệnh sau đều sai cú pháp
N1:= N2 ; N2:= N3;
2.3 Đọc vào, viết ra với một biến kiểu bản ghi
Không dùng được các lệnh nhập xuất dữ liệu Read, Write cho toμn bộ cả một bản ghi mμ phải xử lí đến từng trường thμnh phần
Trang 16Ví dụ, nếu mốn nhập từ bμn phím các dữ liệu cho biến kiểu bản ghi
NgSinh_1 như ở ví dụ trên thì không thể dùng lệnh Read( NgSinh_1) rồi
nhập từ bμn phím các số 10 2 1970 mμ phải dùng 3 cặp lệnh liên tiếp như sau
Write(' cho ngay sinh ') ; Readln(NgSinh_1.Ngay );
Write(' cho tháng sinh ') ; Readln(NgSinh_1.Thang );
Write(' cho năm sinh ') ; Readln(NgSinh_1.Năm );
Tương tự như vậy, nếu muốn viết ra biến NgSinh_1 thì cũng không thể dùng lệnh Write(NgSinh_1) mμ phải truy cập vμ viết ra lần lượt từng
trường thμnh phần có kiểu dữ liệu chuẩn đơn giản
2.4 Câu lệnh With
Ta thấy rằng để truy cập các trường của bản ghi phải chỉ rõ tên biến bản ghi vμ sau đó lμ các tên trường Nếu bản ghi gồm nhiều trường thì tên biến bản ghi được lặp đi lặp lại nhiều lần
Để tránh lặp lại việc viết tên biến kiểu bản ghi khi muốn truy cập tới nhiều trường của nó cùng lúc, ta có thể dùng câu lệnh WITH
Cú pháp: With tên biến do câu lệnh ;
Có thể viết đoạn lệnh gán trị cho biến CanBo1 như sau:
Có thể sử dụng câu lệnh With lồng nhau để truy cập các trường của
một biến có cấu trúc kiểu bản ghi lồng nhau nhiều tầng Ví dụ, muốn gán
trực tiếp ngμy tháng năm sinh cho CanBo1 ta có thể dùng hai câu lệnh With
lồng nhau như sau
WITH CanBo1 DO
Trang 17WITH CanBo1 NgaySinh DO
Nghĩa lμ khi A lμ biến kiểu bản ghi, B lμ một trường của A vμ B lại lμ một biến bản ghi thì để thâm nhập vμo các trường của B thì chỉ cần viết
- Tạo ra nhiều kiểu bản ghi: CôngNhân, TríThức, DoanhNhân, chỉ
khác nhau ở trường nghề nghiệp
- Hoặc định nghĩa một kiểu bản ghi nhưng có 3 trường nghề nghiệp khác nhau vμ chỉ dùng một trong ba trường đó tuỳ trường hợp
Cả hai cách lμm trên đều cồng kềnh vμ lãng phí
Cần đặt ra kiểu mới linh hoạt hơn, đó lμ bản ghi có cấu trúc thay đổi Mô tả cú pháp kiểu bản ghi cấu trúc thay đổi
Trong định nghĩa kiểu bản ghi cho phép có một trường mμ cấu trúc của
nó tuỳ thuộc một biến lựa chọn bởi câu lệnh Case Ví dụ, để giải quyết
trường hợp các nghề nghiệp khác nhau cần ghi các thông tin khác nhau như
đã nêu trên ta có thể xây dựng một kiểu bản ghi với trường NghềNghiệp có
cấu trúc thay đổi như sau:
TYPE Nghề = (CôngNhân, KĩSư,TríThức, DoanhNhân) ;
Trang 18Ngμnh = (KhaiThÌc, CÈKhi, HọaChất, DầuKhÝ, ưiệnLỳc) ;
ChuyànMẬn = (ToÌn,Lý,HoÌ,Sinh ) ; TrỨnhườ = (CÈSỡ, TrungHoc, ưỈiHồc, ThỈcSị, PTS, TS );
HổSÈ = RECORD
Hồưệm: String [20] ; Tàn: String [20] ;
CASE NghềNghiệp: Nghề OF CẬngNhẪn: ( NgμnhCN: Ngμnh ; Bậc: Byte) ; KịSư: ( NgμnhKS: Ngμnh; TrỨnhườKS: TrỨnhườ); TrÝThực: (MẬn: ChuyànMẬn ; TrỨnhườTT: TrỨnhườ); DoanhNhẪn: ( ) ;
Như vậy, trưởng NghềNghiệp cọ cấu trục thay Ẽỗi tuỷ theo Nghề lμ gỨ
Nghề lμ biến lỳa chồn vμ Ẽưùc gồi lμ trưởng ẼÌnh dấu ựng vợi mối giÌ trÞ
cũa trưởng ẼÌnh dấu - lμ cÌc nh·n cũa lệnh Case - ta cọ cÌc cấu trục bản ghi
khÌc nhau thể hiện bÍng danh sÌch trưởng nÍm trong cặp dấu ngoặc ẼÈn Lưu ý rÍng cụ phÌp quy ẼÞnh phải cọ cặp dấu ngoặc ẼÈn dủ rÍng danh sÌch
trưởng lμ rống (xem trưÈng hùp nghề lμ Doanh NhẪn)
Tử khoÌ Case ỡ ẼẪy khẬng hoμn toμn giộng cẪu lệnh Case nhiều lỳa
chồn Ẽ· biết
3.1.3 CÌc quy ẼÞnh
- Chì Ẽưùc phÐp cọ mờt trưởng thay Ẽỗi Tuy nhiàn cÌc bản ghi cọ cấu trục thay Ẽỗi lỈi cọ thể lổng nhau
- Trưởng thay Ẽỗi phải lμ trưởng cuội củng
- Trong phần thay Ẽỗi tất cả cÌc tàn biến khẬng Ẽưùc trủng nhau dủ lμ nÍm trong hai trưởng hùp khÌc nhau Trong vÝ dừ tràn ta phải phẪn biệt
NgμnhCN vợi NgμnhKS cúng như phẪn biệt TrỨnhườKS vợi TrỨnhườTT dủ
rÍng chụng thuờc hai trưởng hùp khÌc nhau Nếu lμ hai kiểu bản ghi phẪn biệt thỨ ró rμng Ẽiều nμy khẬng cần thiết
3.2 Sữ dừng bản ghi cọ cấu trục thay Ẽỗi
Về nguyàn t¾c, truy cập cÌc biến bản ghi cấu trục thay Ẽỗi cúng giộng như truy cập bản ghi thẬng thưởng ưiểm khÌc nhau duy nhất lμ ỡ trưởng tuỷ
chồn Ta phải sữ dừng mờt cẪu lệnh Case Ẽể tuỷ biến theo mối trưởng hùp
Dượi ẼẪy lμ mờt chưÈng trỨnh minh hoỈ cÌch sữ dừng kiểu bản ghi cọ cấu trục thay Ẽỗi như ẼÞnh nghịa ỡ tràn Lưu ý phần in Ẽậm trong thũ từc hiển
thÞ biến bản ghi cọ cấu trục thay Ẽỗi ShowVariableRecord