Nhập môn lập trình (Pascal)
MỤC LỤC
Phần 1: Tin học cơ sở . 3
Chƣơng 1. Những khái niệm nhập môn tin học cơ sở . 3
1.1. Những khái niệm cơ bản. . 3
1.2. Hệ đếm và cách chuyển đổi giữa các hệ đếm. . 9
Chƣơng 2. Hệ điều hành Windows. 13
2.1. Một số khái niệm . 13.
2.2. Một số lệnh hay dùng nhất của Start memu . 16
2.3 Cách tổ chức và trao đổi thông tin trên DESKTOP . 18
2.4 Cách tạo Shortcut trên DESKTOP . 19
2.5. Trình ứng dụng Windows Explorer . 20
Chƣơng 3. Hệ soạn thảo văn bản Microsoft Word . 25
3.1. Khái niệm . 25
3.2. Những yếu tố đầu tiên để soạn thảo văn bản . 25
3.3. Cất, mở, đóng tệp tài liệu. . 28
3.4. Các xử lý văn bản và khối văn bản; định dạng ký tự . 29
3.5. Một số kỹ thuật tăng tốc khi soạn thảo văn bản . 32
3.6. Tạo bảng và các xử lý trong bảng. 37
3.7. Thiết lập trang và một số chức năng khác . 41
Phần 2: Ngôn ngữ lập trình Pascal. 45
Chƣơng 1. Nhập môn . 45
1.1. Những khái niệm mở đầu chung về lập trình . 45
1.1.1. Ngôn ngữ lập trình là gì? . 45
1.1.2. Chương trình là gì? . 45
1.2. Những khái niệm cơ bản về ngôn ngữ Pascal . 47
1.2.1. Bộ ký tự của PASCAL . 48
1.2.2. Từ khoá . 48
1.2.3. Tên . 49
1.2.4. Tên chuẩn . 49
1.2.5. Cấu trúc của chương trình viết trên PASCAL . 49
1.2.6. Một vài vấn đề khác . 51
1.3. Các kiểu dữ liệu đơn giản chuẩn, các hàm chuẩn . 51
1.4. Các hàm chuẩn của PASCAL. . 54
1.5. Khai báo hằng, biến, kiểu, biểu thức, câu lệnh . 55
Chƣơng 2. Các lệnh cơ bản có cấu trúc . 58
2.1. Cấu trúc tuần tự . 58
2.2. Các cấu trúc rẽ nhánh . 59
2.2.1. Lệnh IF.THEN . 59
2
2.2.2. Lệnh IF.THEN.ELSE . 60
2.2.3. Lệnh CASE.OF . 61
2.3. Các cấu trúc lặp (các câu lệnh lặp) . 62
2.3.1. Câu lệnh FOR (dạng tiến và dạng lùi) . 62
2.3.2. Câu lệnh REPEAT.UNTIL . 63
2.3.3. Câu lệnh WHILE.DO . 63
Chƣơng 3. Lập trình cấu trúc trong Pascal (Hàm - Thủ tục) 65
3.1. Thủ tục trong Pascal . 65
3.1.1. Thủ tục không có các tham số hình thức. . 65
3.1.2. Thủ tục có các tham biến hình thức . 66
3.2. Các loại biến nhớ trong lập trình cấu trúc . 67
3.2.1. Biến chung . 67
3.2.2. Biến riêng . 67
3.3. Hàm trong Pascal . 67
3.4. Hàm đệ quy . 69
Chƣơng 4. Mảng và tập hợp . 72
4.1. Mảng . 72
4.1.1. Khai báo mảng . 72
4.1.2. Một số thuật toán cơ bản trên mảng . 73
4.2. Tập hợp . 75
Chƣơng 5. Dữ liệu kiểu xâu ký tự (String) . 79
5.1. Khai báo xâu và các phép toán trên xâu . 79
5.2. Các thủ tục và hàm xử lý xâu . 80
Chƣơng 6. Dữ liệu kiểu bản ghi và tệp . 82
6.1. Bản ghi . 82
6.2. Mảng các bản ghi . 84
6.3. Tệp . 85
Chƣơng 7: Biến con trỏ . 91
7.1. Khai báo . 91
7.2. Các phép toán . 93
ải thử xem tệp có còn phần tử không (tức là đã ở
cuối tệp chưa?). Hàm chuẩn EOF sẽ báo cho biết. Do vậy
trước khi đọc tệp cần kiểm tra xem tệp đó đã ở cuối tệp chưa
bằng câu lệnh:
IF not EOF(Biến_Tệp) then READ(Biến_Tệp, X);
Nếu muốn đọc tất cả các phần tử của tệp
WHILE NOT EOF(Biến_Tệp) DO
Begin
READ (Biến_Tệp, X);
....
End;
Việc cuối cùng là đóng tệp lại: CLOSE(Biến_Tệp);
* Tệp với các phần tử của tệp là dữ liệu có cấu trúc:
Vì phần tử của tệp là cả một bản ghi nên để ghi vào
tệp ta phải dùng:
Write (FNS, Nguoi);
chứ không thể ghi riêng rẽ từng thành phần, từng trường
như:
Write (FNS, Nguoi.Ten);
Tệp truy nhập trực tiếp:
Cách viết:
SEEK (Biến_Tệp, No)
trong đó No là số thứ tự của phần tử trong tệp
Cần chú ý là phần tử đầu tiên của tệp được đánh số là 0;
Theo thủ tục này, máy sẽ đặt vị trí con trỏ tệp đến phần tử
thứ No. Sau đó ta chỉ việc dùng thủ tục Read để đọc phần tử
89
đó ra, hoặc Write để ghi giá trị mới vào. Như vậy ta có thể
cập nhật một tệp một cách dễ dàng.
Các thủ tục và hàm xử lý tệp của TP:
* FileSize(Biến_Tệp) : Hàm cho số phần tử của tệp. Hàm
nhận giá trị 0 khi tệp rỗng.
* FilePos(Biến_Tệp) : Hàm cho vị trí tức thời của con trỏ
tệp. Phần tử đầu tiên là số 0.
* Erase(Biến_Tệp) : Thủ tục xoá file trên đĩa.
* Rename(Biến_Tệp, Str) : Thủ tục thay đổi tên tệp với tên
có kiểu String chứa trong biến Str. Lưu ý là tên mới không
được trùng với một tên tệp nào có sẵn trong đĩa.
Tệp văn bản (TEXT File)
Trong Pascal có một kiểu tệp đ• được định nghĩa
trước, đó là tệp văn bản được định nghĩa với từ chuẩn TEXT
Ví dụ:
VAR
F1, F2 : TEXT;
Các phần tử của tệp kiểu TEXT là các ký tự, song
TEXT file khác với FILE OF Char ở chỗ tệp văn bản được
tổ chức thành từng dòng với độ dài mỗi dòng khác nhau nhờ
có thêm các dấu hết dòng (EndOfLine) hay dấu chấm xuống
dòng. Đó là cặp ký tự điều khiển: CR(Carriage Return: Nhảy
về đầu dòng, mã ASCII = 13) và LF (Line Feed : Nhảy
thẳng xuống dòng tiếp theo, mã ASCII = 10).
Ví dụ:
Đoạn văn bản sau:
Hom nay la Chu nhat
12345
Ket thuc
được hiểu là máy sẽ chứa trong tệp văn bản thành một dãy
như sau:
Hom nay la Chu nhat CR LF 12345 CR LF Ket thuc EOF
Việc đọc và ghi tệp văn bản cũng như các tệp tuần tự
ở trên chỉ khác ở chỗ. Tệp văn bản không chấp nhận nhận xử
lý trên các biến có cấu trúc (mảng, bản ghi, file).
Tệp không định kiểu (UnTyped File)
Tệp không định kiểu là một kiểu file đặc biệt, được
định nghĩa ra trong TP và nó là một công cụ mạnh để bạn có
thể khai thác. Đó là tệp khi định nghĩa hay khai báo ra, ta
90
không nói rõ nó chứa gì, không nói rõ bản chất của các dữ
liệu được ghi trong đó.
Cách viết:
VAR
F1 , F2 : FILE;
F1 và F2 ở đây là hai tệp không định kiểu.
Không như các tệp văn bản hay tệp có định kiểu, thủ
tục Reset và Rewrite đối với tệp không định kiểu F1 và F2
còn có thêm một tham số nữa, đó là kích thước của Record.
Ví dụ:
RESET (F1, 1): có nghĩa là chuẩn bị FILE để đọc và
đọ dài của Record = 1byte.
Nếu chỉ ghi RESET(F1): thì máy sẽ coi độ dài Record
là 128 bytes.
Việc ghi và đọc đối với tệp không định kiểu còn dùng
đến hai thủ tục là:
BlockRead và BlockWrite.
Ví dụ:
BlockRead(F1 , Str, SizeOf(Str), RecordRead);
Hàm SizeOf(Str) để lấy kích thước của biến Str.
RecordRead để nhận biết có bao nhiêu Record đã
được đọc từ đĩa ra Str. Nếu tham số này có giá trị = 0 báo
rằng hết dữ liệu để đọc.
Thủ tục BlockWrite(F2, Str, RecordWrite);
RecordWrite là số Record thực sự cần ghi vào đĩa.
91
CHƢƠNG 7: BIẾN CON TRỎ
7.1. Khai báo
Khi khai báo một biến, dù là biến đơn hay biến thuộc kiểu
dữ liệu có cấu trúc mặc nhiên chúng ta đã quy định độ lớn vùng
nhớ dành cho biến.
Ví dụ:
a: Real; biến a cần 6 byte
b: aray[1..100] of Integer; biến mảng b cần 200 byte.
Việc khai báo như trên thường là phỏng đoán dung lượng
cần thiết chứ không thật chính xác. Để tránh lỗi chúng ta thường
khai báo dôi ra gây nên lãng phí bộ nhớ. Việc xác định địa chỉ lưu
trữ biến và cấp phát bộ nhớ được thực hiện khi biên dịch, nghĩa là
các địa chỉ này cũng như dung lượng bộ nhớ cần cấp phát đã được
cố định trước khi thực hiện các thao tác khác. Các đại lượng này
không thay đổi trong suốt quá trình thực hiện chương trình, nói
cách khác đây là các đại lượng tĩnh. Để tiết kiệm bộ nhớ, ngay khi
chương trình đang làm việc người lập trình có thể yêu cầu cấp phát
bộ nhớ cho các biến, điều này được gọi là cấp phát bộ nhớ động.
Cấp phát bộnhớ động được thực hiện thông qua biến con trỏ.
Kiểu con trỏ là một kiểu dữ liệu đặc biệt dùng để biểu diễn
các địa chỉ. Kiểu con trỏ do người lập trình định nghĩa theo cú pháp
sau:
Type
Tên kiểu con trỏ = ^Kiểu dữ liệu;
Tên kiểu con trỏ tuân theo quy định đặt tên của Pascal, Kiểu
dữ liệu của kiểu con trỏ là các kiểu dữ liệu đã định nghĩa trước
trong pascal. ðể một kiểu con trỏ có thể đại diện cho một biến nào
đó thì kiểu dữ liệu viết sau ký tự ^ sẽ phải giống như kiểu dữ liệu
của biến đó, nói cách khác hai kiểu dữ liệu phải tương thích.
Ví dụ 7.1: Khai báo kiểu con trỏ:
Type
Chu = string[20];
CT1 = ^Byte;
CT2 = ^chu;
CT3 = ^Nguoi;
Nguoi = record
Hoten:string[20];
Namsinh: 1900..2100;
End;
92
Ví dụ trên định nghĩa ba kiểu con trỏ, riêng kiểu CT3 cách
định nghĩa có vẻ hơi ngược là định nghĩa kiểu con trỏ trước, định
nghĩa kiểu dữ liệu sau. Thật ra chúng ta cứ nên theo thói quen là
định nghĩa kiểu dữ liệu trước rồi định nghĩa kiểu con trỏ sau, cách
định nghĩa CT3 chẳng qua là muốn giới thiệu để chúng ta biết rằng
Pascal cho phép làm ngược lại, tuy nhiên cần nhớ rằng nếu định
nghĩa kiểu con trỏ trước thì ngay trong phần Type phải định nghĩa
kiểu dữ liệu (không nhất thiết phải liền ngay sau định nghĩa kiểu
con trỏ).
Biến con trỏ
Biến con trỏ cũng như biến mảng, biến kiểu bản ghi hay kiểu
tập hợp có thể khai báo thông qua kiểu con trỏ hoặc khai báo trực
tiếp. Biến con trỏ có định kiểu sẽ trỏ đến một kiểu dữ liệu cụ thể.
Để thuận tiện từ nay chúng ta dùng thuật ngữ "Con trỏ" thay
cho thuật ngữ " Biến con trỏ"
Ví dụ 7.2:
Var
So: ^Integer;
Sinhvien: Ct3;
Hoten: Ct2;
Thutu, Mahoso: ^Word;
Trong ví dụ trên chúng ta đã khai báo ba con trỏ So, Thutu,
Mahoso theo kiểu trực tiếp, hai con trỏ Sinhvien và Hoten khai báo
thông qua kiểu đã định nghĩa trong ví dụ 7.1. Con trỏ So trỏ tới
kiểu dữ liệu số nguyên, con trỏ Sinhvien trỏ tới kiểu dữ liệu bản ghi
còn con trỏ Hoten trỏ tới kiểu dữ liệu chuỗi.
Địa chỉ của các biến động và biến tĩnh sẽ được Pascal lưu trữ
vào biến con trỏ điều này có nghĩa là biến con trỏ không dùng để
lưu trữ các giá trị của biến mà là địa chỉ của biến. Dù kích thước
vùng dữ liệu mà các biến con trỏ trỏ tới khác nhau thế nào thì kích
thước của biến con trỏ cũng vẫn là 4 byte.
Các hàm và thủ tục xử lý biến con trỏ được Pascal lưu trữ
trong Unit System.
Quy ước: Các biến con trỏ gọi là tương thích nếu chúng trỏ
tới cùng một kiểu dữ liệu
93
7.2. Các phép toán
Gán giá trị ban đầu:
Giả sử ct là một biến con trỏ đã được định nghĩa, để đảm bảo
rằng ct chưa trỏ đến bất kỳ một đối tượng nào, nghĩa là ct là một
con trỏ rỗng chúng ta phải gán cho ct giá trị NIL
ct := Nil;
Gán địa chỉ của một đối tượng cho con trỏ:
Giả sử ct là một con trỏ và x là một đối tượng (biến, hàm,
thủ tục), có ba cách gán địa chỉ của đối tượng x cho con trỏ ct:
a. ct := @x;
Trong phép gán trên toán tử @ tác động trên đối tượng x sẽ
gán vào con trỏ ct địa chỉ kiểu Pointer của đối tượng đó.
b. ct := Addr(x);
Hàm Addr() cho địa chỉ của đối tượng x, địa chỉ này thuộc
kiểu Pointer
c. ct := Ptr(segment,offset) ;
Hàm Ptr trong phép gán trên đòi hỏi các tham số segment và
offset phải là giá trị kiểu Word viết trong hệ 16, ví dụ:
ct := Ptr($B800, $0000); đưa con trỏ trỏ tới ô nhớ của vùng
Video Ram
Nhận xét: Hai phép gán @ và Addr() cùng trả về địa chỉ kiểu
pointer nên chúng là tương đương.
Phép gán giữa hai con trỏ
Hai con trỏ tương thích (cùng kiểu) có thể gán giá trị cho
nhau, khi đó chúng cùng trỏ tới một địa chỉ.
Ví dụ 7.3:
Var
ct1: ^Float;
ct2: ^Byte;
ct3: Pointer;
x: string;
Ví dụ trên khai báo ba con trỏ thuộc ba kiểu khác nhau, ct1
là con trỏ thực, ct2 là con trỏ nguyên và ct3 là con trỏ không định
kiểu, x là biến chuỗi. Khi đó các phép gán:
ct3:=@x;
ct2 := ct3;
là hợp lệ vì ct2 và ct3 là tương thích, chúng cùng trỏ đến địa chỉ của
biến x.
Còn phép gán
94
ct1 := ct2;
là không hợp lệ vì hai con trỏ không tương thích.
Phép so sánh hai con trỏ
Chỉ tồn tại phép so sánh = (bằng nhau) và (khác nhau)
giữa hai con trỏ nếu chúng tương thích. Kết quả so sánh là một giá
trị Boolean nghĩa là True hoặc False.
Hai con trỏ tương thích gọi là bằng nhau nếu chúng cùng trỏ
tới một đối tượng, ngược lại gọi là khác nhau.
Ví dụ 7.4:
Program contro;
Uses crt;
Var
x,y:real; z:string;
ct1: ^integer; ct2: ^byte; ct3:pointer; ct4,ct5: ^real;
Begin
clrscr;
z:='Ha noi'; x:=5; y:=-123.45;
ct1:=@x; ct2:=@z; ct3:=@z; ct4:=@z; ct5:=@y;
Writeln(ct1=ct2); { không tương thích, máy sẽ báo lỗi}
Writeln(ct1=ct3); {false}
Writeln(ct2=ct3); {true}
writeln(ct4=ct5); {false}
readln;
end.
Ví dụ 7.4 khai báo năm con trỏ, ct1 và ct2 trỏ tới các kiểu
nguyên khác nhau, ct3 là con trỏ không kiểu tức là tương thích với
mọi con trỏ khác, hai con trỏ ct4 và ct5 là cùng kiểu.
Các phép so sánh trong thân chương trình cho thấy một số
điều cần chú ý :
- Phép so sánh ct1=ct2 là không hợp lệ vì hai con trỏ
không tương thích
- Phép so sánh ct1 = ct3 cho kết quả False vì hai con trỏ
tương thích nhưng trỏ tới các địa chỉ khác nhau
- Phép so sánh ct2 = ct3 cho kết quả True vì hai con trỏ là
tương thích và cùng trỏ tới một địa chỉ.
- Phép so sánh ct4 = ct5 cho kết quả False vì hai con trỏ
cùng kiểu nhưng trỏ tới các địa chỉ khác nhau.
File đính kèm:
Nhập môn lập trình (Pascal).pdf

