Tải bản đầy đủ (.pdf) (284 trang)

Giáo trình Tin học đại cương A1 - GS.TSKH. Hoàng Kiếm

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (8.95 MB, 284 trang )

<span class='text_page_counter'>(1)</span><div class='page_container' data-page=1></div>
<span class='text_page_counter'>(2)</span><div class='page_container' data-page=2>

<b>CHƯƠNG 1</b>



<b>TỔNG QUAN VỀ MÁY TÍNH</b>


<b>1. GIỚI THIỆU</b>


Máy tính là cơng cụ xử lý thông tin. Về cơ bản, quá trình
xử lý thơng tin trên máy tính - cũng như q trình xử lý thơng
tin của con người - có bốn giai đoạn chính:


<i><b>Nhận thơng tin (Receive input): thu nhận thông tin từ thế </b></i>
giới bên ngồi vào máy tính. Thực chất đây là q trình chuyển
đổi các thơng tin ở thế giới thực sang dạng biểu diễn thông tin
trong máy tính thơng qua các thiết bị đầu vào.


<i><b>Xử lý thơng tin (process information): biến đổi, phân tích, </b></i>
tổng hợp, tra cứu... những thơng tin ban đầu để có được những
thông tin mong muốn.


<i><b>Xuất thông tin (produce output): đưa các thông tin kết quả </b></i>
(đã qua xử lý) ra trở lại thế giới bên ngồi. Ðây là q trình
ngược lại với quá trình ban đầu, máy tính sẽ chuyển đổi các
thơng tin trong máy tính sang dạng thơng tin ở thế giới thực
thông qua các thiết bị đầu ra.


<i><b>Lưu trữ thông tin (store information): ghi nhớ lại các </b></i>
thông tin đã được ghi nhận để có thể đem ra sử dụng trong
những lần xử lý về sau.


Ðể đáp ứng bốn thao tác đó thì một máy tính thơng thường
cũng gồm bốn bộ phận hợp thành, mỗi bộ phận có một chức
năng riêng:



</div>
<span class='text_page_counter'>(3)</span><div class='page_container' data-page=3>

<i><b>Thiết bị xử lý (đơn vị xử lý trung tâm - CPU )thực hiện thao </b></i>
tác xử lý, tính tốn các kết quả, điều hành hoạt động tính tốn
của máy vi tính. Có thể xem CPU như bộ não của con người.


<i><b>Thiết bị xuất (output): thực hiện thao tác gởi thơng tin ra </b></i>
ngồi máy vi tính, thường dùng màn hình máy tính làm thiết bị
xuất chuẩn, có thể thêm một số khác như máy in…


<i><b>Thiết bị lưu trữ (storage devices): được dùng để lưu giữ </b></i>
thông tin. Lưu trữ sơ cấp (primary memory) là bộ nhớ trong của
máy tính dùng để lưu các tập lệnh của chương trình, các thơng
tin dữ liệu sẵn sàng làm việc tùy theo yêu cầu của CPU. Lưu trữ
thứ cấp (secondary storage) là cách lưu trữ đơn thuần với mục
đích lưu giữ dữ liệu, cách này dùng các thiết bị lưu trữ như đĩa
cứng, đĩa mềm, băng từ, CD.


<b>2. THÔNG TIN - BIỂU DIỄN VÀ XỬ LÝ THÔNG TIN</b>
Khái niệm thông tin (information) được sử dụng thường
ngày. Con người có nhu cầu đọc báo, nghe đài, xem phim,
video, đi tham quan, du lịch, tham khảo ý kiến người khác, ...
để nhận được thêm thông tin mới. Thông tin mang lại cho con
người sự hiểu biết, nhận thức tốt hơn về những đối tượng trong
đời sống xã hội, trong thiên nhiên, ... giúp cho họ thực hiện hợp
lý công việc cần làm để đạt tới mục đích một cách tốt nhất.


</div>
<span class='text_page_counter'>(4)</span><div class='page_container' data-page=4>

Khi tiếp nhận được thông tin, con người thường phải xử lý
nó để tạo ra những thơng tin mới, có ích hơn, từ đó có những
phản ứng nhất định. Người tài xế chăm chú quan sát người, xe
cộ đi lại trên đường, độ tốt xấu mặt đường, tính năng kỹ thuật


cũng như vị trí của chiếc xe để quyết định, cần tăng tốc độ hay
hãm phanh, cần bẻ lái sang trái hay sang phải... nhằm đảm bảo
an toàn tối đa cho chuyến xe đi.


<i>Thơng tin có thể được phát sinh, được lưu trữ, được truyền, </i>
<i>được tìm kiếm, được sao chép, được xử lý, nhân bản. Thơng tin </i>
<i>cũng có thể biến dạng, sai lệch hoặc bị phá hủy.</i>


Mỗi tế bào sinh dục của những cá thể sinh vật mang thông
tin di truyền quyết định những đặc trưng phát triển của cá thể
đó. Gặp môi trường không thuận lợi, các thông tin di truyền đó
có thể bị biến dạng, sai lệch dẫn đến sự hình thành những cá thể
dị dạng. Ngược lại, bằng những tác động tốt của di truyền học
chọn giống, ta có thể cấy hoặc làm thay đổi các thông tin di
truyền theo hướng có lợi cho con người. Thông tin được thể
hiện dưới nhiều dạng thức khác nhau như sóng ánh sáng, sóng
âm, điện từ, các ký hiệu viết trên giấy hoặc khắc trên gỗ, trên
đá, trên các tấm kim loại ... Về nguyên tắc, bất kỳ cấu trúc vật
chất nào hoặc bất kỳ dòng năng lượng nào cũng có thể mang
thơng tin. Chúng được gọi là những vật (giá) mang tin. Dữ liệu
(data) là biểu diễn của thông tin và được thể hiện bằng các tín
hiệu (signal) vật lý.


</div>
<span class='text_page_counter'>(5)</span><div class='page_container' data-page=5>

Mỗi tín hiệu có thể dùng để thể hiện các thông tin khác nhau.
Uống một chén rượu để mừng ngày gặp mặt, cũng có thể uống
chén rượu để giải sầu, để tiễn đưa người thân lên đường đi xa.


Thông tin là một khái niệm trừu tượng, tồn tại khách quan,
có thể nhớ trong đối tượng, biến đổi trong đối tượng và áp dụng
để điều khiển đối tượng. Thông tin làm tăng thêm hiểu biết của


con người, là nguồn gốc của nhận thức. Thông tin về một đối
tượng chính là một dữ kiện về đối tượng đó, chúng giúp ta nhận
biết và hiểu được đối tượng. Thơng tin có liên quan chặt chẽ
đến khái niệm về độ bất định. Mỗi đối tượng chưa xác định
hồn tồn đều có một độ bất định nào đó. Tính bất định này
chưa cho biết một cách chính xác và đầy đủ về đối tượng đó.


Ðộ bất định có liên quan chặt chẽ đến khái niệm xác suất
-độ đo khả năng có thể xảy ra của sự kiện (biến cố). Nếu một
biến cố không bao giờ xảy ra, xác suất của nó có giá trị bằng 0.
Nếu có một biến cố chắc chắn xảy ra, xác suất của nó bằng 1.
Ðại lượng xác suất có giá trị trong đoạn [0,1]. Xác suất đối
tượng A trú ngụ ở đâu trong 9 địa bàn (4 quận và 5 huyện) của
Hà Nội trước khi có thơng tin bổ sung là 1/9, cịn sau đó là 1/5.
Xác suất càng nhỏ thì độ bất định càng lớn. Thơng tin có thể đo
được. Giả sử sự kiện có thể tồn tại ở một trong số n trạng thái
được đánh số 1, 2,..., n trong đó trạng thái i xuất hiện với xác
suất là Pi (0 < Pi < 1). C. Shannon, vào năm 1948, đã đưa ra


</div>
<span class='text_page_counter'>(6)</span><div class='page_container' data-page=6>

thái của sự kiện là như nhau (đồng xác suất: p1= p2= 1/2). Ðộ


bất định trong trường hợp này sẽ là log<i>2</i>2-1.


Trong máy tính, các thơng tin được biểu diễn bằng hệ đếm
nhị phân. Tuy chỉ dùng hai ký số là 0 và 1 mà ta gọi là bit
nhưng hệ nhị phân đã giúp máy tính biểu diễn - xử lý được trên
hầu hết các loại thông tin mà con người hiện đang sử dụng như
văn bản, hình ảnh, âm thanh, video, ...


<b>3. CÁC HỆ ĐẾM VÀ CÁC PHÉP TÍNH</b>


<b>3.1. Khái niệm hệ đếm & hệ đếm nhị phân</b>


Các chữ số cơ bản của một hệ đếm là các chữ số tối thiểu để
biểu diễn mọi số trong hệ đếm ấy.


<i>Ví dụ</i>


Hệ thập phân có các chữ số cơ bản: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.
Hệ nhị phân có các chữ số cơ bản: 0, 1.


Ðặc biệt hệ thập lục phân có các chữ số cơ bản được ký hiệu
là 0,…, 9, A, B, C, D, E, F. Nếu một số có giá trị lớn hơn các số
cơ bản thì nó sẽ được biểu diễn bằng cách tổ hợp các chữ số cơ
bản theo công thức sau:


<b>X = anan-1... a1a0</b> <b>= anb</b>
<b>n</b>


<b>+ an-1b</b>
<b>n-1</b>


<b>+... + a1b + a0</b> <b>(*)</b>
trong đó: b là cơ số hệ đếm,


a0, a1, a2,...., anlà các chữ số cơ bản


X là số ở hệ đếm cơ số b.
<i>Ví dụ</i>


</div>
<span class='text_page_counter'>(7)</span><div class='page_container' data-page=7>

<b>3.2. Chuyển đổi giữa các hệ đếm</b>


<i><b> Qui tắc 1 </b></i>


Ðể chuyển đổi một số từ hệ thập phân sang hệ có cơ số b (b
 10) ta áp dụng cách làm sau:


Lấy số thập phân chia cho cơ số b cho đến khi phần thương
của phép chia bằng 0, số đổi được chính là các phần dư của
phép chia theo thứ tự ngược lại.


<i>Ví dụ</i>


<i>Cho X = 610</i> <i>nghĩa là X = 6 trong hệ thập phân thì X sẽ </i>


<i>được đổi thành 1102trong hệ nhị phân.</i>


Cách đổi như hình sau


<i><b> Qui tắc 2 </b></i>


Ðể chuyển đổi một số từ hệ cơ số b về hệ thập phân ta sử
sụng công thức (*)


</div>
<span class='text_page_counter'>(8)</span><div class='page_container' data-page=8>

<b>2</b> <b>10</b> <b>2</b>


<b>3</b> <b>11</b> <b>3</b>


<b>4</b> <b>100</b> <b>4</b>


<b>5</b> <b>101</b> <b>5</b>



<b>6</b> <b>110</b> <b>6</b>


<b>7</b> <b>111</b> <b>7</b>


<b>8</b> <b>1000</b> <b>8</b>


<b>9</b> <b>1001</b> <b>9</b>


<b>10</b> <b>1010</b> <b>A</b>


<b>11</b> <b>1011</b> <b>B</b>


<b>12</b> <b>1100</b> <b>C</b>


<b>13</b> <b>1101</b> <b>D</b>


<b>14</b> <b>1110</b> <b>E</b>


<b>15</b> <b>1111</b> <b>F</b>


<i><b> Qui tắc 3 </b></i>


Ðể chuyển số từ hệ nhị phân về hệ thập lục phân ta thực
hiện như sau:


Nhóm lần lượt 4 bit từ phải sang trái, sau đó thay thế các
nhóm 4 bit bằng giá trị tương ứng với hệ thập lục phân (tra theo
bảng chuyển đổi trên).


<i>Ví dụ: X = 11’10112= 3B16</i>



<i><b> Qui tắc 4 </b></i>


</div>
<span class='text_page_counter'>(9)</span><div class='page_container' data-page=9>

<i>Ví dụ: X = 3B16= 0011’10112= 11’10112</i>


<b>4. TỔNG QUAN CẤU TRÚC CỦA MÁY TÍNH VÀ</b>
<b>CÁC THIẾT BỊ NGOẠI VI</b>


<b>4.1. Đơn vị xử lý trung tâm - CPU và bộ nhớ</b>
<b>4.1.1.</b> <b>Cách làm việc của CPU</b>


<i><b>Ðơn vị xử lý trung tâm (Central Processing Unit) - CPU</b></i>
là một mạch xử lý dữ liệu theo chương trình được thiết lập
trước. Nó là một mạch tích hợp phức tạp gồm hàng triệu
transitor trên một bảng mạch nhỏ. Phần lớn người dùng không
biết và cũng không cần biết đến cái gì trên CPU. Một CPU có
thể thi hành hàng triệu lệnh mỗi giây, để như vậy, trong một
CPU tiêu biểu phải có nhiều thành phần phức tạp với các chức
năng khác nhau hoạt động nhịp nhàng với nhau để hoàn thành
các tập lệnh chương trình. Ở đây chúng ta sẽ xem qua các thành
phần căn bản bên trong của một CPU.


</div>
<span class='text_page_counter'>(10)</span><div class='page_container' data-page=10>

<i><b>Ðơn vị giải mã - Decode unit: ra chỉ thị cho đường truyền </b></i>
đọc các lệnh được lưu giữ tại một địa chỉ bộ nhớ riêng biệt. Ðơn
vị này không chỉ định vị và nạp lệnh được thi hành kế tiếp mà
còn nạp cả các lệnh lần lượt sau nữa vào hàng chờ sẵn sàng hoạt
động.


Ðơn vị nối ghép đường truyền - Bus Interface Unit: bộ phận
dẫn truyền điều phối các thông tin.



Những nhà sản xuất vi xử lý luôn phát triển các kỹ thuật
<i>nhằm tăng tốc độ xử lý cho CPU. Và như vậy, bộ nhớ ẩn </i>
<i>-cache memory là một bộ nhớ nhỏ tốc độ cao đặt ngay bên trong</i>
bộ xử lý và nối trực tiếp với mạch xử lý để lưu trữ các lệnh
chuẩn bị được thực hiện, hay các lệnh thường xuyên được dùng
để sẵn sàng cho CPU. Bộ nhớ này chỉ do bộ xử lý kiểm sốt,
người sử dụng khơng thể thâm nhập được, nhằm phục vụ cho
việc tăng tốc độ tính tốn của bộ xử lý. Loại cache memory
nằm ngay trong bản thân bộ xử lý thường được gọi là cache nội
hay cache sơ cấp - primary, hay còn gọi là cache L1 (cache
level 1). Loại cache memory nằm ngoài bộ xử lý thường được
gọi là cache ngoại hay cache thứ cấp - secondary cache, hay còn
gọi là cache L2 (cache level 2).


<i><b>Ðơn vị điều khiển - control unit: có nhiệm vụ thông dịch </b></i>
các lệnh của chương trình và điều khiển hoạt động xử lý, được
điều tiết chính xác bởi xung nhịp đồng hồ hệ thống.


<i><b>Mạch xung nhịp hệ thống - system clock: dùng để đồng bộ </b></i>
các thao tác xử lý trong và ngồi CPU theo các khoảng thời
gian khơng đổi, khoảng thời gian chờ giữa hai xung gọi là chu
kỳ xung nhịp. Tốc độ theo đó xung nhịp hệ thống tạo ra các
xung tín hiệu chuẩn thời gian gọi là tốc độ xung nhịp - tốc độ
đồng hồ tính bằng triệu đơn vị mỗi giây - Mhz.


</div>
<span class='text_page_counter'>(11)</span><div class='page_container' data-page=11>

<b>4.1.2.</b> <b>Lưu trữ sơ cấp: Bộ nhớ máy tính</b>


Cơng việc chính của CPU là thi hành các mã lệnh của
chương trình, nhưng trong cùng thì CPU chỉ có khả năng giải


quyết một ít trong phần dữ liệu. Như vậy phần còn lại của dữ
liệu được đọc vào phải cần một chỗ nào đó để lưu giữ lại sẵn
sàng cho CPU xử lý, và RAM hay bộ nhớ chính sẽ nhận nhiệm
vụ này.


<i><b>Bộ nhớ truy cập ngẫu nhiên - Random Access Memory</b></i>
<b>(RAM): là loại thiết bị lưu trữ sơ cấp. Chip RAM gồm nhiều </b>
mạch điện tử có chức năng lưu trữ các lệnh và dữ liệu chương
trình một cách tạm thời. Chính thuật ngữ truy cập ngẫu nhiên
cũng cho thấy tính chất của loại bộ nhớ này. Mỗi vị trí lưu trữ
trong RAM đều có thể truy cập trực tiếp, nhờ đó các thao tác
truy tìm và cất trữ có thể thực hiện rất nhanh. Nội dung lưu trữ
<i>trong RAM không cố định - volatile memory, có nghĩa phải </i>
<i>ln có nguồn ni để lưu trữ nội dung thơng tin đó - mất điện </i>
<i>là mất tất cả.</i>


</div>
<span class='text_page_counter'>(12)</span><div class='page_container' data-page=12>

<b>4.1.3.</b> <b>Cách làm việc của bộ nhớ </b>


<i><b>Bộ nhớ (Memory): là một mạch tích hợp phức tạp gồm </b></i>
hàng triệu tế bào nhớ (storage cell) - các tế bào nhớ này chính là
đơn vị lưu dữ kiện. Các thơng tin trong bộ nhớ có thể là tập lệnh
chương trình hay là dữ liệu của hình ảnh, các con số của phép
tính số học hay luận lý và cũng có khi là các ký tự chữ cái. Mỗi
byte bộ nhớ đều có địa chỉ riêng để CPU có thể truy cập đến dữ
liệu trong đó. Bộ nhớ có nhiều loại với đặc điểm cấu trúc tính
năng sử dụng khác nhau, nhưng về căn bản đều dùng để lưu dữ
kiện nhằm phục vụ cho việc xử lý thông tin của CPU, và nó có
thể là loại nằm ngay trên CPU hay nằm ngồi CPU.


Một máy tính cá nhân bình thường ngày nay thường lắp từ


64 đến 256 megabytes bộ nhớ - bộ nhớ được nói đến trong câu
này có nghĩa là loại bộ nhớ ngồi CPU mà ta thường gọi là các
thanh RAM.


Các vi mạch DRAM được kết nối với nhau trên một bản
mạch nhỏ được gọi là RAM, có khi là SIMM (single in - line
memory module) - module nhớ hàng chân kép. Tùy lượng vi
mạch nhớ và cấu trúc, các SIMM hay DIMM có thể có dung
lượng từ 1 MB đến 32 MB hoặc hơn; các thế hệ cũ thì có 30
chân (thường dùng từ các máy 486DX trở về trước), thế hệ
thông dụng hiện nay dùng loại 72 chân (từ 486DX cho tới các
máy hiện đại nhất). Đã xuất hiện loại DIMM - SDRAM có tốc
độ lý thuyết 10ns (so với RAM EDO là 60ns), có số chân là 168
chân cũng được dùng rộng rãi với một số bo mạch chọn lọc.
Các RAM này được cắm vào các khe quy định sẵn trên mạch hệ
thống chính.


Xét về chi tiết thì nơi nhớ - tế bào nhớ giống như một cái
hộp thư. Một hộp thư hiện đại cho một địa chỉ có thể lưu giữ
một byte thông tin.


</div>
<span class='text_page_counter'>(13)</span><div class='page_container' data-page=13>

Khi khởi động máy, CPU tự động (đã qui định trước) đọc
thông tin lưu trong bộ nhớ chỉ đọc - ROM và thi hành. Hầu hết
các hệ thống máy tính đều có ROM để lưu dữ kiện để điều
khiển hệ thống. Các chương trình trên ROM thường được gọi là
<i>BIOS - hệ thống xuất nhập cơ sở.</i>


Các lệnh cần thực hiện nào đã nạp vào bộ nhớ thì CPU có
khả năng thực hiện chúng.



Như vậy, khi bật máy, CPU đọc thơng tin trên bộ nhớ ROM
- thi hành nó, sau đó đọc đến thơng tin trên đĩa khởi động và
nạp các thông tin hệ điều hành trên đĩa vào bộ nhớ RAM. Các
thông tin lưu trên RAM ở các tế bào nhớ, tức là nằm sẵn trong
RAM - và CPU có thể thực hiện các tác vụ.


<b>4.2. Thiết bị nhập</b>
<b>4.2.1.</b> <b>Bàn phím</b>


Ðể thể hiện những lá thư, những con số, hay các ký tự đặc
biệt bằng máy tính, người ta dùng bàn phím nối với máy tính,
kích hoạt ứng dụng thích hợp rồi gõ các phím nào cần gõ cho ra
các từ, câu muốn có. Khi bạn gõ - nhấn một ký tự nào trên bàn
phím, trên màn hình sẽ hiện ra chữ ấy (giả định đang trong trình
ứng dụng thích hợp). Các phím mũi tên, Alt, Ctrl, Enter…
khơng gửi một chữ nào cho máy mà là các lệnh đặc biệt nào đó.


</div>
<span class='text_page_counter'>(14)</span><div class='page_container' data-page=14>

lưỡng về mặt ngôn ngữ học về tần suất xuất hiện của các chữ
cái, dựa vào đó đưa ra một thứ tự sao cho những chữ cái hay
dùng nhất ở vị trí phím dễ dùng nhất.


<b>4.2.2.</b> <b>Thiết bị chỉ điểm - Pointing Device</b>


Hàng triệu người dùng máy tính hiện nay dùng bàn phím để
gõ các chữ cái và con số, nhưng để ra lệnh cho máy, định vị con
trỏ, họ khơng chỉ dùng bàn phím mà cịn dùng một thiết bị đặc
biệt thông dụng khác gọi là: con chuột - mouse. Con chuột dùng
để chuyển dịch một ký hiệu hay một đối tượng được chọn từ
nơi này sang nơi khác trên màn hình. Con chuột thường được
thể hiện thông qua con trỏ trên màn hình. Khi người sử dụng di


chuyển con chuột trên mặt bàn thì con trỏ cũng di chuyển trên
màn hình.


Một con chuột có một, hai, hay ba nút nhấn có thể dùng để
gởi các tín hiệu đến máy tính. Nhiều người dùng không quan
tâm đến con chuột - cũng chẳng sao, nhưng ngày càng nhiều
các chương trình ứng dụng đặt con chuột vào vị trí quan trọng
để điều khiển chương trình. Cũng như nhiều linh kiện khác,
chuột cũng có nhiều chủng loại với cấu tạo và điểm mạnh yếu
khác nhau nhưng cùng có chung nhiệm vụ.


<i><b>Con chuột chuẩn: gồm các nút nhấn ở trên và một hịn bi ở </b></i>
dưới, nó có cấu tạo nhỏ gọn nối máy tính bởi một sợi dây, có
thể dịch chuyển dễ dàng và đó cũng là nhiệm vụ của nó.


<i><b>Con chuột bóng - Trackball: nó cũng gồm các thành phần </b></i>
như trên, nhưng viên bi lại hướng lên trên. Thường được chế
tạo to lớn khó di chuyển chuột được, tác vụ di chuyển chuột
thực hiện trực tiếp bằng chính người sử dụng dùng tay lăn viên
bi, nút nhấn vẫn không thay đổi chức năng.


</div>
<span class='text_page_counter'>(15)</span><div class='page_container' data-page=15>

Một vài thiết bị đặc biệt khác cũng được xem là các thiết bị
chỉ điểm, ví dụ như:


<i><b>Cần điền khiển - Joystick: cũng được xem là thiết bị tính </b></i>
năng chỉ điểm đặc biệt, nó giống như cần điều khiển trong máy
trị chơi điện tử.


<i><b>Màn hình cảm ứng - Touch Screen: màn hình thiết kế đặc </b></i>
biệt để có thể cảm nhận được sự chỉ điểm của ngón tay hoặc vật


gì đó đối với màn hình.


<i><b>Bàn vẽ - Graphic table: là một thiết bị đặc dụng dành cho</b></i>
những nhà thiết kế hay họa sỹ, bàn vẽ càng tốt thì độ nhạy cảm
về áp lực trên nó càng cao. Bàn vẽ sẽ chuyển trực tiếp những
hình ảnh được vẽ trên bàn vẽ thành các hình ảnh trên máy tính.
<b>4.2.3.</b> <b>Thiết bị đọc </b>


Một số các thiết bị đọc bị giới hạn bởi khả năng đưa dữ liệu
- văn bản trực tiếp trên giấy, hay chuyển các thông tin đã được
in ra cho máy tính xử lý. Một số thiết bị nhập khác (được gọi là
thiết bị đọc) đã được chế tạo nhằm đáp ứng cho những nhu cầu
thực tế này:


</div>
<span class='text_page_counter'>(16)</span><div class='page_container' data-page=16>

đặc biệt trên vùng dành riêng cho chúng, thường dùng cho các
thẻ bán hàng hay thẻ tín dụng. Người ta dùng các thiết bị này
rất nhiều trong các cửa hàng, các nơi thanh toán chuyển đổi
tiền, nối với một thiết bị đầu cuối POS (điểm bán - point of
sale). Thiết bị đầu cuối (Terminal) này sẽ gửi thông tin nhận từ
cây đũa thần đến một máy tính (có thể là một mainframe), máy
tính này sẽ xác định cơ sở dữ liệu cần thiết phù hợp (giá cả,
cước thuế, số tiền phải trả cho món hàng…) và gởi lại thơng tin
ấy cho POS. Ðó là một trong các trường hợp ứng dụng, nguyên
tắc làm việc cũng tương tự với thẻ tín dụng.


<i><b>Cây viết máy tính - pen-based computer: như phần trước có </b></i>
nói đến, trong các loại máy hệ xách tay có loại nhỏ gọn nhất có
<i>thể bỏ vào áo khốc - loại trợ lý kỹ thuật số hay cịn gọi là Máy</i>
<i>thơng tin cá nhân (personal digital assistant - personal</i>
<i>comunicatior) nó dùng một cây viết để đưa dữ liệu vào máy</i>


<i>tính, thiết bị này là Cây viết máy tính - pen-based computer. Ðể </i>
nhập liệu, người ta viết trực tiếp lên màn hình phẳng của máy
tính.


Xét về trường hợp nhập liệu trực tiếp từ giấy tờ văn bản đã
nói ở trên cịn phương pháp dùng chương trình nhận dạng chữ.
Chương trình này chuyển các hình ảnh của văn bản đưa vào
máy tính bằng máy quét ảnh thành các ký tự chữ cái, độ chính
xác của các chương trình này khoảng hơn 99% với ngơn ngữ
chỉ có các ký tự Latin.


<b>4.2.4.</b> <b>Các thiết bị số hóa thế giới thực</b>


</div>
<span class='text_page_counter'>(17)</span><div class='page_container' data-page=17>

kỹ thuật số, thể hiện hình ảnh số thì dùng màn hình máy tính,
thể hiện ảnh ra giấy thì dùng máy in… và nhiều nhu cầu khoa
học khác dùng các thiết bị số hóa đặc biệt khác nữa. Nói chung
"cả thế giới thực của chúng ta đều có thể được số hóa".


<i><b>Máy quét ảnh - scanner: là một thiết bị nhập liệu có thể </b></i>
biến những hình ảnh thành những thơng tin số hóa đại diện cho
nó. Máy quét ảnh hiện nay có nhiều chủng loại và kích cỡ khác
nhau, thông dụng nhất là loại máy quét phẳng - flatbed scanner.
Còn loại máy quét cầm tay - handheld scanner, nhưng thay vì
viên bi định vị là bóng đèn chân khơng. Cịn một loại khác gọn
nhẹ thường được đặt giữa màn hình và bàn phím gọi là máy
qt phụ trợ – shet-fed scanner.


<i><b>Máy ảnh số – digital camera: cũng bằng phương pháp</b></i>
tương tự như scanner, máy ảnh số dùng để chụp hình ảnh bên
ngồi, thay vì lưu hình ảnh lên phim thì nó lưu ảnh dưới dạng


thơng tin số hóa. Khác với máy quét ảnh, máy ảnh số không bị
giới hạn bởi mặt phẳng hình ảnh, nó hồn tồn có thể chụp
được những hình ảnh mà máy ảnh thông thường chụp được.
Ảnh chụp từ máy ảnh số có thể được lưu trên đĩa hay loại thiết
bị lưu trữ nào đó tùy mỗi loại máy. Loại máy ảnh kỹ thuật số
này ngày càng trở nên rộng rãi hơn, nó đặc biệt hữu dụng trong
việc chụp những hình ảnh ở những nơi mang tính tơn nghiêm vì
hầu như nó không gây ra một tiếng động đáng kể nào.


</div>
<span class='text_page_counter'>(18)</span><div class='page_container' data-page=18>

các hệ máy mới là vô cùng phong phú, ngày nay hầu như bạn
<i>có thể bắt gặp dòng chữ âm thanh kỹ thuật số – digital audio</i>
trên hầu hết các thiết bị âm thanh hiện đại như máy đĩa CD
nhạc, CD video...


<i><b>Thiết bị cảm ứng: Trong các ứng dụng khoa học, các thiết </b></i>
bị cảm ứng được dùng rất nhiều để đưa dữ kiện bên ngồi vào
máy tính dưới dạng số hóa. Ðó là điều hiển nhiên bởi máy tính
chỉ xử lý được những thông tin dạng số. Ứng dụng thông
thường nhất là các thiết bị đong, đo như nhiệt kế điện tử, máy
dự báo thời tiết, thiết bị kiểm sốt mơi trường, thiết bị kiểm sốt
mức độ ơ nhiễm về âm thanh lẫn ô nhiễm về khơng khí và
nhiều ứng dụng khác nữa.


<b>4.3. Thiết bị xuất</b>


Máy tính nhận thơng tin, xử lý và phải xuất thông tin. Như
vậy nơi để nhận dữ liệu xuất ra sau khi xử lý gọi là bộ phận
xuất hay thiết bị xuất. Hiện nay người ta thường dùng hai thiết
bị xuất chủ yếu là màn hình và máy in.



<b>4.3.1.</b> <b>Xuất ra màn hình</b>


<i><b>Màn hình máy tính (tạm dịch từ Video Monitor) hay thiết </b></i>
<i>bị đầu cuối hiển thị hình ảnh (video display terminal - VDT) sẽ </i>
cho ta thấy những ký tự mà ta gõ trên bàn phím hoặc các thơng
điệp từ máy tính. Những thế hệ màn hình mới có thể thể hiện
chi tiết các hình ảnh cũng như chữ, số và các ký hiệu với đủ loại
màu sắc khác nhau, thường gọi là màn hình màu, tên gọi như
vậy để phân biệt loại màn hình đơn sắc dùng cho các hệ máy cũ
(loại máy XT).


</div>
<span class='text_page_counter'>(19)</span><div class='page_container' data-page=19>

cả màn hiển thị, tất cả lắp trong vỏ máy, người ta thường gọi
<i>monitor là màn hình.</i>


Màn hình có hai loại chính là: màn hình kiểu thiết kế giống
như tivi dùng các bóng đèn tia điện tử cathode CRT (cathode
<i>ray tube) và màn hình tinh thể lỏng LCD (liquid crystal</i>
<i>display). Tuy rằng LCD là loại màn hình phẳng nhỏ gọn hơn</i>
CRT nhiều, nhưng giá của LCD lại quá cao so với CRT. Các
màn hình CRT ngày nay cho chất lượng hình ảnh tốt hơn màn
hình LCD. Thơng thường người ta chỉ dùng LCD cho các máy
tính dạng xách tay. Màn hình CRT này về cơ bản gồm một
bóng đèn hình lớn chứa ba ống phóng điện tử cho ba màu đỏ,
xanh lá cây và xanh dương. Ba màu cơ bản này sẽ tạo ra được
mọi màu khác cần hiển thị. Mỗi điểm ảnh sẽ do ba yếu tố RGB
hợp thành tạo ra màu sắc cần thiết.


<i>Màn hình được nối kết với máy tính thơng qua bộ điều hợp </i>
<i>hiển thị - video adapter hay display adapter. Nó cịn có tên gọi </i>
<i>là cạc màn hình - display card, video card. Bộ điều hợp hiển thị </i>


là một bảng mạch điện tử được cắm trong máy tính ở khe cắm
mở rộng. Hình ảnh là thơng tin được lưu ở bộ nhớ màn hình
-VRAM. Khả năng của bộ điều hợp hiển thị sẽ quyết định tốc độ
làm tươi hình ảnh, tốc độ hiện hình, độ phân giải, mức độ màu
có thể hiển thị. Bộ điều hợp hiển thị được phân loại theo độ
rộng bus dữ liệu của nó:


</div>
<span class='text_page_counter'>(20)</span><div class='page_container' data-page=20>

Kích thước của màn hình cũng gần như một cái tivi. Thơng
số dùng để phân loại màn hình máy tính và tivi được quy định
giống nhau - là độ dài đo được của đường chéo màn hiển thị.
Một máy tính để bàn thơng thường có màn hình thừ 14 đến 15
inch. Hình ảnh hiện trên màn hiển thị là sự kết hợp của nhiều
<i>chấm nhỏ - gọi là điểm ảnh - pixel. Ðộ phân giải của màn hiển </i>
thị thông thường là 72 điểm trong một inch cho mỗi chiều
ngang và dọc. (Ðơn vị tính độ phân giải viết tắt là dpi - điểm
trong một inch: dots per inch) Ðộ phân giải càng cao, các điểm
ảnh càng sít lại với nhau, hình ảnh càng mịn hơn và đẹp hơn.


Cịn một cách nói khác về kích thước màn hình, thay vì nói
về độ dài đường chéo thực sự của màn hiển thị, người ta nói về
mức độ phân giải có thể của màn hiển thị. Nếu nói màn hình
800 x 600 tức là chiều ngang gồm 800 điểm, chiều dọc gồm
600 điểm.


Yếu tố khác nói về khả năng card màn hình là độ sâu màu
có thể hiển thị - color depth. Ví dụ như, màn hình đơn sắc thì
thể hiện 2 bit cho mỗi điểm, mỗi bit có thể hiển thị 2 màu hoặc
màu này hoặc màu kia (các màn hình đơn sắc ban đầu thường
có màu xám, xanh hay nâu). Nếu mỗi điểm có 8 bit màu thì có
khả năng thể hiện 256 màu - 28 - đây là khả năng thông thường


mà hầu hết tất cả các máy tính hiện nay đều thể hiện được. Loại
cao cấp hơn có thể chấp nhận 24 bit màu, tức khoảng hơn 16
triệu màu (16777216 màu - 224), hiện nay trên máy vi tính đã
có thể thể hiện 32 bit màu - chấp nhận 4.294.967.296 màu. Số
màu có thể hiển thị càng nhiều thì hình ảnh càng trung thực sắc
nét và sống động - và chắc chắn là đẹp hơn hình ảnh trên tivi
nhiều lần.


<b>4.3.2.</b> <b>Xuất ra giấy </b>


</div>
<span class='text_page_counter'>(21)</span><div class='page_container' data-page=21>

lưu trữ, bởi các bản in ra giấy. Máy in có nhiều loại và được
<i>chia thành hai nhóm chính: máy in gõ hay máy in không gõ</i>
(impact printer or nonimpact printer)


<i><b>Máy in gõ: là các máy in theo dòng hay theo ma trận điểm. </b></i>
Các máy in kim là loại này, có đặc điểm là tốc độ in chậm, ồn
ào, độ phân giải thấp cho chất lượng in ấn trung bình. Máy in
này dùng một đầu kim chạy suốt chiều ngang giấy để ấn các
kim xuống giấy (qua lớp băng mực) theo tín hiệu điểu khiển,
nhiều lần như vậy tạo nên bản in. Số đầu kim của máy càng cao
thì độ phân giải đạt được càng cao, các loại máy in 9,18 kim
hầu như khơng cịn được sử dụng nữa, thơng dụng nhất của máy
in loại này có lẽ là có thể in trên khổ giấy lớn mà giá máy rẻ và
có thể nhân thành nhiều bản bằng giấy than do sự gõ truyền lực.
<i><b>Máy in không gõ: là loại máy in như tên gọi của nó - khơng</b></i>
dùng tác động cơ tạo nên chữ mà bằng các kỹ thật hiện đại
khác.


</div>
<span class='text_page_counter'>(22)</span><div class='page_container' data-page=22>

-khi có điện áp điều -khiển tác động vào. Khi đặt trong ống dẫn
mực nó đẩy mực ra khỏi ống và hút thêm mực khác vào - như


một máy bơm. Một hình thái khác của máy in phun là máy in
phun bong bóng - bubbe jet printer: dùng phần tử nung nóng
thay cho tinh thể áp điện, bơm tinh thể có thể đóng mở tần số
5kHz nên có thể cho phép tốc độ in nhanh hơn. Loại này bị hạn
chế bởi tốc độ in, do các phần tử in phải có thời gian nguội nếu
không sẽ gây nhiều vấn đề phức tạp khác, nhưng ưu điểm dùng
điện áp thấp từ 24V đến 50V làm cho nó tiện dụng hơn. Do tính
chất in phun như vậy, nên loại máy này có thể dùng với mọi
loại giấy, độ nét và độ mịn của bản in có chất lượng cao, đơi khi
rất khó phân biệt với loại máy in laser. Loại máy in phun rẻ hơn
laser nhiều nhưng chi phí in cao hơn.


<i><b>Máy in laser: dùng công nghệ in tĩnh điện (electrostatic </b></i>
<i>-ES) là phương pháp in tạo hình ký tự bằng cách tạo ra điện tích </i>
tĩnh điện và làm chảy mực lên giấy nhờ q trình nung nóng.
Vậy khác hồn tồn với các loại máy in trước dùng đầu in để in,
loại máy in này tạo sản phẩm thông qua một quá trình phức tạp.
Quá trình in tĩnh điện thực hiện trong hệ thống tạo hình - image
formation system (IFS) có các bước: xóa trống nhạy sáng để gạt
bỏ các hạt mực cịn trên đó, và làm trống trở nên trung hịa điện
tích. Nạp điện lên bề mặt trống bằng điện áp âm rất lớn (khoảng
5000V) - sẵn sàng ghi hình. Máy in giải mã tín hiệu theo từng
dịng máy tính đưa sang và xây dựng bản đồ bit của trang in,
dùng chùm tia sáng ghi hình bản đồ này lên mặt trống. Mực
được phun vào mặt trống đang quay và bị hút vào các điểm
được chiếu sáng và nhiễm điện tích âm - phương pháp ghi hình
đen. Cịn nếu mực được phun vào các điểm khơng được chiếu
sáng gọi là phương pháp ghi hình trắng, cách này hình đen hơn,
dày hơn. Giấy được đưa qua một bộ phận nạp điện tích dương
trước khi đi qua trống để hút điện tích âm là các hạt mực. Sau


đó qua hệ thống ép nhiệt nóng 180o


</div>
<span class='text_page_counter'>(23)</span><div class='page_container' data-page=23>

cho máy in thơng thường có thể in được từ 200-5000 bản in tùy
độ phức tạp hình ảnh.


Một kỹ thuật mới thay thế tia laser trong cách ghi hình ảnh
là dùng thanh nhiều đèn hay dãy nhiều cửa đóng mở nguồn
sáng đèn huỳnh quang bằng tinh thể lỏng để chiếu sáng vào mặt
<i>trống... Ðó là loại máy in di-ốt phát quang - light emitting diode</i>
<i>printer và máy in cửa sập tinh thể lỏng - liquid crystal shutter</i>
<i>printer.</i>


<i><b>Máy in màu: hoạt động dựa trên nguyên tắc các điểm màu</b></i>
cơ bản li ti xen kẽ nhau tạo nên nhiều màu sắc phong phú. Ðể
thể hiện màu sắc theo nguyên tắc này có nhiều phương pháp
phối màu khác nhau.


</div>
<span class='text_page_counter'>(24)</span><div class='page_container' data-page=24>

tính - và là phương án in màu duy nhất đối với các máy in sách
báo hiện nay trên thế giới. Những máy in màu hiện nay dùng
<i>trong các văn phịng cơ quan hay gia đình thường là loại máy in</i>
<i>phun màu, máy in thăng hoa màu hay máy in truyền sáp nhiệt.</i>
Các loại máy in này có giá thấp phù hợp khả năng tài chính của
mọi người, thơng thường thì từ 300 đến 2000 USD. Các thế hệ
máy in phun màu mới hiện nay có khả năng in với độ phân giải
trên 1000 dpi sẽ làm cho hình ảnh mịn hơn và đẹp gần như ảnh
thật. Còn loại máy in laser màu không được phổ biến lắm do giá
khá cao, và thường chỉ trang bị cho các công ty thiết kế tạo
mẫu.


Hiện nay cịn có máy vẽ - plotter là một họ máy anh em với


máy in phun. Do kỹ thuật in phun ra đời nên ranh giới giữa máy
in phun màu khổ lớn và máy vẽ rất khó phân biệt. Loại máy in
này hầu như chỉ dùng ngơn ngữ in postscript có thể dùng để in
các bản vẽ thiết kế, hình ảnh, bản đồ lớn với khổ giấy A0 và


thích hợp với nhiều loại giấy. Với ngôn ngữ in cao cấp và các
thiết kế phun mực tiên tiến, hình ảnh in từ loại máy in này có
chất lượng khá cao.


<b>4.3.3.</b> <b>Xuất ra âm thanh </b>


</div>
<span class='text_page_counter'>(25)</span><div class='page_container' data-page=25>

Hiển nhiên để âm thanh phát ra cần phải có thêm một hay
nhiều loa, ngồi ra máy tính có thể nối với bộ khuếch đại, bộ
lọc âm thanh, micro, và cũng có thể là một cây đàn điện tử có
chuẩn MIDI. Những máy tính tiêu biểu hiện nay đều có gắn
thiết bị CD, với thiết bị này, bạn có thể nghe nhạc, hay xem
phim với hình ảnh đẹp và âm thanh chuẩn xác vơ cùng hấp dẫn.
Cịn với các chương trình dạy phát âm ngoại ngữ thì nghe như
người thật phát âm bên tai bạn vậy.


Âm thanh trong máy tính hiện nay chia thành hai dạng
MIDI và Wave. Loại âm thanh MIDI chỉ dùng để thể hiện âm
thanh của các loại nhạc cụ đã được số hóa (các nhạc cụ điện tử)
theo một bảng mã qui định sẵn, do đó kích thước tập tin dạng
này nhỏ hơn dạng Wave với cùng thời gian thể hiện. Còn Wave
dùng để thể hiện mọi thứ âm thanh mà ta có thể nghe và tổng
hợp được như tiếng hát, giọng nói, tiếng mèo kêu, xe máy...
<b>4.3.4.</b> <b>Làm việc với máy tính khác</b>


</div>
<span class='text_page_counter'>(26)</span><div class='page_container' data-page=26>

<b>4.4. Lưu trữ thứ cấp</b>



Máy tính có các thiết bị ngoại vi có khả năng nhận và xuất
dữ liệu - đó là các ổ đĩa máy tính, nơi ghi nhớ các thơng tin dữ
<i>liệu. Những thiết bị này gọi là các thiết bị lưu trữ thứ cấp </i>
<i>-secondary starage (thiết bị lưu trữ sơ cấp - primary storage là</i>
bộ nhớ máy tính). Khác với thiết bị lưu trữ sơ cấp khi ngắt điện
là mọi thứ trong RAM đều khơng cịn, thiết bị lưu trữ thứ cấp
này có thể lưu dữ kiện ngay cả khi khơng có nguồn ni, xét về
lý thuyết, dữ liệu trên loại này có thể tồn tại vĩnh viễn và có thể
được đọc, ghi, sửa hay xóa lúc này hay lúc khác. Có hai phương
pháp lưu dữ kiện tạo nên hai họ khác nhau là dựa trên từ tính và
dựa trên khả năng ứng dụng quang học.


<b>4.4.1.</b> <b>Ðĩa từ tính </b>


Có hai loại chủ yếu là đĩa mềm và đĩa cứng. Ðĩa mềm, có
thể hiểu đơn giản là loại đĩa dung lượng thấp, nhỏ gọn tháo lắp
dễ dàng, nhiều đĩa dùng chung một ổ đĩa. Hiểu như vậy để có
thể phân biệt với đĩa cứng là loại ổ đĩa thường lắp hẳn bên trong
máy, ít được tháo rời, phức tạp, và bản thân nó là thiết bị hoàn
chỉnh đọc ghi với dung lượng lớn.


<b>4.4.2.</b> <b>Ðĩa mềm - floopy disk</b>


</div>
<span class='text_page_counter'>(27)</span><div class='page_container' data-page=27>

gần như khơng cịn được dùng nữa. Ðĩa mềm có tính cơ động
cao, nhưng bị hạn chế về dung lượng nhớ, hiện nay các chương
trình hầu như không thể chạy trên đĩa mềm như cách đây
khoảng 5 năm, cho nên đĩa mềm chủ yếu dùng sao lưu dữ liệu,
vả lại tốc độ đọc ghi của đĩa mềm rất thấp - bù lại giá đĩa mềm
tương đối rẻ, bạn có thể mua một hộp đĩa mềm với giá khoảng


50.000 đồng (10 hay 11 đĩa).


<i><b>Ðĩa cứng - Hard disk</b></i>


</div>
<span class='text_page_counter'>(28)</span><div class='page_container' data-page=28>

năm 1983 dùng phương pháp mã hóa RLL, tốc độ có thể đạt
đến khoảng 24MB mỗi giây, là dạng giao tiếp câm nên các điều
khiển quan trọng đều do card quản lý. Chuẩn IDE (Intelligent
Drive Electronic - Intergrated Drive Electronic) cũng còn gọi là
ATA (AT Attachment) dùng loại mạch điện tử ổ đĩa thông
minh, là giao tiếp ở mức hệ thống. Chuẩn này nối với máy bằng
một cáp nguồn 4 chân và một cáp dữ liệu 40 chân. Loại ổ đĩa
này có tốc độ khá cao nên được dùng trong hầu hết các máy vi
tính hiện nay, giá thành cũng rẻ hơn so với các loại ổ đĩa cứng
khác. Chuẩn giao tiếp SCSI (Small Computer System Interface)
là một cấu trúc bus độc lập có thể truyền dữ liệu với tốc độ cao,
từ 4Mb/giây đến khoảng 10Mb/giây, được ứng dụng với ổ đĩa
cứng tạo nên một khả năng lưu trữ cao với tốc độ đọc ghi cao.
Ðể dùng được, cần có một bảng mạch điều hợp SCSI, tuy nhiên
một card SCSI này có thể nối tiếp đến 7 thiết bị theo chuẩn này.


<i><b>Ðĩa floptical</b></i>


Là loại ổ đĩa từ mềm, có hình dáng giống như đĩa 3.5 inch,
nhưng dùng phương pháp định vị quang học để đọc ghi, nên
mật độ dữ liệu trên đĩa cao hơn, dung lượng nhớ lớn hơn. Thiết
bị này không ghi dữ liệu bằng quang học, chỉ làm thao tác định
vị thơi. Tuy nhiên do giá thành cao nên dù có khả năng lưu đến
hơn 20MB, loại này vẫn không phổ dụng.


<i><b>Ổ băng ghi lưu</b></i>



</div>
<span class='text_page_counter'>(29)</span><div class='page_container' data-page=29>

<i><b>Ổ đĩa tháo lắp ZIP</b></i>


Dùng loại đĩa có kích thước cũng khoảng 3.5 inch, dung
lượng lên đến 100Mb trên một đĩa. Tốc độ đọc ghi trung bình,
kỹ thuật dùng ở đây là định vị quang học để ghi dữ liệu. Nếu
dùng với card SCSI, tốc độ khơng thua gì ổ cứng IDE.


<b>4.4.3.</b> <b>Ðĩa từ quang </b>


<i>Ðĩa từ quang - Magneto optical drive, thường gọi tắt là</i>
MO, là thiết bị kết hợp giữa từ tính và quang học để lưu dữ liệu.
Ðĩa từ tính, dùng ánh sáng laser làm tác nhân đọc ghi. Dung
lượng của loại 5.25 inch là 1.3GB, loại 3.5inch là 230MB. Công
nghệ này phù hợp để lưu trữ, theo các chuyên gia, có thể bảo
đảm dữ liệu 50 năm so với 5 năm của ổ đĩa cứng, ổ mềm, băng
từ.


<b>4.4.4.</b> <b>Ðĩa quang học</b>


</div>
<span class='text_page_counter'>(30)</span><div class='page_container' data-page=30>

thể đưa vào loại đĩa quang giá rẻ 680MB như chúng ta dùng
rộng rãi hiện nay, đồng thời các loại đĩa âm thanh cũng có thể
đọc hiểu và hoạt động được bằng ổ đĩa CD của máy tính, nhưng
đầu đọc của máy CD âm thanh thì khơng thể đọc được đĩa CD
dữ liệu. Nói là CD-ROM - chỉ đọc, nhưng dĩ nhiên là phải có
một lần nào đó ghi dữ liệu lên đĩa rồi mới đọc, thao tác này theo
nguyên tắc khắc trên đĩa các điểm lõm hay không lõm đại diện
cho số 0, 1 bằng một nguồn phát tia laser công suất lớn. Người
ta tạo một đĩa gốc trước trên nguyên tắc này bằng đầu CD có
thể ghi trên một đĩa CD mới, sau đó âm bản của đĩa gốc được


tạo ra bằng quá trình mạ điện hoặc photopolymer. Tiến trình
nhân bản thực hiện bằng cách phun polycarbonate - trong suốt,
nhẹ, bền, ổn định, không nhiễm bẩn - nên đĩa CD giữ được
thông tin gần như vĩnh viễn.


Như vậy, bạn có thể hiểu về bản chất các đĩa CD được chép
lại bán ở một số dịch vụ tin học thực ra là một dạng đĩa gốc, do
đó khi sử dụng phải tuyệt đối cẩn thận vì nó khơng hề có một
lớp bảo vệ polycarbonate như các đĩa CD được phát hành chính
quy hay các đĩa CD nhạc.


Khi mà các đĩa CD-ROM đã gần như trở nên một chuẩn
không thể thiếu trong hầu hết các máy tính multimedia thì lại
xuất hiện một thành viên mới trong họ đĩa quang học mà được
dự đoán sẽ là thiết bị lưu trữ chủ đạo thế kỷ 21 - DVD.


</div>
<span class='text_page_counter'>(31)</span><div class='page_container' data-page=31>

hồng ngoại. Quan trọng nhất là kỹ thuật DVD cho phép loại đĩa
có hai lớp trên một mặt, nên với mỗi lớp khoảng hơn 4GB thì
loại đĩa hai lớp hai mặt hồn tồn có thể chứa đến 17GB dữ
liệu.


<b>4.4.5.</b> <b>Ðường truyền – cổng – thiết bị ngoại vi</b>
Trong một máy tính thơng thường, CPU và bộ nhớ được
gắn với bo mạch chính cùng một vài linh kiện cần thiết khác
nữa. Những thông tin chuyển qua lại giữa các linh kiện thông
<i>qua một mạch lưới gọi là các bus. Các bus này có thể có 8, 16 </i>
hay 32 đường dẫn và do đó gọi là các bus 8 bit, bus 16 bit hay
bus 32 bit. Hiển nhiên rằng xa lộ đa luồng làm tăng lưu lượng
xe có thể chạy qua, ở đây cũng có thể các bus chấp nhận số bit
lớn thì càng có thể chuyển tải nhiều thông tin cùng một lúc, như


vậy sẽ làm tăng đáng kể tốc độ hệ thống.


</div>
<span class='text_page_counter'>(32)</span><div class='page_container' data-page=32>

xuất đưa ra bus ISA mở rộng cho máy AT dùng vi xử lý 80286
- tức là máy 286 với bus dữ liệu 16bit. Bus này gồm hai đoạn
khe cắm rời nhau, một đoạn 62 chân như kiểu dùng cho XT,
một đoạn bổ sung 36 chân - bổ sung 5 dịch vụ ngắt, 8 đường dữ
liệu, 4 đường địa chỉ và một số đường chức năng điều khiển.
Loại này vẫn tương thích với 8 bit. Tốc độ truyền loại này đạt
khoảng 8MB mỗi giây (ISA - Industry Standard Architecture).


<i><b>Bus MCA (Micro Chanel Architecture)</b></i>


Năm 1987, bus này được đưa ra riêng cho loại máy PS/2
của IBM, nó là kiểu thiết kế bus 32bit. Nó gồm 32 bit dữ liệu,
32 đường địa chỉ (có khả năng địa chỉ hóa 4GB bộ nhớ), một
kênh âm thanh, khả năng VGA cài sẵn. Tốc độ của nó đạt
20MB mỗi giây nên có thể đáp ứng cho các CPU đến 199MHz.
Tuy nhiên, do loại này khơng tương thích với bus AT và máy
PC nên nếu muốn dùng, người dùng phải thay toàn bộ các thiết
bị tương thích MCA nên khơng được hưởng ứng. Do đó nó
khơng được phát triển và cuối cùng IBM phải tự hủy bỏ.


<i><b>Bus EISA (Enhanced ISA)</b></i>


Là loại bus mở rộng AT được nâng cao do liên minh 9 công
ty lớn (AST, Compaq, Epson, Hewlett - Packard, NEC, Olivetti,
Tandy, Wyse, Zenith Data System) cùng hợp tác phát triển. Nó
được thiết kế để cạnh tranh với các MCA và đã thành cơng
trong thời gian dài. Nó hồn tồn tương thích với ISA - 16bit và
ISA - 8bit của XT. Bus EISA có tốc độ 33MB mỗi giây hoạt


động với 8.33MHz. EISA cịn có một phiên bản mới nâng cấp
tốc độ lên 132MB mỗi giây, loại này vẫn còn dùng trong một số
server và mạng.


<i><b>Local bus</b></i>


</div>
<span class='text_page_counter'>(33)</span><div class='page_container' data-page=33>

<i>-Video Electronics Standard Association). Nếu bo mạch chính </i>
33MHz thì tốc độ bus có thể đạt 107MB mỗi giây, tuy nhiên
hầu hết các bo mạch cùng có VESA Local Bus và ISA.


<i><b>Bus mở rộng PCI</b></i>


Loại này có 32 bit hay 64 bit dựa vào thiết kế do Intel xây
dựng năm 1992. PCI-Peripheral Component Interface bus, là
kiểu trung gian giữa bus dữ liệu ngoài của vi xử lý và bus vào
ra chung của máy tính, nó là loại bus mở rộng hồn chỉnh nên
nó cho phép các nhà sản xuất hồn tồn có thể loại bỏ hẳn loại
bus ISA.


Thiết bị ngoại vi là các thiết bị giúp máy tính liên thơng
được với thế giới bên ngồi. Bàn phím nối liên kết người dùng
và máy tính để nhập liệu, màn hình-máy in sẽ thể hiện kết quả
xử lý của máy tính sau các tác vụ gửi cho người dùng, ngồi ra
cịn vơ số các thiết bị khác như máy quét ảnh, máy ảnh số… mà
chúng ta đã làm quen ở các phần trên.


</div>
<span class='text_page_counter'>(34)</span><div class='page_container' data-page=34>

<b>CHƯƠNG 2</b>



<b>TỔNG QUAN VỀ GIẢI QUYẾT VẤN ĐỀ </b>


<b>BÀI TỐN TRÊN MÁY TÍNH</b>




<b>1. KHÁI NIỆM VẤN ĐỀ-BÀI TỐN</b>


Khi nào chúng ta phải suy nghĩ? Có thể thấy ngay là khi
phải trả lời câu hỏi của giáo viên, làm một bài toán hoặc giải
quyết một vấn đề như mua gì tặng bạn ngày sinh nhật…


Có thể nói, mọi cá nhân cũng như mọi cộng đồng xã hội
phải liên tục giải quyết những vấn đề và bài tốn đặt ra trong
q trình tồn tại và phát triển. Cuộc sống là một chuỗi vấn đề
mà ta phải nói: “Thơng thường, nhiều người quan niệm vấn đề
có nghĩa rộng hơn bài tốn và bài tốn là một loại vấn đề mà để
giải quyết phải liên quan ít nhiều đến tính tốn: bài tốn trong
vật lý, hóa học, xây dựng, kinh tế… Cho nên từ vấn đề vẫn
thường được dùng với nghĩa rộng hơn trong toán học”.


Nhà toán học cổ Hy Lạp Pitago đã phân chia mọi vấn đề mà
con người phải giải quyết thành hai loại:


<b>+ Theorema là vấn đề cần được khẳng định tính đúng-sai.</b>
Chúng ta thường quen với loại vấn đề này qua việc chứng minh
các định lý trong toán học, đặc biệt là hình học.


<b>+ Problema là vấn đề cần tìm giải pháp để đạt được một </b>
mục tiêu xác định từ những điều kiện ban đầu nào đó. Các ví dụ
minh họa điển hình cho loại bài tốn này là bài tốn dựng hình,
tổng hợp hóa chất, tìm đường đi ngắn nhất, thi cơng cơng trình
nhanh nhất, mua sắm tiết kiệm nhất…


</div>
<span class='text_page_counter'>(35)</span><div class='page_container' data-page=35>

<b>A →B</b>


Ở đây:


- A có thể là giả thiết, điều kiện ban đầu
- B có thể là kết luận, mục tiêu cần đạt.
-<b>→</b>là suy luận, giải pháp cần xác định


Theo sơ đồ này, việc cho một vấn đề - bài tốn có nghĩa là
cho A và B. Việc giải quyết vấn đề - bài tốn có ý nghĩa là xuất
phát từ A dùng một số hữu hạn các bước suy luận có lý hoặc
hành động thích hợp để đạt được B. Để cho việc giải quyết vấn
đề - bài toán được xác định cũng phải chỉ ra tập các thao tác cơ
bản được dùng trong suy luận hoặc hành động, nghĩa là những
điều kiện ràng bược đối với yếu tố “→” trong sơ đồ đã nêu. Đối
với tin học sơ đồ này được hiểu với nghĩa A là Input (thông tin
vào), B là Output (thơng tin ra) và <b>→là chương trình tạo thành</b>
từ các lệnh cơ bản của máy cho phép biến đổi A thành B.


Như ta đã thấy, chương trình chỉ là một cách mã hóa lại
thuật toán hoặc thuật giải đã được xây dựng để giải quyết vấn
đề - bài toán đã cho.


</div>
<span class='text_page_counter'>(36)</span><div class='page_container' data-page=36>

Khi một người khơng biết số ngun dương, số thực là gì…
thì khơng hiểu được bài tốn chứ chưa nói đến việc tìm cách
giải.


+ Thơng báo về các điều kiện đặt ra cho cách giải (→)
thường được nêu ra trong bài toán hoặc vấn đề. Đối với các bài
toán trong sách thì thường được hiểu ngầm được phép dùng mọi
kiến thức về tốn đã học cho tới phần đó của giáo trình.



Có thể nói: thuật tốn hay thuật giải cung cấp đủ lượng
thông tin (không thừa không thiếu) để giải quyết vấn đề - bài
tốn. Chính vì những lý do nêu trên, hiện nay để giải một vấn
đề trên máy tính, việc thiết kế xây dựng thuật giải vẫn chủ yếu
được thực hiện bởi con người. Từ những thông tin được phản
ánh rõ ràng hoặc tiềm ẩn trong các thông báo A, B hoặc “→”,
cùng với các tri thức liên quan có trong đầu người giải quyết
vấn đề - bài toán sẽ được kiến tạo nên thuật toán hay thuật giải
cần thiết. Đây là cơng việc có tính trí tuệ cao và quyết định sự
thành công của việc giải quyết vấn đề - bài toán được đặt ra.


</div>
<span class='text_page_counter'>(37)</span><div class='page_container' data-page=37>

chất là một cơ sở tri thức về lĩnh vực vấn đề cần giải quyết được
kết hợp với một chương trình suy diễn để tạo sinh được thuật
toán hay thuật giải cần thiết. Những hệ giải quyết vấn đề dựa
trên cơ sở tri thức mở rộng hơn cùng với các chương trình “tư
duy” mạnh hơn đang được phát triển và ứng dụng trong rất
nhiều lĩnh vực. Những hệ này thường được gọi là hệ chuyên gia
hay hệ cơ sở tri thức.


<b>2. CÁC BƯỚC GIẢI QUYẾT VẤN ĐỀ BÀI TỐN</b>
<b>BẰNG MÁY TÍNH</b>


Việc sử dụng máy tính điện tử (MTÐT) để giải quyết một
vấn đề nào đó thường được quan niệm một cách khơng chuẩn
xác, đơn giản đó chỉ là việc lập trình thuần túy. Thực ra, đó là
cả một quá trình phức tạp bao gồm nhiều giai đoạn phát triển
mà lập trình chỉ là một trong các giai đoạn đó (thậm chí chưa
chắc đã là phần việc quan trọng nhất). Các bước quan trọng của
toàn bộ quá trình được liệt kê dưới đây:



<b> Bước 1. Xác định vấn đề - bài toán</b>


</div>
<span class='text_page_counter'>(38)</span><div class='page_container' data-page=38>

Tùy theo nhu cầu cụ thể mà lựa chọn phương pháp thích hợp.
Việc lựa chọn trên cũng cần căn cứ vào khả năng xử lý tự động
mà ta sẽ sử dụng.


<b> Bước 3. Xây dựng thuật tốn hoặc thuật giải</b>


Xây dựng mơ hình chặt chẽ, chính xác hơn và chi tiết hóa
hơn phương pháp đã lựa chọn. Xác định rõ ràng dữ liệu vào, ra
cho các bước thực hiện cơ bản và trật tự thực hiện các bước cơ
bản đó. Nên áp dụng phương pháp thiết kế có cấu trúc, từ thiết
kế tổng thể tiến hành làm mịn dần từng bước.


<b> Bước 4. Cài đặt chương trình</b>


Mơ tả thuật giải bằng chương trình. Dựa vào thuật giải đã
được xây dựng, căn cứ quy tắc của một ngôn ngữ lập trình để
soạn thảo ra chương trình thể hiện giải thuật thiết lập ở bước 3.


<b> Bước 5. Hiệu chỉnh chương trình</b>


Ở bước 4, nói chung chúng ta khơng tránh khỏi sai sót. Ở
bước 5 này chúng ta cho chương trình chạy thử để phát hiện và
điều chỉnh các sai sót nếu tìm thấy.


<b>Có hai loại lỗi:</b>


<b>- Lỗi cú pháp: là lỗi do không tuân thủ đúng các quy tắc </b>
viết chương trình trên một ngơn ngữ lập trình cụ thể.



<b>- Lỗi ngữ nghĩa: là lỗi làm sai lạc ý nghĩa hoặc dẫn đến bế </b>
tắc của chương trình.


Lỗi cú pháp thường dễ phát hiện và hiệu chỉnh hơn lỗi ngữ
nghĩa. Cần phải nói rằng, việc hiệu chỉnh chương trình khá
phức tạp, mất nhiều thời gian và công sức. Việc xây dựng tốt,
phù hợp, đầy đủ các bộ dữ liệu để kiểm chứng chương trình là
hết sức quan trọng, giúp phát hiện ra các lỗi ngữ nghĩa của
chương trình cũng như có thể có vấn đề gì đó bị bỏ sót.


</div>
<span class='text_page_counter'>(39)</span><div class='page_container' data-page=39>

Cho máy tính thực hiện chương trình. Tiến hành phân tích
kết quả thu được. Việc phân tích kết quả nhằm khẳng định kết
quả đó có phù hợp hay khơng. Nếu khơng, cần kiểm tra lại toàn
bộ các bước một lần nữa. Nói chung, dù thận trọng đến mức
nào đi nữa thì sau mỗi bước thực hiện nêu trên cũng không
khẳng định được kết quả thực hiện từng bước là đúng đắn tuyệt
đối. Hơn nữa, như ở bước 5, ta chỉ hiệu chỉnh tất cả các lỗi đã
được phát hiện. Cịn có thể có sai sót khác của chương trình với
một bộ dữ liệu nào khác phức tạp hơn mà ta chưa có cơ hội để
phát hiện trước đó. Do đó, ta khơng thể khẳng định được rằng,
chương trình đúng tuyệt đối, khơng cịn sai sót nữa. Như vậy,
việc giải quyết một vấn đề cụ thể thực hiện qua hai giai đoạn.
Giai đoạn đầu là giai đoạn quan niệm, gồm các bước phân tích,
lựa chọn mơ hình, xây dựng thuật giải, cài đặt chương trình.
Giai đoạn sau là khai thác và bảo trì chương trình. Trong q
trình sử dụng, nói chung thường có nhu cầu về cải tiến, mở rộng
chương trình do các yếu tố của bài tốn ban đầu có thể thay đổi.
<b>3. THUẬT TỐN VÀ THUẬT GIẢI</b>



<b>3.1. Thuật tốn</b>


</div>
<span class='text_page_counter'>(40)</span><div class='page_container' data-page=40>

Giả sử khi nhận một lớp học mới, ban giám hiệu yêu cầu
giáo viên chủ nhiệm chọn lớp trưởng mới theo các bước sau:


<b>1. Lập danh sách tất các học sinh trong lớp;</b>
<b>2. Sắp thứ tự danh sách học sinh; </b>


<b>3. Chọn học sinh đứng đầu danh sách để làm lớp trưởng. </b>


Khi nhận được thông báo này, giáo viên chắc chắn sẽ rất bối
rối vì khơng hiểu là trong danh sách học sinh cần có những
thơng tin gì? Danh sách chỉ cần họ tên, hay cần thêm ngày
tháng năm sinh? Có cần thêm điểm trung bình không? Yêu cầu
2 lại càng gây nhiều thắc mắc. Cần phải sắp xếp danh sách theo
chiều tăng dần hoặc giảm dần? Sắp theo chỉ tiêu gì? Theo tên,
theo ngày tháng năm sinh hay theo điểm trung bình chung... Giả
sử sắp theo điểm trung bình thì nếu có hai học sinh cùng điểm
trung bình thì học sinh nào sẽ sắp trước, học sinh nào sẽ sắp
sau? ...


<i>Hướng dẫn ở trên vi phạm tính chất "không mập mờ" của </i>
thuật tốn. Nghĩa là, có q nhiều thơng tin còn thiếu để làm
cho các bước 1, 2 được hiểu <b>đúng</b> và hiểu theo <b>một nghĩa duy </b>
<b>nhất.</b> Nếu sửa lại một chút ít thì hướng dẫn trên sẽ trở nên rõ
ràng hơn rất nhiều và có thể gọi là một thuật toán chọn lớp
trưởng!


<b>1. Lập danh sách tất các học sinh trong lớp theo hai thông tin: Họ và</b>



Tên; Ðiểm trung bình cuối năm.


<b>2. Sắp hạng học sinh theo điểm trung bình theo thứ tự giảm dần (từ điểm </b>


cao đến điểm thấp). Hai học sinh có cùng điểm trung bình sẽ có cùng
hạng.


<b>3. Nếu chỉ có một học sinh có hạng nhất thì chọn học sinh đó làm lớp </b>


trưởng. Trường hợp có nhiều học sinh đồng hạng nhất thì chọn học
sinh có điểm mơn Tốn cao nhất làm lớp trưởng. Nếu vẫn còn nhiều
hơn một học sinh đồng hạng nhất và có cùng điểm mơn Tốn cao nhất
thì tiến hành bốc thăm.


</div>
<span class='text_page_counter'>(41)</span><div class='page_container' data-page=41>

<i>nhưng không đủ điều kiện để quyết định. Cịn chọn lựa có quyết </i>
định là hồn tồn xác định duy nhất trong điều kiện cụ thể của
vấn đề. Chẳng hạn trong vấn đề chọn lớp trưởng ở trên, bước 3
thể hiện một sự lựa chọn có quyết định. Tất nhiên, khi chưa lập
danh sách, chưa xếp hạng theo điểm trung bình thì giáo viên
khơng thể biết được sẽ chọn lớp trưởng theo cách nào. Nhưng
khi đã sắp xong danh sách thì chỉ có một phương án chọn duy
nhất.


<i>Tính "thực thi được" cũng là một tính chất khá hiển nhiên.</i>
Rõ ràng nếu trong "thuật tốn" tồn tại một bước khơng thể thực
thi được thì làm sao ta có được kết quả đúng như ý muốn? Tuy
<i>nhiên, cần phải hiểu là "thực thi được" xét trong điều kiện hiện </i>
tại của bài tốn. Chẳng hạn, khi nói "lấy căn bậc hai của một số
âm" là không thể thực thi được nếu miền xác định của bài toán
<i>là số thực, nhưng trong miền số phức thì thao tác "lấy căn bậc </i>


<i>hai của một số âm" là hoàn toàn thực thi được. Tương tự, nếu ta </i>
chỉ đường cho một người đi xe máy đến một bưu điện nhưng
con đường ta chỉ là đường cụt, đường cấm hoặc đường ngược
chiều thì người đi khơng thể đi đến bưu điện được.


</div>
<span class='text_page_counter'>(42)</span><div class='page_container' data-page=42>

B6. Cộng thêm 2 vào i
B7. Quay lại bước B4.
B8. Tổng cần tìm chính là S.


Ta chú ý đến bước B4. Ở đây ta muốn kết thúc thuật toán
khi giá trị của i vượt quá n. Thay vì viết là "nếu i lớn hơn n" thì
ta thay bằng điều kiện "nếu i bằng n+1" vì theo tốn học "i =
n+1" thì suy ra "i lớn hơn n". Nhưng điều kiện "i=n+1" không
phải lúc nào cũng đạt được. Vì ban đầu i = 1 là số lẻ, sau mỗi
bước, i được tăng thêm 2 nên i luôn là số lẻ. Nếu n là số chẵn
thì n+1 là một số lẻ nên sau một số bước nhất định, i sẽ bằng
n+1. Tuy nhiên, nếu n là một số lẻ thì n+1 là một số chẵn, do i
là số lẻ nên dù có qua bao nhiêu bước đi chăng nữa, i vẫn khác
n+1. Trong trường hợp đó, thuật tốn trên sẽ bị quẩn.


<i>Tính "đúng" là một tính chất khá hiển nhiên nhưng là tính</i>
chất khó đạt tới nhất. Thực vậy, khi giải quyết một vấn đề - bài
tốn, ta ln ln mong muốn lời giải của mình sẽ cho kết quả
đúng nhưng không phải lúc nào cũng đạt được. Mọi học sinh
khi làm bài kiểm tra đều muốn bài làm của mình có đáp số đúng
nhưng trên thực tế, trong lớp học chỉ có một số học sinh nhất
định là có khả năng đưa ra lời giải đúng!


<b> Các đặc trưng khác của thuật toán</b>



Bên cạnh ba đặc trưng chính là xác định, hữu hạn và đúng,
thuật tốn cịn có thêm ba đặc trưng phụ khác:


<i><b>1. Ðầu vào và đầu ra (input/output): mọi thuật toán, dù có</b></i>
đơn giản đến mấy cũng phải nhận dữ liệu đầu vào, xử lý nó và
cho ra kết quả cuối cùng.


</div>
<span class='text_page_counter'>(43)</span><div class='page_container' data-page=43>

giá, chọn lựa cách giải quyết vấn đề - bài tốn trên thực tế. Có
rất nhiều phương pháp để đánh giá tính hiệu quả của thuật toán.
Trong mục 3 của chương, ta sẽ tìm hiểu một tiêu chuẩn được
dùng rộng rãi là độ phức tạp của thuật tốn.


<i><b>3. Tính tổng qt (generalliness): thuật tốn có tính tổng </b></i>
qt là thuật toán phải áp dụng được cho mọi trường hợp của
bài tốn chứ khơng phải chỉ áp dụng được cho một số trường
hợp riêng lẻ nào đó. Chẳng hạn giải phương trình bậc hai sau
đây bằng delta đảm bảo được tính chất này vì nó ln giải được
với mọi giá trị số thực a, b, c bất kỳ. Tuy nhiên, không phải
thuật toán nào cũng đảm bảo được tính tổng quát. Trong thực
tế, có lúc người ta chỉ xây dựng thuật toán cho một dạng đặc
trưng của bài tốn mà thơi.


<b>Thuật tốn giải phương trình bậc hai ax2<sub>+ bx + c= 0 (a ≠ 0)</sub></b>
<b>1. Yêu cầu cho biết giá trị của 3 hệ số a, b, c</b>


<b>2. Nếu a = 0 thì</b>


2.1. Yêu cầu đầu vào khơng đảm bảo.
2.2. Kết thúc thuật tốn.



<b>3. Trường hợp a ≠ 0 thì</b>


</div>
<span class='text_page_counter'>(44)</span><div class='page_container' data-page=44>

3.3.3. Kết thúc thuật tốn
3.4. Nếu D < 0 thì


3.4.1. Phương trình vơ nghiệm.
3.4.2. Kết thúc thuật tốn.


<b> Thuật tốn tìm hộp có trọng lượng nặng nhất </b>


<b>Vấn đề: Có n hộp có khối lượng khác nhau và một cái cân </b>
đĩa. Hãy chỉ ra cách cân để tìm được hộp có trọng lượng nặng
<i>nhất. Vấn đề này là thể hiện của một bài toán tổng quát: Cho</i>
<i>một tập hợp A hữu hạn và một thứ tự toàn phần trên A. Hãy xây</i>
<i>dựng thuật tốn tìm phần tử lớn nhất của A. Bài tốn trong tốn</i>
học có vẻ rất phức tạp nhưng một thể hiện trên thực tế lại rất dễ
hiểu, và cách giải quyết cũng đơn giản. Từ đó ta có thể dễ dàng
suy ra cách giải bài tốn tổng quát.


<b>1. Nếu chỉ có 1 hộp (n = 1) thì</b>


1.1. Hộp đó chính là hộp nặng nhất.
1.2. Kết thúc thuật tốn.


<b>2. Ngược lại nếu có từ hai hộp trở lên (n > 1)</b>
2.1. Chọn hai hộp bất kỳ và đặt lên bàn cân.


<i>2.2. Giữ lại hộp nặng hơn, cất hộp nhẹ hơn sang chỗ </i>
khác.



<b>3. Nếu còn hộp chưa được cân thực hiện các bước sau, nếu </b>
khơng cịn hộp nào nữa, sang bước 5.


3.1. Chọn một hộp bất kỳ và để lên đĩa cân còn trống.
<i>3.2. Giữ lại hộp nặng hơn, cất hộp nhẹ hơn sang chỗ </i>
khác.


<b>4. Trở lại bước 3. </b>


</div>
<span class='text_page_counter'>(45)</span><div class='page_container' data-page=45>

<b> Thuật tốn Euclid tìm ước số chung lớn nhất</b>


<b>Bài toán: Cho hai số nguyên dương a và b. Tìm ước số </b>
chung lớn nhất của a và b.


<b>1. Yêu cầu cho biết giá trị của a, b.</b>
<b>2. a</b>0= a


<b>3. b</b>0= b


<b>4. i = 0</b>


<b>5. Nếu ai</b>khác bithì thực hiện các thao tác sau, ngược lại qua
bước 7.


5.1 Tăng i lên 1.
5.2. Nếu a<b>i-1</b>> b<b>i-1</b>thì


ai= ai-1- bi-1
bi= bi-1
5.3. Ngược lại



bi= bi-1- ai-1
ai= ai-1
<b>6. Trở lại bước 5.</b>


</div>
<span class='text_page_counter'>(46)</span><div class='page_container' data-page=46>

<b>+ Có những bài toán được giải theo những cách giải vi </b>
phạm thuật toán nhưng vẫn chấp nhận được.


Từ những nhận định trên, người ta thấy rằng cần phải có
những đổi mới cho khái niệm thuật toán. Người ta đã mở rộng
<i>hai tiêu chuẩn của thuật toán: tính xác định và tính đúng đắn.</i>
Việc mở rộng tính xác định đối với thuật tốn đã được thể hiện
qua các giải thuật đệ quy và ngẫu nhiên. Tính đúng của thuật
tốn bây giờ khơng cịn bắt buộc đối với một số cách giải bài
toán, nhất là các cách giải gần đúng. Trong thực tiễn, có nhiều
<i>trường hợp người ta chấp nhận các cách giải thường cho kết quả </i>
<i>tốt (nhưng không phải lúc nào cũng tốt) nhưng ít phức tạp và</i>
<i>hiệu quả. Chẳng hạn nếu giải một bài toán bằng thuật toán tối </i>
ưu địi hỏi máy tính thực hiện nhiều năm thì chúng ta có thể sẵn
lịng chấp nhận một giải pháp gần tối ưu mà chỉ cần máy tính
chạy trong vài ngày hoặc vài giờ.


<i>Các cách giải chấp nhận được nhưng khơng hồn tồn đáp</i>
<i>ứng đầy đủ các tiêu chuẩn của thuật toán thường được gọi là</i>
<i>các thuật giải. Khái niệm mở rộng này của thuật toán đã mở </i>
rộng cửa cho chúng ta trong việc tìm kiếm phương pháp để giải
quyết các bài toán được đặt ra.


</div>
<span class='text_page_counter'>(47)</span><div class='page_container' data-page=47>

<b>4.1. Ngôn ngữ tự nhiên</b>



Trong cách biểu diễn thuật tốn theo ngơn ngữ tự nhiên,
người ta sử dụng ngôn ngữ thường ngày để liệt kê các bước của
thuật tốn (Các ví dụ về thuật toán trong mục 1 của chương sử
<i>dụng ngôn ngữ tự nhiên). Phương pháp biểu diễn này không</i>
yêu cầu người viết thuật toán cũng như người đọc thuật toán
phải nắm các quy tắc. Tuy vậy, cách biểu diễn này thường dài
dòng, khơng thể hiện rõ cấu trúc của thuật tốn, đơi lúc gây hiểu
lầm hoặc khó hiểu cho người đọc. Gần như khơng có một quy
tắc cố định nào trong việc thể hiện thuật tốn bằng ngơn ngữ tự
nhiên. Tuy vậy, để dễ đọc, ta nên viết các bước con lùi vào bên
phải và đánh số bước theo quy tắc phân cấp như 1, 1.1, 1.1.1, ...
Bạn có thể tham khảo lại ba ví dụ trong mục 1 của chương để
hiểu cách biểu diễn thuật toán theo ngôn ngữ tự nhiên.


<b>4.2. Lưu đồ - sơ đồ khối</b>


Lưu đồ hay sơ đồ khối là một công cụ trực quan để diễn đạt
các thuật toán. Biểu diễn thuật toán bằng lưu đồ sẽ giúp người
đọc theo dõi được sự phân cấp các trường hợp và quá trình xử
lý của thuật toán. Phương pháp lưu đồ thường được dùng trong
những thuật tốn có tính rắc rối, khó theo dõi được quá trình xử
lý.


</div>
<span class='text_page_counter'>(48)</span><div class='page_container' data-page=48>

<b>4.2.2. Thao tác xử lý (process)</b>


Thao tác xử lý được biểu diễn bằng một hình chữ nhật, bên
trong chứa nội dung xử lý.


<b>4.2.3. Ðường đi (route)</b>



Khi dùng ngôn ngữ tự nhiên, ta ngầm hiểu rằng quá trình
thực hiện sẽ lần lượt đi từ bước trước đến bước sau (trừ khi có
yêu cầu nhảy sang bước khác). Trong ngôn ngữ lưu đồ, do thể
hiện các bước bằng hình vẽ và có thể đặt các hình vẽ này ở vị
trí bất kỳ nên ta phải có phương pháp để thể hiện trình tự thực
hiện các thao tác.


Hai bước kế tiếp nhau được nối bằng một cung, trên cung
có mũi tên để chỉ hướng thực hiện. Chẳng hạn trong hình dưới,
trình tự thực hiện sẽ là B1, B2, B3.


</div>
<span class='text_page_counter'>(49)</span><div class='page_container' data-page=49></div>
<span class='text_page_counter'>(50)</span><div class='page_container' data-page=50>

<b>4.2.4. Ðiểm cuối (terminator) </b>


</div>
<span class='text_page_counter'>(51)</span><div class='page_container' data-page=51>

<b>4.2.5. Ðiểm nối (connector) </b>


Ðiểm nối được dùng để nối các phần khác nhau của một lưu
đồ lại với nhau. Bên trong điểm nối, ta đặt một ký hiệu để biết
sự liên hệ giữa các điểm nối.


</div>
<span class='text_page_counter'>(52)</span><div class='page_container' data-page=52>

Ở trên chỉ là các ký hiệu cơ bản và thường được dùng nhất.
Trong thực tế, lưu đồ cịn có nhiều ký hiệu khác nhưng thường
chỉ dùng trong những lưu đồ lớn và phức tạp. Ðối với các thuật
toán trong cuốn sách này, ta chỉ cần sử dụng các ký hiệu trên là
đủ.


<b>4.3. Mã giả</b>


Tuy sơ đồ khối thể hiện rõ quá trình xử lý và sự phân cấp
các trường hợp của thuật toán nhưng lại cồng kềnh. Ðể mô tả
một thuật toán nhỏ ta phải dùng một không gian rất lớn. Hơn


nữa, lưu đồ chỉ phân biệt hai thao tác là rẽ nhánh (chọn lựa có
điều kiện) và xử lý mà trong thực tế, các thuật toán cịn có thêm
các thao tác lặp (chúng ta sẽ tìm hiểu về thao tác lặp trong các
bài sau).


<i>Khi thể hiện thuật toán bằng mã giả, ta sẽ vay mượn các cú</i>
pháp của một ngơn ngữ lập trình nào đó để thể hiện thuật tốn.
Tất nhiên, mọi ngơn ngữ lập trình đều có những thao tác cơ bản
là xử lý, rẽ nhánh và lặp. Dùng mã giả vừa tận dụng được các
khái niệm trong ngơn ngữ lập trình, vừa giúp người cài đặt dễ
dàng nắm bắt nội dung thuật toán. Tất nhiên là trong mã giả ta
vẫn dùng một phần ngôn ngữ tự nhiên. Một khi đã vay mượn cú
pháp và khái niệm của ngôn ngữ lập trình thì chắc chắn mã giả
sẽ bị phụ thuộc vào ngơn ngữ lập trình đó. Chính vì lý do này,
chúng ta chưa vội tìm hiểu về mã giả trong bài này (vì chúng ta
chưa biết gì về ngơn ngữ lập trình!). Sau khi tìm hiểu xong bài
về thủ tục - hàm bạn sẽ hiểu mã giả là gì!


<b> Một đoạn mã giả của thuật tốn giải phương trình bậc hai</b>
<b>if Delta > 0 then</b>


<b>Begin</b>


x1=(-b-sqrt(delta))/(2*a)


</div>
<span class='text_page_counter'>(53)</span><div class='page_container' data-page=53>

xuất kết quả: phương trình có hai nghiệm là x1và x2


<b>End</b>
<b>else</b>



<b>if delta = 0 then</b>


xuất kết quả: phương trình có nghiệm kép là -b/(2*a)
<b>else {trường hợp delta < 0}</b>


</div>
<span class='text_page_counter'>(54)</span><div class='page_container' data-page=54>

<b>CHƯƠNG 3</b>



<b>LẬP TRÌNH CĂN BẢN BẰNG</b>


<b>NGƠN NGỮ PASCAL</b>


<b>1. GIỚI THIỆU NGƠN NGỮ PASCAL</b>


Pascal là ngơn ngữ lập trình cấp cao được giáo sư Niklaus
Wirth ở Trường đại học Kỹ thuật Zurich (Thụy sĩ) thiết kế và
công bố vào năm 1971. Ơng đặt tên cho ngơn ngữ của mình là
Pascal để tưởng nhớ nhà toán học nổi tiếng người Pháp ở thế kỷ
17: Blaise Pascal, người đã sáng chế ra chiếc máy tính cơ khí
đầu tiên của nhân loại. Qua thời gian sử dụng, Pascal ngày càng
được đông đảo người dùng đánh giá cao, và trở thành một trong
các ngôn ngữ lập trình phổ biến nhất hiện nay.


Thành cơng của ngơn ngữ Pascal là ở chỗ: nó là ngơn ngữ
<b>đầu tiên đưa ra và thể hiện được khái niệm lập trình có cấu </b>
<b>trúc. Ý tưởng về một chương trình có cấu trúc xuất phát từ suy </b>
nghĩ cho rằng có thể chia một bài toán lớn, phức tạp thành
nhiều bài toán nhỏ, đơn giản hơn. Nếu mỗi bài toán nhỏ được
giải quyết bằng một chương trình con, thì khi liên kết các
chương trình con này lại sẽ tạo nên một chương trình lớn giải
quyết được bài toán ban đầu.


Bằng cách chia một chương trình thành các chương trình


con như vậy, người thảo chương có thể lập trình để giải quyết
riêng lẻ từng phần một, từng khối một, hoặc có thể tổ chức để
nhiều người cùng tham gia, mỗi người phụ trách một vài khối.
Ðặc biệt khi phải thay đổi hay sửa chữa trong một khối thì điều
đó sẽ ít ảnh hưởng đến các khối khác.


</div>
<span class='text_page_counter'>(55)</span><div class='page_container' data-page=55>

hai từ khóa Begin và End tạo thành một câu lệnh mới phức tạp
hơn gọi là câu lệnh ghép. Ðến lượt mình, hai hay nhiều lệnh
ghép lại có thể được nhóm lại để tạo thành một câu lệnh ghép
phức tạp hơn nữa… Tương tự như thế, ngôn ngữ Pascal cũng
cho phép xây dựng các kiểu dữ liệu phức tạp hơn từ các kiểu dữ
liệu đã có.


Pascal là một ngơn ngữ khơng chỉ chặt chẽ về mặt cú pháp
mà cịn chặt chẽ về mặt dữ liệu. Mỗi biến, mỗi hằng tham gia
trong chương trình ln có một kiểu dữ liệu xác định và chỉ
nhận những giá trị có cùng kiểu dữ liệu với nó. Ðiều này buộc
người lập trình phải nắm chắc cú pháp và ln chú ý đến tính
tương thích của các biểu thức về mặt kiểu dữ liệu. Chính vì thế,
lập trình bằng ngơn ngữ Pascal là một cơ hội tốt khơng chỉ rèn
luyện tư duy mà cịn rèn luyện tính cẩn thận và chính xác.


Ngày nay, ngơn ngữ Pascal được dùng để viết các chương
trình ứng dụng trong nhiều lĩnh vực. Với văn phạm sáng sủa, dễ
hiểu, với khả năng đủ mạnh, Pascal được xem là ngơn ngữ thích
hợp nhất để giảng dạy ở các trường phổ thông và đại học.


<b>2. CẤU TRÚC CỦA CHƯƠNG TRÌNH PASCAL</b>
<b>2.1. Ví dụ mở đầu</b>



</div>
<span class='text_page_counter'>(56)</span><div class='page_container' data-page=56>

<i>Chương trình cụ thể như sau:</i>


<b>PROGRAM VIDU;</b>


<b>{Tinh dien tich va chu vi hinh chu nhat}</b>
<b>Uses CRT;</b>


<b>Var</b>


<b>a, b, S, P: Real;</b>
<b>Begin</b>


<b>Clrscr;</b>


<b>Write( ‘Nhap chieu dai: ‘);</b> <b>Readln(a);</b>
<b>Write( ‘Nhap chieu rong: ‘); Readln(b);</b>


<b>S:=a*b;</b>
<b>P:=2* (a+b);</b>


<b>Writeln (‘Dien tich = ‘, S:8:2);</b>
<b>Writeln (‘Chu vi = ‘, P:8:2);</b>
<b>Readln;</b>


<b>End.</b>


<b>Giải thích các dịng trong chương trình:</b>
+ {Tinh dien tich va chu vi hinh chu nhat}


</div>
<span class='text_page_counter'>(57)</span><div class='page_container' data-page=57>

Khai báo sử dụng thư viện CRT của Turbo Pascal.


+ Var


a, b, S, P: Real;


Khai báo bốn biến a, b, S, P có kiểu dữ liệu là số thực
(Real).


+ Begin


Lệnh bắt đầu chương trình
+ Clrscr;


Lệnh xóa màn hình.


+ Write(‘Nhap chieu dai: ‘);


Lệnh in lên màn hình câu ‘Nhap chieu dai: ‘nhằm nhắc
người dùng nhập vào số đo chiều dài.


+ Readln(a);


Lệnh nhập dữ liệu cho biến a.
+ Write( ‘Nhap chieu rong: ‘);


Lệnh in lên màn hình câu ‘Nhap chieu rong: ‘nhằm nhắc
người dùng nhập vào số đo chiều rộng.


+ Readln(b);


</div>
<span class='text_page_counter'>(58)</span><div class='page_container' data-page=58>

Lệnh này in lên màn hình câu ‘Dien tich= ‘, kế đó in giá trị


<b>của biến S. Chỉ thị S:8:2 ấn định dành 8 cột trên màn hình để in </b>
giá trị của S, trong đó có hai cột để in phần thập phân.


+ Writeln(‘Chu vi = ‘, P:8:2);


Lệnh này in lên màn hình câu ‘Chu vi = ‘, kế đó in giá trị
của chu vi P có cả thảy 8 chữ số, trong đó có 2 số phần lẻ.


+ Readln;


Lệnh dừng màn hình để xem kết quả chạy chương trình.
<b>+ End.</b>


Dấu hiệu kết thúc chương trình.


<b>2.2. Cấu trúc chung của chương trình Pascal</b>


Chương trình là một dãy các câu lệnh chỉ thị cho máy các
công việc phải thực hiện. Một chương trình Pasccal đầy đủ gồm
ba phần chính:


<i>+ Phần tiêu đề </i>
<i>+ Phần khai báo</i>


<i>+ Phần thân chương trình</i>


<b>Program Têntựđặt;{Phần tiêu đề}</b>


{Phần khai báo }



<b>Uses ... {</b><i>khai báo sử dụng thư viện chuẩn}</i>
<b>Label ... {</b><i>khai báo nhãn}</i>


<b>Const ... {</b><i>khai báo hằng}</i>
<b>Type ... {</b><i>khai báo kiểu dữ liệu}</i>
<b>Var ... {</b><i>khai báo biến}</i>


</div>
<span class='text_page_counter'>(59)</span><div class='page_container' data-page=59>

<b>Procedure ... {</b><i>hàm và thủ tục}</i>


{Phần thân chương trình}


<b>Begin</b>
<b>{Các lệnh}</b>
<b>End.</b>


<b>2.2.1.</b> <b>Phần tiêu đề chương trình</b>


Phần này bắt đầu bằng từ khóa Program, sau đó ít nhất là
một khoảng trắng và một tên do người dùng tự đặt, cuối cùng
<b>kết thúc bằng dấu chấm phẩy ‘;’.</b>


<b>Ví dụ: Program Btap1;</b>


<b>hoặc: Program Giai_pt_bac2;</b>


Phần tiêu đề chiếm một dòng, còn gọi là phần đầu của
<i><b>chương trình, nó có thể khơng có cũng được.</b></i>


<b>2.2.2.</b> <b>Phần khai báo</b>



</div>
<span class='text_page_counter'>(60)</span><div class='page_container' data-page=60>

Các thủ tục và hàm được dùng khi có nhu cầu thiết kế các
chương trình lớn, phức tạp. Đối với các bài toán nhỏ, đơn giản,
việc sử dụng chương trình con là chưa cần thiết. Chi tiết về
phần này sẽ được trình bày kỹ trong các bài sau.


Sau đây ta điểm qua vài nét về các khai báo thông dụng
nhất.


<i><b>a) Khai báo hằng và khai báo biến</b></i>


<b>Biến là đại lượng có giá trị thay đổi được, cịn Hằng là đại </b>
lượng có giá trị khơng đổi, chúng được dùng trong chương trình
để lưu trữ các dữ liệu, tham gia vào các biểu thức tính tốn và
các q trình xử lý trong máy. Việc khai báo có tác dụng xác
<i>định tên và kiểu dữ liệu của biến hay hằng. Biến và hằng là</i>
những thành phần khó có thể thiếu được trong một chương
trình. Để khai báo biến ta dùng từ khóa Var, để khai báo hằng ta
dùng từ khóa Const, ví dụ:


Const N=10;
Var x, y: Real;


i, k: Integer;


<i><b>b) Khai báo (định nghĩa) một kiểu dữ liệu mới</b></i>


Ngồi các kiểu dữ liệu mà bản thân ngơn ngữ đã có sẵn như
kiểu thực, kiểu nguyên, kiểu ký tự, kiểu lơgic,... người dùng có
thể tự xây dựng các kiểu dữ liệu mới phục vụ cho chương trình
của mình, nhưng phải mơ tả sau từ khóa TYPE. Khi đã định


nghĩa một kiểu dữ liệu mới, ta có thể khai báo các biến thuộc
kiểu dữ liệu này. Ví dụ, ta định nghĩa một kiểu dữ liệu mới có
tên là Mang:


<b>Type Mang = Array[1..10] of Real;</b>


Bây giờ có thể khai báo hai biến A và B có kiểu dữ liệu là
<b>kiểu Mang:</b>


</div>
<span class='text_page_counter'>(61)</span><div class='page_container' data-page=61>

<i><b>c) Khai báo sử dụng thư viện chuẩn</b></i>


Turbo Pascal có sẵn một số hàm và thủ tục chuẩn, chúng
được phân thành từng nhóm theo chức năng mang các tên đặc
trưng, gọi là các thư viện hay đơn vị chương trình (Unit), như:
Crt, Graph, Dos, Printer... Muốn sử dụng các hàm hay thủ tục
của thư viện nào, ta phải khai báo có sử dụng thư viện đó, lời
khai báo phải để ở ngay sau phần tiêu đề của chương trình theo
cú pháp:


<b>Uses danhsáchthưviện;</b>


Ví dụ: do thủ tục Clrscr nằm trong thư viện CRT, nên nếu
trong chương trình mà có dùng lệnh Clrscr, thì phải khai báo:


Uses CRT;


Muốn sử dụng cả hai thư viện CRT và GRAPH, ta khai báo:
Uses CRT, GRAPH;


<b>2.2.3.</b> <b>Phần thân chương trình</b>



<i>Đây là phần chủ yếu nhất của một chương trình, bắt buộc </i>
<i>phải có.</i>


</div>
<span class='text_page_counter'>(62)</span><div class='page_container' data-page=62>

<b>3. CÁC PHẦN TỬ CƠ BẢN CỦA PASCAL </b>
<b>3.1. Tập ký tự cơ bản</b>


Mỗi ngôn ngữ đều được xây dựng từ một tập ký tự nào đó.
Nhiều ký tự nhóm lại với nhau tạo nên các từ. Nhiều từ liên kết
với nhau theo một qui tắc ngữ pháp nhất định (gọi là văn phạm)
thì tạo nên các mệnh đề. Trong các ngôn ngữ thảo chương,
mệnh đề còn được gọi là câu lệnh. Một tập hợp các câu lệnh
được sắp xếp theo một trật tự nhất định nhằm chỉ thị cho máy
các thao tác phải thực hiện tạo thành một chương trình. Các
chương trình được soạn thảo bởi người thảo chương và được
lưu trữ trên đĩa dưới dạng các tập tin.


Ngôn ngữ Pascal được xây dựng trên bộ ký tự cơ bản, gồm:
+ Các chữ cái latinh: A, B, C,...,Z, a, b, c,..., z


+ Các chữ số: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9


+ Các ký hiệu đặc biệt: +, -, *, /, =, <, {,}, [, ], %, $, &, #,...
+ Ký tự gạch nối ‘_’ và ký tự trắng ‘‘ (space)


Các chữ Ả rập: , , ,... không thuộc bộ ký tự của Pascal.
<b>3.2. Từ khóa (key word )</b>


Có một số từ được Pascal dành riêng cho việc xây dựng các
câu lệnh, các khai báo, các phép tính,... gọi là từ khóa. Việc sử


dụng các từ khóa địi hỏi phải tuân thủ đúng quy tắc đề ra, và
đặc biệt là người lập trình khơng được đặt một tên mới (tên
biến, tên hằng, tên hàm, tên thủ tục,...) trùng với một trong các
từ khóa. Dưới đây là danh sách các từ khóa của Pascal:


<b>absolute, and, array, Begin, case, const, div, do, downto,</b>


<b>else,</b> <b>End,</b> <b>file,</b> <b>for,</b> <b>forward,</b> <b>function,</b> <b>goto,</b> <b>if,</b>


</div>
<span class='text_page_counter'>(63)</span><div class='page_container' data-page=63>

<b>set, shl, shr, string, then, to, type, unit, until, uses, var,</b>
<b>while, with, xor</b>


<i>Các từ khóa có thể viết dưới dạng chữ hoa hay chữ thường </i>
<i><b>hay xen kẽ chữ hoa với chữ thường đều được. Ví dụ viết Begin</b></i>
<b>hay Begin hay BEGIN là như nhau.</b>


<b>3.3. Tên (identifier)</b>


Các biến, các hằng, các hàm, các thủ tục,... được sử dụng
<i>trong chương trình đều cần phải đặt tên, còn gọi là định danh</i>
<i>hay danh hiệu. Các tên này do người thảo chương tự đặt và phải </i>
đảm bảo đúng quy tắc: tên phải bắt đầu bằng chữ cái, kế đó có
thể là chữ cái, chữ số, hay dấu gạch nối ‘_’. Tên không được đặt
trùng với từ khóa. Chiều dài của tên tối đa là 127 ký tự. Thông
thường tên nên đặt ngắn gọn và có tính gợi nhớ.


Dưới đây là ví dụ về các tên được đặt đúng:


+ Delta, X1, X2, i, j , Chuc_vu, Luong, So_luong, Don_gia.
+ Còn các tên: 3ABC, In, Chu vi, Ma-so là sai vì:



+ 3ABC: bắt đầu bằng số
+ Chu vi: có chứa ký tự trắng


</div>
<span class='text_page_counter'>(64)</span><div class='page_container' data-page=64>

Mặc dù người lập trìmh có thể đặt một tên mới trùng với
một trong các tên chuẩn, song, để đỡ nhầm lẫn, chúng ta nên
tránh điều này.


<b>4. CÁC KIỂU DỮ LIỆU ĐƠN GIẢN</b>
<b>4.1. Khái niệm</b>


Chức năng của máy điện toán là xử lý các thông tin. Các
thông tin được nhập và lưu trữ trong bộ nhớ của máy dưới các
dạng khác nhau: có thể là số, là chữ, có thể là hình ảnh, âm
thanh,... mà thuật ngữ tin học gọi chung là dữ liệu. Tính đa dạng
của dữ liệu đòi hỏi phải tổ chức và phân phối bộ nhớ thích hợp
để lưu trữ và xử lý tốt các dữ liệu. Ngôn ngữ thảo chương chia
các dữ liệu thành từng nhóm riêng trên đó xây dựng một số
phép toán tạo nên các kiểu dữ liệu khác nhau, mỗi kiểu dữ liệu
là một tập hợp các giá trị mà một biến thuộc kiểu đó có thể
nhận. Khi một biến được khai báo thuộc kiểu dữ liệu nào thì
máy sẽ dành cho biến đó một dung lượng thích hợp trong bộ
nhớ để có thể lưu trữ các giá trị thuộc kiểu dữ liệu đó.


Các kiểu dữ liệu trong ngôn ngữ Pascal được chia ra thành
<b>hai loại chính: loại đơn giản và loại có cấu trúc.</b>


Mỗi kiểu dữ liệu đơn giản là một tập các giá trị cơ sở có thứ
tự. Ví dụ kiểu Integer gồm các số nguyên nằm trong phạm vi từ
-32768 đến 32767 và có thứ tự tự nhiên: -32768< ... < -1 < 0 <


1 < ... < 32767 , kiểu lơgic chỉ có hai giá trị False, True với quy
ước False < True.


Các kiểu dữ liệu có cấu trúc được xây dựng từ các kiểu dữ
liệu đơn giản. Mỗi kiểu dữ liệu có cấu trúc là một tập các phần
tử thuộc kiểu dữ liệu đơn giản được tổ chức lại theo một quy tắc
nhất định .


</div>
<span class='text_page_counter'>(65)</span><div class='page_container' data-page=65>

<b>Các kiểu dữ liệu có cấu trúc gồm có: kiểu mảng, kiểu bản </b>
<b>ghi, kiểu tập hợp và kiểu tập tin.</b>


Riêng chuỗi ký tự (STRING) là một kiểu dữ liệu đặc biệt,
vừa có tính đơn giản lại vừa có tính cấu trúc. Mỗi chuỗi có thể
xem là một giá trị, nhưng cũng có thể xem là một mảng các giá
trị kiểu ký tự. Vì vậy, việc sử dụng chuỗi cũng có hai mức khác
nhau: mức đơn giản và mức có cấu trúc.


Các kiểu dữ liệu đơn giản còn được phân thành hai loại:
<b>đếm được (Ordinal type) và không đếm được. Kiểu thực thuộc </b>
loại không đếm được, các giá trị của nó dày đặc. Tất cả các kiểu
dữ liệu đơn giản còn lại: nguyên, ký tự, lôgic, liệt kê và đoạn
<i>con đều thuộc loại đếm được (còn gọi là rời rạc).</i>


Dưới đây sẽ lần lượt trình bày kỹ về bốn kiểu dữ liệu đơn
giản chuẩn và thông dụng: kiểu nguyên, kiểu thực, kiểu logic,
kiểu ký tự. Kiểu chuỗi được giới thiệu để có thể sử dụng ngay ở
mức đơn giản.


<b>4.2. Kiểu số nguyên</b>



<b>4.2.1.</b> <b>Các kiểu số nguyên</b>


<b>Tên kiểu</b> <b>Phạm vi giá trị</b> <b>Số byte</b>


</div>
<span class='text_page_counter'>(66)</span><div class='page_container' data-page=66>

Ngoài kiểu Integer là thông dụng nhất, các số nguyên còn
được chia ra thành bốn kiểu nữa đó là: Byte, Word, ShortInt và
LongInt. Bảng trên liệt kê chi tiết về tên gọi, phạm vi giá trị và
độ dài tính theo đơn vị byte của từng kiểu nguyên.


Các biến nguyên chỉ có thể nhận các giá trị là các số nguyên
nằm trong phạm vi giá trị của biến đó. Khi gán cho một biến
một số ngun nằm ngồi phạm vi của biến thì máy sẽ báo lỗi:
<i>"Const out of range". Ví dụ, cho khai báo:</i>


<b>Var</b>
i: Byte;
N: Integer;


thì các lệnh đưới đây là đúng:
i:= 200;


N:= -1500;


còn các lệnh dưới đây là bị lỗi:
i:= -5;


N:= 50000;


Ðặc biệt không thể gán một số thực cho một biến nguyên.
Câu lệnh sau là sai:



N:= 12.5;


<i>Khi gặp tình huống này, máy sẽ báo lỗi "Type mismatch".</i>
<i><b>Chú ý</b></i>


</div>
<span class='text_page_counter'>(67)</span><div class='page_container' data-page=67>

<b>4.2.2.</b> <b>Các phép toán số học trên số nguyên</b>
+ Phép cộng và trừ: ký hiệu + và - như thường lệ.


+ Phép nhân: ký hiệu bằng dấu *, ví dụ 4*2 cho kết quả là
8.


+ Phép chia: ký hiệu bằng dấu /, ví dụ 6/4 cho kết quả là
1.5.


+ Phép chia lấy phần nguyên: ký hiệu bằng từ khóa DIV.
+ Phép lấy phần dư nguyên của phép chia: ký hiệu bằng từ
khóa MOD.


<b>Ví dụ: 15 DIV 6 cho kết quả là 2.</b>
15 MOD 6 cho kết quả là 3.


Các phép toán trên đều cho kết quả là các số nguyên, trừ ra
phép chia (/) luôn cho kết quả là một số thực. Vì thế nếu N là
một biến nguyên, mà gán:


N:= 20/5;


thì máy sẽ báo lỗi, bởi vế phải có giá trị kiểu thực (=4.0) mặc
dù phần lẻ bằng khơng.



</div>
<span class='text_page_counter'>(68)</span><div class='page_container' data-page=68>

<b>Ví dụ: tính biểu thức sau:</b>


15 mod (2 +4) * 20 div (10 div 4) + 40 mod ( 5* 3)
= 15 mod 6 * 20 div 2 + 40 mod 15


= 3 * 20 div 2 + 10
= 60 div 2 + 10
= 30 + 10
= 40


<i><b>* Ví dụ sau đây là một ứng dụng của các phép tốn </b></i>
<i><b>div, mod:</b></i>


<b>+ Ví dụ: Nhập một số tiền N đồng, đổi ra xem được bao </b>
nhiêu tờ 5 đồng, bao nhiêu tờ 2 đồng, bao nhiêu tờ 1 đồng sao
cho tổng số tờ là ít nhất. Ví dụ N = 43đ = 8 tờ 5đ + 1 tờ 2đ + 1
tờ 1đ. Cách tính như sau:


Số tờ 5đ = 43 div 5 = 8
Số tiền dư = 43 mod 5 = 3


Số tờ 2đ = Số tiền dư div 2 = 3 div 2 =1
Số tờ 1đ = Số tiền dư mod 2 = 3 mod 2 = 1
Dưới đây là chương trình cụ thể:


<b>PROGRAM VIDU4_1;</b>
<b>{Ðổi tiền}</b>


<b>Var</b> <b>N, st5, st2, st1, sodu: LongInt;</b>


<b>Begin</b>


<b>Write(‘Nhap so tien: ’); Readln(N);</b>
<b>st5:= N div 5;</b>


</div>
<span class='text_page_counter'>(69)</span><div class='page_container' data-page=69>

<b>st2:= Sodu div 2;</b>
<b>st1:= Sodu mod 2;</b>


<b>Writeln(‘KET QUA DOI TIEN LA: ‘);</b>
<b>Writeln(‘So to 5đ= ‘, st5);</b>


<b>Writeln(‘So to 2đ= ‘, st2);</b>
<b>Writeln(‘So to 1đ=‘, st1);</b>
<b>Readln;</b>


<b>End.</b>


<b>4.2.3.</b> <b>Các phép tốn so sánh</b>


Ngơn ngữ Pascal có sáu phép tốn so sánh được liệt kê
trong bảng


<b>Ký hiệu</b> <b>Ý nghĩa</b> <b>Ví dụ</b>


= bằng nhau x=y


<> khác nhau x<>y


</div>
<span class='text_page_counter'>(70)</span><div class='page_container' data-page=70>

Biểu thức 5+2 <> 7 cho kết quả là FALSE.



Biểu thức 6 div 2 > 10 div 3 cho kết quả là FALSE.
<b>4.2.4.</b> <b>Các phép tốn lơgic trên số nguyên</b>


Các phép tính NOT, AND, OR, XOR xử lý các bít nhị phân
được xác định như sau:


NOT 1 = 0 1 AND 1=1 1 OR 1=1 1 XOR 1=0
NOT 0 = 1 1 AND 0=0 1 OR 0=1 1 XOR 0=1
0 AND 1=0 0 OR 1=1 0 XOR 1=1
0 AND 0=0 0 OR 0=0 0 XOR 0=0
Mỗi số nguyên được biểu diễn trong máy dưới dạng một
dãy các bít nhị phân. Số kiểu Integer được biểu diễn bằng 16
bit. Ví dụ: số 1 và số 2 có biểu diễn trong máy lần lượt là:


0000 0000 0000 0001
0000 0000 0000 0011


Phép lấy NOT một số nguyên sẽ đảo tất cả các bít biểu diễn
số ngun đó, tức là 0 thành 1, cịn 1 thành 0. Ví dụ:


NOT 1 = 1111 1111 1111 1110
NOT 2 = 1111 1111 1111 1100


Phép lấy AND, OR, XOR hai số nguyên được tiến hành
bằng cách AND, OR, XOR từng cặp bít tương ứng của hai số
đó, ví dụ:


</div>
<span class='text_page_counter'>(71)</span><div class='page_container' data-page=71>

<b>4.2.5.</b> <b>Các phép dịch chuyển số học SHR và SHL</b>
N SHR k: dịch các bít của số nguyên N sang phải đi k bit.
N SHL k: dịch các bít của số nguyên N sang trái đi k bit.


Có thể chứng minh được:


N SHR k = N div 2k
N SHL k = N * 2k
<b>Ví dụ:</b>


120 shr 4 = 7, vì:


120 shr 4 = 120 div 24= 120 div 16 = 7.
120 shl 3 = 960, vì:


120 shl 3 = 120 * 23= 120 * 8 = 960.


Hai phép toán SHR và SHL được dùng khi muốn tăng tốc
độ tính tốn trên các số ngun.


<b>4.2.6.</b> <b>Các hàm có</b> <b>đối số nguyên</b>


<b>* Hàm PRED(k): đối số k nguyên, trả về số nguyên đứng </b>
ngay trước k, tức là k-1 .


Ví dụ: Pred (5) = 4, Pred (-6) = -7.


</div>
<span class='text_page_counter'>(72)</span><div class='page_container' data-page=72>

Ví dụ: Odd(15) = True; Odd(4) = False.


<i><b>+ Ví dụ: Nhập số nguyên N, nếu N chẵn thì in ra chữ chẵn,</b></i>
<i>nếu N lẻ thì in ra chữ lẻ. Chương trình như sau:</i>


<b>PROGRAM VIDU4_2;</b>
<b>Var</b>



<b>N: Integer;</b>
<b>Begin</b>


<b>Write(‘Nhap so N:’); Readln(N);</b>
<b>If Odd(N) = TRUE then</b>


<b>Write(N, ‘la so le’)</b>
<b>Else</b>


<b>Write(N, ‘la so chan’);</b>
<b>Readln;</b>


<b>End.</b>


<b>4.2.7.</b> <b>Các thủ tục có đối số ngun</b>
Có hai thủ tục khá thơng dụng là:


<b>* Thủ tục INC(k): tăng k lên một đơn vị. Ví dụ, sau khi </b>
thực hiện các lệnh:


k:=5;
Inc(k);


thì giá trị sau cùng của k là 6.


Vậy, lệnh Inc(k); tương đương với lệnh k:=k+1; hay
k:=Succ(k);


</div>
<span class='text_page_counter'>(73)</span><div class='page_container' data-page=73>

k:=5;


Dec(k);


thì giá trị của k sẽ là 4.


Vậy, lệnh Dec(k); tương đương với lệnh k:=k-1; hay
k:=Pred(k);


<b>4.3. Kiểu số thực</b>


<b>4.3.1.</b> <b>Kiểu Real và các kiểu mở rộng</b>


Kiểu Real là kiểu số thực thông dụng nhất dùng để biểu
diễn các số thực x có trị tuyệt đối |x| nằm trong khoảng từ
2.9*10-39đến 1.7*10+38. Nếu x > 1.7*10+38thì khơng biểu diễn
x trong máy được, cịn nếu |x| < 2.9*10-39thì x được coi là bằng
0.


Có hai cách biểu diễn các số thực:


<i><b>* Cách 1: Viết bình thường, trong đó dấu phẩy thập phân </b></i>
<i>được thay bằng dấu chấm thập phân.</i>


Ví dụ: 45.0 -256.45 +122.08


<i><b>* Cách 2: Viết số dưới dạng khoa học:</b></i>


</div>
<span class='text_page_counter'>(74)</span><div class='page_container' data-page=74>

<b>Var</b>


x, y: Real;



<b>Ngoài kiểu Real ra, các số thực cịn có bốn kiểu mở rộng </b>
<b>nữa là Single, Double, Extended và Comp. Bảng sau nêu chi</b>
tiết về phạm vi giá trị và số byte dùng để lưu trữ trong bộ nhớ
của từng kiểu số thực.


<b>Tên kiểu</b> <b>Phạm vi giá trị</b> <b>Số byte</b>
Real 2.9*10-39.. 1.7*1038 6
Single 1.5*10-45.. 3.4*1038 4
Double 5.0*10-324.. 1.7*10308 8
Extended 3.4*10-4932.. 1.1*104932 10


Comp -9.2*1018.. 9.2*1018 8


<i><b>+ Chú ý: Turbo Pascal thường chỉ làm việc với một kiểu </b></i>
Real. Muốn dùng bốn kiểu thực còn lại, phải chuyển sang mode
8087 bằng cách viết chỉ thị {$N+} ở ngay đầu chương trình.
<b>4.3.2.</b> <b>Các phép tốn trên số thực </b>


Có bốn phép toán số học là nhân (*), chia (/), cộng (+) và
trừ (-). Khi một trong các số hạng tham gia tính tốn là kiểu
thực thì kết quả của phép toán cũng là một số thực.


<i>Phép tốn DIV, MOD khơng dùng cho các số thực.</i>


Ví dụ: với hai biến x, y kiểu thực thì lệnh sau là bị lỗi vì
biểu thức vế phải khơng hợp lệ:


</div>
<span class='text_page_counter'>(75)</span><div class='page_container' data-page=75>

Các phép toán so sánh (= , <> , < , <= , > , >= ) cũng dùng
được cho các số hạng là thực hay nguyên.



<b>4.3.3.</b> <b>Các hàm có</b> <b>đối số nguyên hoặc thực</b>


<i><b>* Hàm ABS(x): tính trị tuyệt đối của x: |x|. Kiểu dữ liệu của </b></i>
kết quả cùng kiểu với đối số. Nếu x nguyên thì ABS(x) cũng
nguyên, nếu x là số thực thì ABS(x) cũng là số thực.


Ví dụ: Abs(5 - 8) = 3


<i><b>* Hàm SQR(x): tính bình phương của x: x</b></i>2. Kiểu dữ liệu
của kết quả cùng kiểu với đối số.


Ví dụ: Sqr(4.0) = 16.0
Sqr(7 div 3) = 4


Trong các hàm dưới đây, đối số x có thể là nguyên hay thực,
<i>nhưng giá trị trả về luôn ln là kiểu thực:</i>


<i><b>* Hàm SQRT(x): tính</b></i> , (x ≥ 0)
<i><b>* Hàm EXP(x):</b></i> tính ex


<i><b>* Hàm LN(x):</b></i> tính lnx, (x > 0)


<i><b>* Các hàm SIN(x), COS(x), và ARCTAN(x): tính sinx,</b></i>
cosx và arctgx.


</div>
<span class='text_page_counter'>(76)</span><div class='page_container' data-page=76>

Ví dụ: Trunc(12.55) = 12
Trunc(-2.98) = -2


<i><b>* Hàm ROUND(x): cho số nguyên bằng cách làm tròn x.</b></i>
Ví dụ: Round(12.45) = 12



Round(-2.98) = -3


Chú ý rằng hàm Int(x) và hàm Trunc(x) cùng cho phần
nguyên của x, chúng chỉ khác nhau về kiểu dữ liệu của giá trị
trả về. Int(4.5)= 4.0 còn Trunc(4.5) = 4 (viết 4 thì hiểu đó là số
ngun, cịn viết 4.0 thì hiểu đó là số thực).


<b>+ Ví dụ: Viết chương trình nhập số thực x bất kỳ, tính và in</b>
các giá trị y và z lên màn hình theo cơng thức:


Trong Pascal khơng có hàm tính trực tiếp 2xvà Log4(x), nên


ta phải chuyển qua hàm exvà Ln(x) như sau:
, và


Chương trình cụ thể như sau:
<b>PROGRAM VIDU4_3;</b>
<b>Var</b>


<b>x, y, z: Real;</b>
<b>Begin</b>


<b>Write(‘Nhap x: ‘); Readln(x);</b>


</div>
<span class='text_page_counter'>(77)</span><div class='page_container' data-page=77>

<b>z:= exp( x*Ln(2) ) + Ln(abs(x)+1) / Ln(4);</b>


<b>Writeln(‘y= ‘, y:10:3 );</b>
<b>Writeln(‘z= ‘, z:10:3 );</b>
<b>Readln;</b>



<b>End.</b>


Khi chạy chương trình, nếu nhập x = 0 thì kết quả y = 0.250
và z = 1.000.


<b>4.4.</b> <b>Kiểu ký tự (char)</b>


<b>4.4.1.</b> <b>Ký tự và biến kiểu ký tự</b>
<b>Ký</b>


<b>tự</b>


<b>Mã</b>
<b>ASCII</b>


<b>Ký</b>
<b>tự</b>


<b>Mã</b>
<b>ASCII</b>


<b>Ký</b>
<b>tự</b>


<b>Mã</b>
<b>ASCII</b>


32 A 65 a 97



0 48 B 66 b 98


</div>
<span class='text_page_counter'>(78)</span><div class='page_container' data-page=78>

6 54 H 72 h 104


7 55 I 73 i 105


8 56 J 74 j 106


9 57 K 75 k 107


L 76 l 108


M 77 m 109


N 78 n 110


O 79 o 111


P 80 p 112


Q 81 q 113


R 82 r 114


S 83 s 115


T 84 t 116


U 85 u 117



V 86 v 118


</div>
<span class='text_page_counter'>(79)</span><div class='page_container' data-page=79>

X 88 x 120


Y 89 y 121


Z 90 z 122


Các ký tự dùng trong máy tính điện tử được liệt kê đầy đủ
trong bảng mã ASCII gồm 256 ký tự khác nhau và được đánh
số thứ tự từ 0 đến 255. Số thứ tự của mỗi ký tự còn gọi là mã
ASCII của ký tự đó. Bảng trên liệt kê một phần của bảng mã
ASCII gồm các chữ số và chữ cái kèm theo mã của chúng.


Trong bảng, ký tự có mã bằng 32 là ký tự trắng (space).
Tuy có 256 ký tự khác nhau song chỉ có 128 ký tự đầu tiên
là hay dùng, cịn lại là các ký tự mở rộng. Các ký tự có mã từ 0
đến 31 gọi là các ký tự điều khiển, không in ra được, được dùng
để điều khiển các thiết bị ngoại vi, chẳng hạn ký tự có mã là 7
dùng để tạo một tiếng kêu bip, ký tự có mã là 13 dùng để
chuyển con trỏ màn hình xuống đầu dòng dưới...


Mỗi ký tự trong bảng mã ASCII gọi là một hằng ký tự,
chiếm độ dài 1 byte, và khi viết trong Pascal phải được đặt
trong cặp nháy đơn: ‘0’, ‘1’, ‘A’, ‘B’, ‘$’,...


</div>
<span class='text_page_counter'>(80)</span><div class='page_container' data-page=80>

Khi đó có thể gán:
ch:=‘A’;
ch1:=‘$’;



<i>Ký tự ‘A’gọi là giá trị của biến ch, còn ‘$’là giá trị của </i>
biến ch1.


<i><b>+ Nhận xét: Từ bảng mã của các chữ cái ta suy ra:</b></i>


<b>Mã chữ thường = Mã chữ hoa tương ứng + 32. (1)</b>
<b>4.4.2.</b> <b>Các hàm liên quan</b> <b>đến ký tự</b>


<b>* Hàm PRED(ch): cho ký tự đứng ngay trước ký tự ch </b>
trong bảng mã.


Ví dụ: Pred(‘B’)=‘A’


<b>* Hàm SUCC(ch): cho ký tự đứng ngay sau ký tự ch trong </b>
bảng mã.


Ví dụ: Succ(‘A’)=‘B’.


<b>* Hàm UpCase(ch): đổi ký tự ch thành chữ hoa. </b>
Ví dụ: Upcase( ‘a’) = ‘A’,


Upcase( ‘b’) = ‘B’,
Upcase( ‘A’) = ‘A’.


<b>* Hàm ORD(ch): cho mã của ký tự ch. </b>
Ví dụ: Ord (‘A’) = 65, Ord (‘a’) = 97 .


<b>* Hàm CHR(k): đối số k nguyên, 0k< 255, cho ký tự có </b>
mã bằng k.



Ví dụ: Chr (65)= ‘A’,
Chr (97)= ‘a’,


</div>
<span class='text_page_counter'>(81)</span><div class='page_container' data-page=81>

Có một số ký tự khơng có trên bàn phím, để viết chúng lên
màn hình ta phải dùng lệnh Write và hàm CHR. Ví dụ:


Lệnh Writeln(Chr(201)); in ra ký tự: +
Lệnh Writeln(Chr(187)); in ra ký tự: +


Ký tự có mã là 7 gọi là ký tự BEL (chuông), và lệnh:
Write(Chr(7)); hay Write(#7); có tác dụng phát ra một tiếng kêu
bip.


<i><b>Chú ý</b></i>


* Turbo Pascal (TP) cho phép viết gọn Chr(k) thành #k nếu
k là hằng số. Ví dụ, hai lệnh sau cùng in lên màn hình chữ A:


Write(#65);
Write(Chr(65));


* Trong TP khơng có hàm đổi chữ hoa ra chữ thường,
nhưng có thể làm việc này nhờ công thức (1) và hai hàm Ord và
Chr:


<b>Chữ thường:= Chr ( Ord(chữ hoa) + 32 )</b> (1)
<b>+ Ví dụ: Nhập vào một số nguyên k, 0 < k < 255, in ra ký tự </b>
có mã là k. Chương trình kết thúc khi nhập vào số 0:


</div>
<span class='text_page_counter'>(82)</span><div class='page_container' data-page=82>

<b>Write(‘Nhập mã của ký tự: ‘); Readln(k);</b>


<b>Writeln(‘Ký tự có mã ‘, k, ‘là ‘, Chr(k) );</b>
<b>Until k=0;</b>


<b>Readln;</b>
<b>End.</b>


<b>+ Ví dụ: Nhập một ký tự, nếu là chữ hoa thì đổi ra chữ </b>
thường, nếu là chữ thường thì đổi ra chữ hoa.


<b>PROGRAM VIDU4_5;</b>


<b>{Ðổi chữ hoa ra thường và ngược lại}</b>
<b>Var</b>


<b>ch, ch1: Char;</b>
<b>Begin</b>


<b>Write(‘Nhập một ký tự:’); Readln(ch);</b>
<b>If (ch>=‘A’) and ( ch<=‘Z’) then</b>


<b>ch1:=Chr( Ord (ch)+32)</b>
<b>else</b>


<b>ch1:= Upcase(ch);</b>
<b>Writeln(ch, ‘đã đổi ra: ‘, ch1);</b>
<b>Readln;</b>


<b>End.</b>


<b>4.5. Kiểu lơgic (boolean)</b>



</div>
<span class='text_page_counter'>(83)</span><div class='page_container' data-page=83>

Các phép tốn lơgic gồm có: NOT, AND, OR và XOR. Nếu
A và B là hai đại lượng lơgic thì NOT A, A and B, A or B và A
xor B cũng là những đại lượng lơgic có kết quả được cho ở
bảng sau:


<b>A</b> <b>not A</b>


True False


False True


<b>A</b> <b>B</b> <b>A and B</b> <b>A or B</b> <b>A xor B</b>


True True True True False


True False False True True


False True False True True


False False False False False


<i><b>Cũng từ bảng này ta rút ra các nhận xét:</b></i>


</div>
<span class='text_page_counter'>(84)</span><div class='page_container' data-page=84>

A:=Not (2*3=5) or (‘A’<‘B’) and not (4/2=2) xor (Sqrt(2)>1);
thì giá trị của A= FALSE, thật vậy:


Not (2*3=5) or (‘A’<‘B’) and not (4/2=2) xor (Sqrt(2) >1)
= TRUE or TRUE and FALSE xor TRUE



= TRUE or FALSE xor TRUE
= TRUE xor TRUE


= FALSE


Biến chỉ nhận giá trị là TRUE hoặc FALSE gọi là biến kiểu
lôgic. Khi khai báo biến kiểu lơgic ta dùng từ khóa Boolean, ví
dụ:


<b>Var</b>


A, B: Boolean;


Trong chương trình ta có thể gán:
A:= True;


B:=2*2 < 3;


Giá trị của biến B sẽ là False vì biểu thức 2*2 < 3 là sai.
<i>* Về thứ tự tính tốn, các phép so sánh thì ngang cấp nhau </i>
<i>và được tính sau tất cả các phép tốn khác.</i>


Ví dụ tính biểu thức:


5+7 div 2 < -7 mod 3 + 5*2
= 5 + 3 < -1 + 10


= 8< 9
= TRUE



</div>
<span class='text_page_counter'>(85)</span><div class='page_container' data-page=85>

Chẳng hạn, biểu thức sau là sai quy cách:
N > 0 and N<10


Cần sửa đúng thành:
(N > 0) and (N<10)


<b>+ Ví dụ: Nhập vào độ dài ba cạnh a, b, c của một tam giác, </b>
nếu a, b, c không phải là ba cạnh của tam giác thì in lên màn
hình câu "khơng phải ba cạnh của tam giác", ngược lại, nếu
đúng là ba cạnh của một tam giác thì tính chu vi và diện tích
tam giác đó theo cơng thức Hêrông:


, với p là nửa chu vi:


Ta biết, điều kiện để a, b, c là ba cạnh của một tam giác là
mỗi cạnh phải dương và tổng hai cạnh thì lớn hơn cạnh cịn lại.


Dưới đây là chương trình cụ thể:
<b>PROGRAM VIDU4_6;</b>


<b>{Tính diện tích và chu vi tam giác theo ba cạnh}</b>
<b>Var</b> <b>a, b, c, P, S: Real;</b>


</div>
<span class='text_page_counter'>(86)</span><div class='page_container' data-page=86>

<b>Else</b>
<b>Begin</b>


<b>P:=(a+b+c)/2;</b>


<b>S:= Sqrt( P*(P-a)*(P-b)*(P-c));</b>
<b>Writeln(‘Chu vi = ‘, 2*P:10:2);</b>


<b>Writeln(‘Dien tich S= ‘, S:10:2);</b>
<b>End;</b>


<b>Readln;</b>
<b>End.</b>


Khi chạy chương trình này, để nhập ba cạnh của tam giác,
bạn gõ ba số cách nhau khoảng trắng rồi enter, chẳng hạn:


<b>Nhap 3 canh cua tam giac: 3 4 5</b>


Kết quả chu vi = 12.00, dien tich = 6.00. Nếu nhập ba cạnh
<b>là: 2 3 6 thì máy hiện câu: "Khơng phải ba cạnh của tam giác ! " </b>
(vì 2+3 < 6).


<b>4.6. Chuỗi ký tự (string)</b>


<i>* Một dãy ký tự đặt trong cặp nháy đơn gọi là một hằng </i>
<i>chuỗi. Dưới đây là ba hằng chuỗi:</i>


‘NGON NGU PASCAL’
‘Tin hoc nam 2000’
‘123456’


Các chuỗi có thể được ghép nối với nhau nhờ phép cộng
chuỗi. Khi cộng (+) hai chuỗi ta được một chuỗi duy nhất bằng
cách ghép chuỗi sau vào cuối của chuỗi đầu.


</div>
<span class='text_page_counter'>(87)</span><div class='page_container' data-page=87>

Các chuỗi cũng so sánh được với nhau. Việc so sánh hai
chuỗi được thực hiện bằng cách so sánh từng cặp ký tự tương


ứng từ trái qua phải. Khi phát hiện có một cặp ký tự khác nhau
thì chuỗi nào chứa ký tự nhỏ hơn sẽ nhỏ hơn.


Ví dụ: Biểu thức ‘Anh’< ‘an’ là đúng vì ‘A’< ‘a’
Biểu thức ‘Thong’> ‘Tha’ là đúng vì ‘o’> ‘a’


Nếu nội dung của hai chuỗi giống nhau từ đầu đến hết chiều
dài của chuỗi ngắn hơn thì chuỗi ngắn hơn là nhỏ hơn.


Ví dụ: Biểu thức ‘Tha’< ‘Thang’ là đúng vì ‘Tha’ ngắn hơn
‘Thang’.


Hai chuỗi bằng nhau nếu chúng dài bằng nhau và mọi cặp
ký tự ở các vị trí tương ứng đều giống nhau.


Ví dụ: Biểu thức ‘Pascal’= ‘Pascal’ cho kết quả là đúng
Biểu thức ‘Pascal’= ‘PAscal’ cho kết quả là sai.
<i>* Biến nhận giá trị là các hằng chuỗi gọi là biến kiểu chuỗi.</i>
Có thể khai báo hai biến chuỗi như sau:


<b>Var</b>


Ho_ten: String[20];
St: String;


</div>
<span class='text_page_counter'>(88)</span><div class='page_container' data-page=88>

<b>5. HẰNG, BIẾN và BIỂU THỨC </b>
<b>5.1. Khái niệm về biến và hằng</b>


Trong phần trước ta đã biết mỗi kiểu dữ liệu có một tập các
<i>giá trị tương ứng. Các giá trị của kiểu nguyên hay kiểu thực là</i>


các số, như 40 hay 5.72, các giá trị của kiểu ký tự là các ký tự
như ‘A’hay ‘a’, cịn kiểu lơgic thì chỉ có hai giá trị là True và
False, ...


Q trình xử lý trong máy tính địi hỏi mỗi giá trị phải được
lưu trữ ở một ô nhớ nào đó trong bộ nhớ của máy, và ơ nhớ này
được đặt một cái tên để gọi. Khi đó mọi việc tính tốn hay xử lý
liên quan đến mỗi giá trị được thực hiện gián tiếp thông qua tên
của ơ nhớ chứa giá trị đó. Ví dụ, nếu số 5.72 được lưu trong ơ
nhớ có tên là x, thì biểu thức 5.72*2 có thể được viết là x*2.
Việc dùng tên x dễ nhớ và tiện hơn nhiều so với việc dùng và
nhớ số 5.72.


Như vậy, khi một ô nhớ được đặt tên thì tên này đồng nhất
với giá trị của nó. Trong một chương trình, mỗi ơ nhớ có một
tên duy nhất nhưng giá trị của nó thì có thể thay đổi hoặc
khơng. Nếu giá trị của ơ nhớ có thể thay đổi được thì ơ nhớ này
<i>là một biến, tên của ơ nhớ là tên biến, ngược lại, nếu giá trị của </i>
<i>ơ nhớ khơng thể thay đổi, thì ơ nhớ là một hằng, tên của ô nhớ </i>
là tên hằng.


Các biến và hằng tham gia trong chương trình đều phải
được khai báo. Việc khai báo có tác dụng báo trước cho máy
dành sẵn các ơ nhớ thích hợp trong bộ nhớ để sẵn sàng chứa dữ
liệu.


<b>5.2. Khai báo biến và khai báo hằng</b>


<b>Biến là đại lượng có giá trị thay đổi được trong chương</b>
trình. Cách khai báo biến như sau:



</div>
<span class='text_page_counter'>(89)</span><div class='page_container' data-page=89>

Tên biến là tự đặt, theo đúng quy tắc của một tên.
Ví dụ:


<b>Var</b> i, j: Integer;
x, y: Real;


Theo khai báo trên, ta có hai biến i và j cùng kiểu số nguyên
(Integer), và hai biến x, y cùng kiểu số thực (Real).


<b>Hằng là một đại lượng có giá trị khơng đổi trong chương</b>
trình. Cách khai báo:


<b>Const</b> <b>Tên_hằng = giátrị;</b>


Tên hằng là tự đặt, theo đúng quy tắc của một tên.
Ví dụ:


<b>Const</b> N = 10;


SoPi = 3.1416;
SoE = 2.718;


Turbo Pascal có sẵn một số hằng chuẩn cho phép sử dụng
mà không phải khai báo, như: Pi, MaxInt. Hằng Pi có giá trị
bằng số  , còn MaxInt = 32767, là số Integer lớn nhất. Chẳng
hạn, có thể dùng các lệnh sau:


</div>
<span class='text_page_counter'>(90)</span><div class='page_container' data-page=90>

<i>Ví dụ: 3*5 div 2+7 mod 4 là biểu thức nguyên, có kết quả là</i>
10



<i>2+sin(pi/2) là biểu thức thực, có kết quả là 3.0</i>
<i>Chr(ord(‘a’)-32) là biểu thức ký tự, có kết quả là ‘A’</i>
<i>(4+2=6) and (‘B’<>‘b’) là biểu thức lơgic, kết quả là</i>
True


<i>‘AB’+’CD’là biểu thức chuỗi, có kết quả là ‘ABCD’</i>
Các thành phần trong biểu thức cần phải có kiểu dữ liệu phù
hợp để cho các phép toán thực hiện được, nếu không máy sẽ
báo lỗi. Ví dụ, biểu thức sau:


5 + ‘A’là sai vì khơng thể cộng số ngun với một ký tự.
Một biểu thức có thể chứa nhiều phép toán. Thứ tự thực
hiện các phép toán được cho trong bảng dưới đây:


<b>Cấp ưu tiên</b> <b>Phép toán</b>


1 biểu thức trong ngoặc đơn (...)


2 Các hàm


3 NOT, - (phép lấy dấu âm)


4 * , /, DIV, MOD, AND


5 Shl, Shr


6 +, - (trư?, OR, XOR


</div>
<span class='text_page_counter'>(91)</span><div class='page_container' data-page=91>

Việc tính tốn một biểu thức dựa theo hai quy tắc:



<i><b>Quy tắc 1: Phép toán có cấp ưu tiên nhỏ thì được tính trước, </b></i>
phép tốn có cấp ưu tiên lớn thì được tính sau.


<i><b>Quy tắc 2: Ðối với các phép toán đứng liền nhau và có cùng</b></i>
cấp ưu tiên, thì cái nào đứng trước được tính trước.


Ví dụ: Tính biểu thức số học:
(4+5)*2 div 7 + sin(pi/6)
= 9 * 2 div 7 + 0.5


= 18 div 7 + 0.5
= 2 + 0.5
= 2.5


Ví dụ: Tính biểu thức lơgic:


(2 > 4 div 2) or Not ( 49.25 + 2 < 50)
= (2 > 2) or Not ( 51.25 < 50)


= FALSE or Not FALSE
= FALSE or TRUE
= TRUE


</div>
<span class='text_page_counter'>(92)</span><div class='page_container' data-page=92>

<b>k:= 20;</b>
<b>Clrscr;</b>
<b>Writeln(k);</b>


Các lệnh rẽ nhánh và lệnh lặp được xếp vào loại có cấu trúc,
chúng được xây dựng từ các lệnh đơn giản.



Ví dụ:


<b>If k>=0 then</b>
<b>Writeln(k)</b>
<b>else</b>


<b>Writeln( -k);</b>


Hai hay nhiều lệnh đơn giản được gom lại và đặt giữa hai từ
khóa BEGIN và END tạo thành một câu lệnh ghép, câu lệnh
ghép cũng là lệnh có cấu trúc, ví dụ:


<b>Begin</b>


<b>Write(‘nhập k:’);</b>
<b>Readln(k);</b>


<b>End;</b>


Từ các lệnh đơn giản và các lệnh có cấu trúc đã có lại có thể
xây dựng được các lệnh có cấu trúc phức tạp hơn.


Ví dụ:


<b>If k>= 0 then</b>
<b>Writeln(k)</b>
<b>else</b>


<b>Begin</b>



</div>
<span class='text_page_counter'>(93)</span><div class='page_container' data-page=93>

<b>End;</b>


<b>6.2. Lệnh gán và lệnh chú giải</b>
<b>6.2.1.</b> <b>Câu lệnh gán</b>


Lệnh gán có cú pháp như sau:
<b>TênBiến:= Biểuthức;</b>


Ý nghĩa: tính tốn biểu thức bên phải, rồi lưu kết quả tính
được vào tên biến ở vế trái.


Ví dụ: cho khai báo:
<b>Var</b>


A, B: Real;
K: Integer;
Khi dùng lệnh các lệnh:


K:= 10;
B:= K* 3+5.5;


thì biến K có giá trị là 10, biến B có giá trị là 35.5.


Nếu thực hiện tiếp lệnh gán: B:= 17/2; thì giá trị của B bây
giờ sẽ là 8.5.


</div>
<span class='text_page_counter'>(94)</span><div class='page_container' data-page=94>

<i>Yêu cầu để cho lệnh gán thực hiện được là kiểu dữ liệu của </i>
<i>biểu thức ở vế phải phải phù hợp với kiểu dữ liệu của biến ở vế </i>
<i>trái, nếu khơng phù hợp thì khi dịch (Compile) chương trình,</i>


<i>Turbo Pascal sẽ thơng báo lỗi: "Error 26: Type mismatch".</i>


Ví dụ, lệnh gán dưới đây là sai vì vế trái là kiểu thực cịn vế
phải là kiểu chuỗi: A:=‘Pascal’;


<i>Chú ý rằng một số nguyên có thể gán cho một biến thực,</i>
<i>(chẳng hạn lệnh A:=10; là đúng ), nhưng một số thực khơng thể </i>
<i>gán cho một biến ngun. Ví dụ lệnh K:=10/4; là sai vì biến K </i>
có kiểu ngun, còn vế phải cho kết quả là một số thực (=2.5).


Xét thêm ví dụ về các kiểu dữ liệu khác:
Cho khai báo:


<b>Var</b>


Ch: Char;
St: String[20];
Khi đó:


Lệnh St:=‘A’; là đúng.
Lệnh St:=‘1234’; là đúng.


Lệnh Ch:=‘ABCD’; là sai vì vế phải là một chuỗi.
Lệnh St:= 100; là sai vì vế phải là một số.


Lệnh Ch:=‘1’; là đúng.


Lệnh Ch:=St; là sai vì vế phải là một chuỗi.
<b>6.2.2.</b> <b>Lời chú giải</b>



Lời chú giải có thể đặt tại bất kỳ chỗ nào trong chương trình
và được viết theo một trong hai cách:


</div>
<span class='text_page_counter'>(95)</span><div class='page_container' data-page=95>

(* lời giải thích *)


Lời giải thích là một chuỗi ký tự giải thích mục đích của
chương trình hay của một câu lệnh. Nó chỉ có tác dụng cho
người dùng tham khảo nhằm hiểu nhanh mục đích của chương
trình hay của một câu lệnh mà không cần phải đọc hết chương
trình hay câu lệnh đó.


<b>7. CÁC LỆNH NHẬP XUẤT DỮ LIỆU</b>
<b>7.1. Nhập dữ liệu, thủ tục Readln </b>


Nhập và xuất dữ liệu là hai khâu quan trọng trong quá trình
xử lý thơng tin. Hầu như chương trình nào cũng phải giải quyết
vấn đề nhập, xuất dữ liệu. Có nhập được dữ liệu thì mới có dữ
liệu để tính tốn hay xử lý. Có dữ liệu xuất ra thì mới biết được
kết quả của quá trình xử lý trong máy.


<b>7.1.1.</b> <b>Nhập dữ liệu kiểu số:</b>


Ðể nhập dữ liệu cho biến nguyên hay thực, ta dùng lệnh:
<b>Readln(biến1, biến2, ..., biếnk);</b>


trong đó biến1, biến2, ..., biếnk đã được khai báo và có kiểu dữ
liệu là nguyên hay thực.


</div>
<span class='text_page_counter'>(96)</span><div class='page_container' data-page=96>

10
6.5



4


Trong cả hai trường hợp ta đều được: x=10, y=6.5, và j=4.
Ngoài cách dùng một lệnh Readln(x, y, j); ta cũng có thể
nhập riêng cho từng biến bằng ba lệnh sau:


<b>Readln(x);</b>
<b>Readln(y);</b>
<b>Readln(j);</b>


<b>7.1.2.</b> <b>Nhập dữ liệu kiểu ký tự hay kiểu chuỗi</b>
Ta dùng lệnh:


<b>Readln( biến );</b>
Ví dụ, cho khai báo:


<b>Var</b>


Ho_ten: String[18];
Phai: String[3];
Khoi_thi: Char;


Muốn nhập dữ liệu cho ba biến Ho_ten, Phai, Khoi_thi ta
phải dùng ba lệnh:


<b>Readln(Ho_ten);</b>
<b>Readln(Phai);</b>
<b>Readln(Khoi_thi);</b>
Khi nhập, ta gõ:



</div>
<span class='text_page_counter'>(97)</span><div class='page_container' data-page=97>

<b>A</b>


Kết quả, ba biến sẽ có giá trị là: Ho_ten = ‘Tran Van
Thanh’, Phai= ‘nam’và Khoi_thi=‘A’.


Khác với dữ liệu số, ta không nên dùng một lệnh Readln để
nhập dữ liệu cho hai hay nhiều biến kiểu ký tự hay kiểu chuỗi,
vì sẽ có những nhầm lẫn khơng kiểm sốt được.


Ví dụ, không dùng lệnh sau:


Readln( Ho_ten, Phai, Khoi_thi);


mà phải dùng ba lệnh Readln, mỗi lệnh nhập cho một biến
như đã nêu ở trên.


<b>Các chú ý</b>


a) Dữ liệu nhập phải phù hợp với kiểu của biến. Nếu không
phù hợp thì chương trình sẽ dừng ngay và hiện thơng báo lỗi. Ví
dụ khi gặp lệnh Readln(j); mà ta gõ 4.5 thì bị lỗi vì j là biến
ngun, cịn 4.5 là số thực.


<b>b) Lệnh Readln;</b>


</div>
<span class='text_page_counter'>(98)</span><div class='page_container' data-page=98>

<b>Readln(x, y);</b>
<b>Readln(j);</b>


Nếu khi nhập, ta gõ: 12.5 20.6 10



thì x = 12.5, y = 20.6, cịn số 10 thừa bị xóa ln. Biến j trong
lệnh Readln(j) ở dưới không bị ảnh hưởng. Muốn nhập số 9 cho
j, ta gõ 9 .


Với đoạn chương trình:
<b>Read(x, y);</b>
<b>Readln(j);</b>


Nếu khi nhập, ta cũng gõ: 12.5 20.6 10


thì x = 12.5, y = 20.6, cịn số 10 thừa khơng bị xóa mà tự động
gán cho biến j trong lệnh Readln(j) tiếp theo, kết quả j =10 cho
dù ta chưa muốn nhập cho j.


Vậy, lệnh Read có thể làm sai ý đồ nhập của lệnh nhập tiếp
theo.


<i>Lời khuyên là không nên dùng lệnh Read, chỉ dùng Readln.</i>
<b>7.2. Câu lệnh xuất dữ liệu</b>


Các dữ liệu được in lên màn hình nhờ các lệnh sau:
<b>Writeln( bt1, bt2 , ... , btk );</b>


<b>Write( bt1, bt2 , ... , btk );</b>


ở đây, bt1, bt2, ..., btk là các biểu thức cần phải in giá trị lên
màn hình. Trong trường hợp đơn giản, mỗi biểu thức này có thể
là một biến, một hằng, hay một hàm.



</div>
<span class='text_page_counter'>(99)</span><div class='page_container' data-page=99>

này được in trên một dịng, nếu dài q khổ màn hình thì sẽ
được in tiếp ở dịng dưới.


Ví dụ, lệnh Writeln(3*2+9); sẽ in lên màn hình số 15.
Nếu i, j là các biến nguyên thì khi thực hiện các lệnh sau:


i:=10;
j:=15*2;


Writeln(i, j+1, 678);
trên màn hình sẽ hiện: 1031678.


Sự khác nhau giữa lệnh Writeln và Write là ở chỗ: sau khi
in xong giá trị của các biểu thức, lệnh Writeln sẽ đưa con trỏ
xuống đầu dòng dưới, cịn lệnh Write thì khơng. Ðiều này chỉ
ảnh hưởng đến lệnh in tiếp theo mà thơi.


Ví dụ, khi thực hiện hai lệnh sau:
<i><b>Writeln(‘lap trinh bang ‘);</b></i>
<i><b>Writeln(‘ngon ngu Pascal’);</b></i>
kết quả trên màn hình sẽ hiện hai dịng:


<i>lap trinh bang</i>
<i>ngon ngu Pascal</i>


</div>
<span class='text_page_counter'>(100)</span><div class='page_container' data-page=100>

<b>Writeln( biểuthức );</b>
sẽ in nguyên văn giá trị của biểu thức.


Ví dụ: Lệnh Writen(‘ket qua x=‘, 4+15); sẽ in ra: ket qua
x=19



Lệnh Writeln(‘A = ‘, 2*3<5); sẽ in ra: A=FALSE vì
biểu thức 2*3< 5 có kết quả là FALSE.


<i>Nếu gán: Ho_ten:=‘Tran Van Thanh’; thì lệnh </i>
<b>Writeln(‘Ho va ten: ‘, Ho_ten);</b>


sẽ in lên màn hình dịng chữ:


<i>Ho va ten: Tran Van Thanh</i>


Cần phân biệt hai đại lượng ‘Ho va ten: ‘và Ho_ten. Chúng
khác nhau hoàn toàn: ‘Ho va ten: ‘là một giá trị chuỗi, tức là
một hằng chuỗi nên sẽ được in ngun văn lên màn hình, cịn
Ho_ten là một biến kiểu chuỗi nên sẽ in giá trị mà biến này
đang chứa.


* Ðối với các biểu thức kiểu số thực thì lệnh:
<b>Writeln( biểuthức );</b>


sẽ in giá trị của biểu thức ra dưới dạng dấu chấm thập phân
di động có cả thảy 17 ký số, trong đó có 10 ký số trong phần
định trị, như sau:


</div>
<span class='text_page_counter'>(101)</span><div class='page_container' data-page=101>

Ví dụ: cho x, y là hai biến thực và gán x:=100/4; y:=-9/300;
thì hai lệnh sau:


Writeln(‘x= ‘, x);
Writeln(‘y= ‘, y);
sẽ in lên màn hình:



x = 2.5000000000E+01
y = -3.0000000000E-02
<b>7.2.2.</b> <b>In có</b> <b>định dạng</b>


<i>7.2.2.1. In số thực có định dạng</i>


In các số thực theo cách trên rất khó đọc. Vì thế các số thực
thường được in có định dạng, giống như cách viết số thông
thường, bằng lệnh:


<b>Writeln(biểuthức: n: k);</b>


Ở đây n và k là các số tự nhiên, ấn định dùng n cột để in giá
trị của biểu thức, trong đó có k cột dành cho phần thập phân.
Nếu số cần in có ít hơn n chữ số thì nó sẽ được in dồn về bên
phải và thêm các ký tự trắng ở bên trái cho đủ n cột.


</div>
<span class='text_page_counter'>(102)</span><div class='page_container' data-page=102>

Nếu n nhỏ hơn chiều dài của số cần in thì số sẽ được in ra
với đầy đủ các chữ số trong phần nguyên.


Ví dụ: khi thực hiện các lệnh sau:
x:=12345.675;


Writeln(‘x=‘,x:0:2);
trên màn hình sẽ hiện:


x=12345.68


Ở đây máy đã làm tròn số khi bỏ số lẻ cuối cùng.



<i>7.2.2.2. In kiểu nguyên, ký tự, chuỗi và lôgic có định dạng</i>
Dùng lệnh:


<b>Writeln(biểuthức: n);</b>


trong đó n là số nguyên ấn định số cột dùng để in giá trị của
biểu thức. Nếu n lớn hơn độ dài của giá trị cần in thì giá trị sẽ
được in dồn về bên phải, và thêm các khoảng trắng ở bên trái
cho đủ n cột. Nếu n nhỏ hơn độ dài của giá trị cần in thì giá trị
sẽ được in nguyên văn.


Ví dụ:


Lệnh Write(5+40:4); in ra: 45 (có 2 ký tự trắng trước
số 45)


Lệnh Write(5+40:1); in ra: 45 (in nguyên văn giá trị
45)


Lệnh Write(‘Pascal’:9); in ra: Pascal (có 3 ký tự trắng
trước chữ Pascal)


</div>
<span class='text_page_counter'>(103)</span><div class='page_container' data-page=103>

<b>Các chú ý</b>


- Nhóm ba lệnh: Write(x); Write(y); Write(j); chỉ có tác
dụng như một lệnh: Write(x, y, j);


- Nhóm ba lệnh: Write(x); Write(y); Writeln(j); chỉ có tác
dụng như một lệnh: Writeln(x, y, j);



<b>- Lệnh: Writeln; khơng in gì cả, chỉ đơn giản là đưa con trỏ </b>
xuống dịng dưới.


<b>+ Ví dụ:</b>


Dưới đây là chương trình cho phép nhập họ tên, mã số của
một sinh viên, rồi in họ tên, mã số của sinh viên đó trong một
cái khung được vẽ bằng các dấu sao *, như hình dưới chẳng
hạn:


**********************
* Nguyen Van Tuan *
* Ma so: 1972508 *


**********************
Chương trình cụ thể như sau:
<b>PROGRAM VIDU7_1;</b>


</div>
<span class='text_page_counter'>(104)</span><div class='page_container' data-page=104>

<b>Writeln;</b>


<b>Writeln(‘********************** ’);</b>
<i><b>{in 22 dấu *}</b></i>


<b>Writeln(‘*’, Ten:19, ‘*’:2);</b>


<i><b>{in 1 dấu *, in Ten chiếm 19 cột, in tiếp dấu * chiếm </b></i>
<i><b>2 cột}</b></i>


<b>Writeln(‘* Ma so:’, Maso:12, ‘*’:2);</b>



<i><b>{in * Ma so, in Maso chiếm 12 cột, in tiếp dấu * </b></i>
<i><b>chiếm 2 cột}</b></i>


<b>Writeln(‘**********************’);</b>
<i><b>{in 22 dấu *}</b></i>


<b>Readln;</b>
<b>End.</b>


<b>8. CÂU LỆNH RẼ NHÁNH</b>
<b>8.1. Câu lệnh IF</b>


<b>8.1.1.</b> <b>Câu lệnh IF dạng 1</b>
<i>* Cú pháp:</i>


<b>IF Ðiềukiện THEN</b> <b>LệnhP;</b>


</div>
<span class='text_page_counter'>(105)</span><div class='page_container' data-page=105>

<i>* Ý nghĩa: Tùy theo Ðiềukiện là đúng hay sai mà quyết định </i>
có làm LệnhP hay khơng. Nếu Ðiềukiện là đúng thì làm LệnhP
rồi chuyển sang lệnh kế tiếp ở phía dưới. Nếu Ðiềukiện là sai
thì khơng làm LệnhP mà chuyển ngay sang lệnh kế tiếp. Sơ
đồ?cú pháp của lệnh IF được vẽ trong hình 8.1.


<b>+ Ví dụ 8_1: Nhập vào hai số a và b, tìm và in lên màn hình</b>
số lớn nhất của hai số đó.


Ta dùng một biến phụ đặt tên là Max để chứa giá trị lớn
nhất phải tìm. Thuật tốn gồm ba bước:



</div>
<span class='text_page_counter'>(106)</span><div class='page_container' data-page=106>

- Hoặc là Max < b , tức b là số lớn nhất, khi đó giá trị lớn
nhất b được gởi vào biến Max


- Hoặc là Max >= b, tức giá trị của Max là lớn nhất rồi nên
không phải làm gì nữa.


Chương trình cụ thể như sau:
<b>PROGRAM VIDU8_1;</b>
<b>{Tim Max của hai so}</b>
<b>Var</b>


<b>a, b, max: Real;</b>
<b>Begin</b>


<b>Write(‘Nhap a va b:’);</b>
<b>Readln(a,b);</b>


<b>Max:=a;</b>


<b>If Max < b then Max:=b;</b>


<b>Writeln(‘So lon nhat la: ‘, Max:6:2);</b>
<b>Readln;</b>


<b>End.</b>
<i><b>Nhận xét</b></i>


* Việc tìm số nhỏ nhất của hai số a, b cũng tương tự, ta
dùng biến phụ Min chứa giá trị nhỏ nhất, và thực hiện các lệnh
sau:



<b>Min:=a;</b>


<b>If Min > b then Min:=b;</b>


</div>
<span class='text_page_counter'>(107)</span><div class='page_container' data-page=107>

cũng vẫn ký hiệu là Max. Dưới đây là các lệnh chính để tìm số
lớn nhất trong ba số a, b, c:


<b>Max:=a;</b>


<b>If Max< then Max:=b; {Max là số lớn nhất của a và b}</b>
<b>If Max<c then Max:=c; {Max là số lớn nhất của a, b và</b>
c}


<b>+ Ví dụ 8_2: Nhập vào họ tên và điểm trung bình (DTB)</b>
của một sinh viên. Hãy phân loại sinh viên theo DTB như sau:


Loại: Kém nếu DTB<5,
Tbình nếu 5  DTB<7,
Khá nếu 7  DTB<9,
Giỏi nếu DTB  9.


In họ tên, điểm trung bình và phân loại sinh viên.


<b>Trong chương trình, ta dùng một biến phụ đặt tên là Loai để </b>
lưu trữ phân loại của sinh viên. Vì có năm loại cần lưu trữ là
<b>các chuỗi ‘Kem’, ‘Tbinh’, ‘Kha’, ‘Gioi’, nên biến Loai phải có</b>
kiểu dữ liệu là kiểu chuỗi.


</div>
<span class='text_page_counter'>(108)</span><div class='page_container' data-page=108>

<b>Write(‘Nhap điem trung binh: ’);</b>


<b>Readln(DTB);</b>


{phân loại theo DTB}


<b>If DTB< 5 then Loai:=‘Kem’;</b>


<b>If (DTB>= 5) and (DTB<7) then Loai:=‘Tbinh’;</b>
<b>If (DTB >= 7) and (DTB< 9) then Loai:=‘Kha’;</b>
<b>If DTB >= 9 then Loai:=‘Gioi’;</b>


<b>Writeln(Ho_ten, #32 , DTB:4:1 , #32 , Loai); {#32 là</b>
ký tự trắng}


<b>Readln;</b>
<b>End.</b>


<b>8.1.2.</b> <b>Câu lệnh IF dạng 2</b>
<i>* Cú pháp:</i>


<b>IF Ðiềukiện THEN</b>
<b>LệnhP</b>


<b>ELSE</b>


<b>LệnhQ;</b>
<i><b>* Chú ý:</b></i>


<i>- Trước từ khóa ELSE khơng có dấu chấm phẩy. </i>


<i>- LệnhP và LệnhQ có thể là một lệnh ghép, tức là gồm nhiều </i>


<i>lệnh được đặt trong khối begin và end.</i>


<i>* Ý nghĩa của lệnh: </i>


<i>- Tùy theo Ðiềukiện là đúng hay sai mà quyết định làm một </i>
<i>trong hai lệnh: LệnhP hoặc LệnhQ . </i>


</div>
<span class='text_page_counter'>(109)</span><div class='page_container' data-page=109>

<i>- Ngược lại, nếu Ðiềukiện là sai thì khơng làm LệnhP mà</i>
<i>làm LệnhQ rồi chuyển sang lệnh kế tiếp ở sau LệnhQ. </i>


<i><b>+ Ví dụ 8_3: Ðể tìm số lớn nhất của hai số a và b, dùng</b></i>
<i>lệnh:</i>


<i><b>If a<b then Max:=b</b></i>
<i><b>else</b></i>


<i><b>Max:=a;</b></i>


</div>
<span class='text_page_counter'>(110)</span><div class='page_container' data-page=110>

<i><b>If a < b then</b></i>
<i><b>Begin</b></i>


<i><b>Max:= b;</b></i>
<i><b>Min:= a;</b></i>
<i><b>End</b></i>


<i><b>else {trước else khơng có dấu;} </b></i>
<i><b>Begin</b></i>


<i><b>Max:= a;</b></i>
<i><b>Min:= b;</b></i>


<i><b>End;</b></i>


<i><b>Writeln(‘So lon nhat la: ‘, Max:6:2);</b></i>
<i><b>Writeln(‘So nho nhat la: ‘, Min:6:2);</b></i>
<i><b>Readln;</b></i>


<i><b>End.</b></i>


<b>8.1.3.</b> <b>Câu lệnh IF lồng nhau </b>


<i>Trong câu lệnh IF, nếu LệnhP hoặc LệnhQ, hoặc cả hai, lại </i>
<i>là câu lệnh IF thì ta có cấu trúc IF lồng nhau. Chẳng hạn dưới </i>
<i>đây là hai câu lệnh IF... ELSE lồng nhau:</i>


<i><b>IF Ðiềukiện1 THEN</b></i>


<i><b>If Ðiềukiện2 then LệnhP</b></i>
<i><b>else</b></i>


<i><b>LệnhQ</b></i>
<i><b>ELSE</b></i>


</div>
<span class='text_page_counter'>(111)</span><div class='page_container' data-page=111>

<i><b>+ Ví dụ 8_4: Nhập vào họ tên một chủ hộ, chỉ số điện kế </b></i>
<i>tháng trước (chiso1) và chỉ số điện kế tháng này (chiso2), tính</i>
<i>tiền điện tháng này cho hộ, biết rằng:</i>


<i>Mỗi kW trong 60 kW đầu tiên có đơn giá là 5đ,</i>
<i>Từ kW thứ 61 đến kW thứ 160 có đơn giá 8đ,</i>
<i>Từ kW thứ 161 trở lên có đơn giá 10đ.</i>



<i>Ví dụ, ơng A có chỉ số điện tháng trước là chiso1=1020 và</i>
<i>chỉ số điện tháng này là chiso2=1070, lượng điện tiêu thụ tính </i>
<i>ra là Ldtt= 1070-1020=50, do lượng điện tiêu thụ < 60 nên số </i>
<i>tiền sẽ là:</i>


<i>Tien = 50*5= 250đ.</i>


<i>Nếu chiso2=1150 thì Ldtt = 1150-1020=130, do lượng điện </i>
<i>tiêu thụ vượt quá 60 kw nhưng chưa vượt quá 160 kw nên tiền </i>
<i>điện được tính là:</i>


<i>Tien=60*5 + (130-60) *8 = 860đ.</i>


<i>Nếu chiso2=1234, thì Ldtt = 1234-1020= 214, do lượng </i>
<i>điện tiêu thụ vượt quá 160 kw nên tiền điện sẽ là:</i>


<i>Tien=60*5+100*8+(214-160)*10=300+800+54*10=</i>
<i>1640 đ.</i>


</div>
<span class='text_page_counter'>(112)</span><div class='page_container' data-page=112>

<i><b>Readln(Ho_ten);</b></i>


<i><b>Write(‘Nhap chỉ số tháng trước, chỉ số tháng này: ‘);</b></i>
<i><b>Readln(chiso1, chiso2);</b></i>


<i><b>Ldtt:=chiso2- chiso1;</b></i>


<i><b>If Ldtt<= 60 then Tien:=Ldtt*5</b></i>
<i><b>else</b></i>


<i><b>if Ldtt <=160 then</b></i>



<i><b>Tien:=60*5+(Ldtt - 60)*8</b></i>
<i><b>else</b></i>


<i><b>Tien:=60*5 + 100*8 + (Ldtt - 160)*10;</b></i>
<i><b>Writeln(‘Họ và tên là ‘, Ho_ten);</b></i>


<i><b>Writeln(‘Tiền phải trả là ‘, Tien:10:2);</b></i>
<i><b>Readln;</b></i>


<i><b>End.</b></i>


<b>8.2. Câu lệnh CASE</b>


Trong một số trường hợp, khi phải lựa chọn một việc trong
nhiều việc thì các cấu trúc IF lồng nhau tỏ ra rắc rối, khó viết,
khó kiểm tra tính đúng đắn của nó. Việc dùng cấu trúc CASE
có thể khắc phục được nhược điểm này.


</div>
<span class='text_page_counter'>(113)</span><div class='page_container' data-page=113>

<b>CASE biểuthức OF</b>
<b>hằng1: LệnhP1;</b>
<b>hằng2: LệnhP2;</b>
<b>. . . .</b>


<b>hằngk: LệnhPk;</b>
<b>END;</b>


<b>Dạng 1</b>


<b>CASE biểuthức OF</b>


<b>hằng1: LệnhP1;</b>
<b>hằng2: LệnhP2;</b>
<b>. . . .</b>


<b>hằngk: LệnhPk;</b>
<b>ELSE LệnhQ;</b>
<b>END;</b>


<b>Dạng 2</b>
<b>Chú ý là lệnh CASE phải kết thúc bằng END;</b>


<i><b>* Các yêu cầu</b></i>


<i>- Kiểu dữ liệu của biểuthức chỉ có thể là nguyên, ký tự, </i>
lôgic, hoặc kiểu liệt kê hay kiểu đoạn con. Xin nhấn mạnh rằng:
biểuthức không được là kiểu thực hay kiểu chuỗi, và đây chính
là hạn chế của lệnh CASE so với lệnh IF.


<i>- Các hằng1, hằng2, ..., hằngk phải có kiểu dữ liệu phù hợp </i>
với kiểu dữ liệu của biểuthức.


</div>
<span class='text_page_counter'>(114)</span><div class='page_container' data-page=114>

+ .v.v.


+ Nếu giá trị của biểuthức = hằngk thì thực hiện LệnhPk, rồi
chuyển sang lệnh kế tiếp sau End, ngược lại:


a) chuyển ngay sang lệnh kế tiếp sau End (nếu là dạng 1)
b) thực hiện LệnhQ, rồi chuyển sang lệnh kế tiếp sau End
(nếu là dạng 2) .



Hình 8.4 và hình 8.5 là các sơ đồ của lệnh CASE vẽ cho
trường hợp k=3.


Trong hình vẽ , ta ký hiệu:
<b>G là giá trị của biểuthức</b>


<b>H1, H2, H3 là hằng1, hằng2, hằng3</b>


</div>
<span class='text_page_counter'>(115)</span><div class='page_container' data-page=115>

<b>+ Ví dụ 8_5: Nhập vào họ tên và năm sinh của một người, </b>
cho biết người này thuộc lứa tuổi nào: sơ sinh, nhi đồng, thiếu
niên, thanh niên, trung niên hay người lớn tuổi, biết rằng:


</div>
<span class='text_page_counter'>(116)</span><div class='page_container' data-page=116>

<b>Namsinh, Namnay, Tuoi: Integer;</b>
<b>Phanloai: String[14];</b>


<b>Begin</b>


<b>Write(‘Nhập họ và tên: ‘);</b>
<b>Readln(Ho_ten);</b>


<b>Write(‘Nhập năm sinh và năm nay: ‘);</b>
<b>Readln(Namsinh, Namnay);</b>


<b>Tuoi:=Namnay - Namsinh;</b>


<b>If Tuoi< 0 then writeln( ‘Nhập sai’)</b>
<b>else</b>


<b>Begin</b>



<b>Case Tuoi OF</b>


<b>0 ,1: Phanloai:= ‘sơ sinh’;</b>
<b>2 ..9: Phanloai:= ‘nhi đong’;</b>
<b>10 ..15: Phanloai:= ‘thieu niên’;</b>
<b>16 ..32: Phanloai:= ‘thanh nien’;</b>
<b>33 ..50: Phanloai:= ‘trung nien’;</b>
<b>else</b>


<b>Phanloai:= ‘nguoi lon tuoi’;</b>
<b>End; {hết Case}</b>


<b>Writeln(Ho_ten, #32 , Tuoi, #32 , Phanloai);</b>
<b>End;</b>


</div>
<span class='text_page_counter'>(117)</span><div class='page_container' data-page=117>

Trong ví dụ này, lệnh CASE dựa vào Tuổi để xác định lứa
<b>tuổi, kết quả lưu vào biến Phanloai. Ðóng vai trị hằng1 là hai</b>
số 0 và 1 viết cách nhau bởi dấu phẩy, và dịng:


<b>0,1: Phanloai:= ‘So sinh’;</b>


có nghĩa là khi Tuổi bằng 0 hoặc bằng 1 thì thực hiện lệnh gán:
<b>Phanloai:= ‘So sinh’;</b>


<b>Ðóng vai trị hằng2 là tất cả các số nguyên trong phạm vi từ </b>
2 đến 9, và dịng:


<b>2 ..9: Phanloai:= ‘nhi đong’;</b>


có nghĩa là khi Tuổi bằng một trong các số nguyên từ 2 đến 9


thì thực hiện lệnh gán: Phanloai:= ‘nhi đong’;


<b>+ Ví dụ 8_6: Xây dựng thực đơn cho phép lựa chọn một </b>
trong bốn việc: tính tổng, tính hiệu, tính tích hoặc tính thương
của hai số x, y nhập từ bàn phím.


Màn hình cần hiện ra bốn mục sau cho mọi người lựa chọn:
A. TÍNH TỔNG HAI SỐ


B. TÍNH HIỆU HAI SỐ
C. TÍNH TÍCH HAI SỐ
D. TÍNH THƯƠNG HAI SỐ


</div>
<span class='text_page_counter'>(118)</span><div class='page_container' data-page=118>

Chương trình được viết như sau:
<b>PROGRAM VIDU8_6;</b>


{Thực đơn}
<b>Uses Crt;</b>
<b>Var</b>


<b>x, y: Real;</b>
<b>Ch: Char;</b>
<b>Begin</b>


<b>Clrscr;</b>


<b>Write('Nhap x va y:');</b>
<b>Readln(x, y);</b>


<b>Gotoxy(10, 3); Write('A. TINH TONG HAI SO');</b>


<b>Gotoxy(10, 5); Write('B. TINH HIEU HAI SO');</b>
<b>Gotoxy(10, 7); Write('C. TINH TICH HAI SO');</b>
<b>Gotoxy(10, 9); Write('D. TINH THUONG HAI SO');</b>
<b>Gotoxy(2,11); Write('Chon muc nao (A, B, C, D)?');</b>


<b>Readln(Ch);</b>
<b>CASE Ch of</b>


<b>'A', 'a': Writeln('Tong =', x+y:6:2);</b>
<b>'B', 'b': Writeln('Hieu =', x-y:6:2);</b>
<b>'C', 'c': Writeln('Tich =', x*y:6:2);</b>
<b>'D', 'd': If y<>0 then</b>


</div>
<span class='text_page_counter'>(119)</span><div class='page_container' data-page=119>

<b>Writeln(‘Khong xac dinh !');</b>
<b>ELSE</b>


<b>Writeln('Khong co muc', Ch);</b>
<b>END;</b>


<b>Readln;</b>
<b>End.</b>


<b>Trong chương trình có sử dụng thủ tục: GOTOXY (m, n)</b>
thuộc thư viện CRT, có chức năng đặt con trỏ màn hình vào tọa
độ cột thứ m, dòng thứ n trên màn hình. Ví dụ lệnh Gotoxy (10,
3); đặt con trỏ màn hình vào tọa độ cột 10, dịng 3.


<b>+ Ví dụ 8_7: Nhập vào tháng và năm, cho biết tháng đó </b>
trong năm đó có bao nhiêu ngày.



Theo dương lịch:


Các tháng 4, 6, 9, và 11: có 30 ngày,


Các tháng 1, 3, 5, 7, 8, 10 và 12: có 31 ngày,


Riêng tháng 2 thì bình thường có 28 ngày, nhưng nếu
là năm nhuận thì có 29 ngày.


Cách xác định một năm là nhuận như sau:


</div>
<span class='text_page_counter'>(120)</span><div class='page_container' data-page=120>

<b>Var</b>


<b>Thang, Nam, Songay: Integer;</b>
<b>Nhuan: Boolean;</b>


<b>Begin</b>


<b>Write(‘Nhập Thang, Nam: ‘);</b>
<b>Readln(Thang, Nam);</b>


<b>If (Thang<1) or (Thang>12) then</b>
<b>writeln(‘Nhập sai ’)</b>


<b>else</b>
<b>Begin</b>


<b>Case Thang OF</b>


<b>4, 6, 9, 11: Songay:=30;</b>



<b>1, 3, 5, 7, 8, 10, 12: Songay:=31;</b>
<b>2: Begin</b>


<b>Nhuan:=</b> <b>(Nam</b> <b>mod</b> <b>400=0)</b> <b>or</b>
<b>((Nam mod 100<>0) and (Nam mod</b>
<b>4=0));</b>


<b>If Nhuan= TRUE then</b>
<b>Songay:=29</b>


<b>else</b>


<b>Songay:=28;</b>
<b>End;</b>


<b>End; {Hết Case}</b>


</div>
<span class='text_page_counter'>(121)</span><div class='page_container' data-page=121>

<b>Readln;</b>
<b>End.</b>


Trong ví dụ này, khi Tháng=2 thì phải làm hai lệnh được
đặt trong khối begin và end, đó chính là một lệnh ghép:


<b>Begin</b>


<b>Nhuan:= (Nam mod 400=0) or ((Nam mod 100<>0)</b>
<b>and (Nam mod 4=0));</b>


<b>If Nhuan=TRUE then Songay:=29 else Songay:=28;</b>


<b>End;</b>


<b>* Câu lệnh CASE lồng nhau: </b>


Trong cấu trúc CASE, khi một trong các LệnhP1,
LệnhP2,..., LệnhPk hay LệnhQ lại là một lệnh CASE thì ta có
cấu trúc CASE lồng nhau.


<b>+ Ví dụ 8_8: Một xí nghiệp tính tiền thưởng hàng tháng cho</b>
cơng nhân theo cơng thức: Tiền thưởng = Hệ số * 200.


Trong đó Hệ số được tính dựa vào kết quả bình chọn phân
loại lao động (loại A, B hay C) và nơi làm việc (cơ sở 1 hay cơ
sở 2) của mỗi người trong tháng, cụ thể như sau:


</div>
<span class='text_page_counter'>(122)</span><div class='page_container' data-page=122>

Ví dụ nếu ông X được xếp loại A và làm việc ở cơ sở 1 thì
có hệ số thưởng là 2.0, nên tiền thưởng là =2.0*200=400.


Viết chương trình nhập họ tên, phân loại lao động và nơi
làm việc của một cơng nhân, tính tiền thưởng cho người đó.


<b>PROGRAM VIDU8_8;</b>


{Tính tiền thưởng cho cơng nhân}
<b>Var</b>


<b>Ho_ten: String[20];</b>
<b>Loai: Char;</b>


<b>Coso: Byte;</b>



<b>Heso, Thuong: Real;</b>
<b>Begin</b>


<b>Write(‘Nhập họ và tên: ‘);</b>
<b>Readln(Ho_ten);</b>


<b>Write(‘Nhập cơ sở làm việc (1,2): ‘);</b>
<b>Readln(Coso);</b>


<b>Write(‘Nhập phân loại lao động (A,B,C): ‘);</b>
<b>Readln(Loai);</b>


<b>CASE Loai OF</b>
<b>‘A’, ‘a’: Case Coso of</b>


<b>1: Heso:=2.0;</b>
<b>2: Heso:=2.5;</b>
<b>End;</b>


</div>
<span class='text_page_counter'>(123)</span><div class='page_container' data-page=123>

<b>2: Heso:=1.8;</b>
<b>End;</b>


<b>‘C’, ‘c’: Heso:=1.0;</b>
<b>END; {Hết CASE}</b>
<b>Thuong:=Heso*200;</b>


<b>Writeln(‘Họ và tên Tiền thưởng ‘);</b>
<b>Writeln(Ho_ten , Thuong:8:2 );</b>
<b>Readln;</b>



<b>End.</b>


<b>So sánh lệnh Case với lệnh If</b>


<b>+ Lệnh If và lệnh Case đều là các câu lệnh rẽ nhánh, cho </b>
phép lựa chọn một công việc trong nhiều công việc được lựa
<i>chọn. Nhưng cấu trúc If tổng quát và mạnh hơn cấu trúc Case vì</i>
lệnh If khơng hạn chế gì cả, cịn lệnh Case thì u cầu biểu thức
và các hằng phải thuộc kiểu dữ liệu đếm được: nguyên, ký tự,
<i>lôgic, liệt kê hay đoạn con, không được là kiểu thực hay chuỗi.</i>


+ Lệnh Case nào cũng có thể thay thế tương đương bằng
các lệnh If. Ví dụ lệnh Case trong chương trình nói trên (Ví dụ
8.9) có thể thay bằng ba lệnh If sau:


</div>
<span class='text_page_counter'>(124)</span><div class='page_container' data-page=124>

+ Việc sử dụng lệnh Case trong nhiều trường hợp có tác
dụng làm rõ ràng và nổi bật bố cục của một đoạn chương trình,
từ đó dễ đọc, dễ hiểu hơn.


Thơng thường, người ta dùng lệnh Case để thay thế các cấu
trúc If lồng nhau khi có nhiều (ba, bốn,...) tình huống rẽ nhánh
và khi điều kiện cho phép.


Các bạn hãy viết lại các chương trình trong các ví dụ 8_5,
8_6, 8_7, 8_8 nhưng thay lệnh Case bằng các lệnh If.


<b>9. CÂU LỆNH LẶP FOR</b>
<b>9.1. Dạng 1</b>



<i>Cú pháp:</i>


<b>FOR biến:= m1 TO m2 DO LệnhP;</b>
<i>+ Yêu cầu</i>


<b>biến phải thuộc kiểu dữ liệu đơn giản đếm được, thường là</b>
kiểu nguyên, ký tự hay lôgic, không thể là kiểu thực hay chuỗi.


<b>m1, m2 là các biểu thức có cùng kiểu dữ liệu với biến.</b>
<b>LệnhP có thể là một lệnh đơn giản, lệnh có cấu trúc, hoặc là</b>
một lệnh ghép gồm nhiều lệnh đặt trong khối begin và end.


<b>Hình 9.1 là sơ đồ khối của lệnh For với b là viết tắt của </b>
<b>biến.</b>


<i>+ Cách thức hoạt động của FOR </i>
<i>Bước 1: Gán giá trị biến:= m1;</i>


<i>Bước 2: Nếu biến  m2 thì làm LệnhP, rồi sang bước 3;</i>
Nếu biến > m2 thì khơng làm LệnhP mà chuyển
sang lệnh kế tiếp ở phía dưới.


</div>
<span class='text_page_counter'>(125)</span><div class='page_container' data-page=125>

Quay lại bước 2.


Tóm lại, LệnhP sẽ được làm đi làm lại, bắt đầu khi
biến=m1, và kết thúc khi biến=m2+1, cả thảy là m2-m1+1 lần.
Vì thế, người ta gọi FOR là vịng lặp có số lần lặp đã biết trước.


</div>
<span class='text_page_counter'>(126)</span><div class='page_container' data-page=126>

Bước 3: gán S:=S+3*3; {S=12+22+32}
.v.v.



Bước 10: gán S:=S+10*10; {được S=12+22+32+...+102}
<i>Quá trình từ bước 1 đến bước 10 được gọi là phép cộng dồn</i>
vào biến S. Tại bước thứ i, lấy giá trị của biến S cộng với i2, kết
quả lại được gán cho biến S, do đó giá trị của biến S được tăng
thêm một lượng bằng i2. Khi i thay đổi từ 1 đến 10 thì các số 12,
22, 32, ..., 102đều được cộng vào S, kết quả là sau bước thứ 10
giá trị của S đúng bằng tổng 12+ 22+ 32+ ... + 102.


Tóm lại, lệnh: S:=S + i*i; được làm cả thảy 10 lần, ứng với
i=1, 2, ..., 10. Quá trình này được diễn đạt bằng lệnh FOR, như
sau:


<b>For i:=1 To 10 DO S:=S+ i*i;</b>


Một cách tổng quát, để tính tổng: S=12 + 22+ 32+...+ N2,
trong đó N là một số nguyên dương bất kỳ, ta dùng hai lệnh:


<b>S:=0;</b>


<b>For i:=1 To N DO S:=S+ i*i;</b>
Dưới đây là chương trình cụ thể:
<b>PROGRAM VIDU9_1;</b>


{Tính tổng bình phương các số tự nhiên <=N}
<b>Var</b>


<b>N, i: Integer;</b>
<b>S: LongInt;</b>
<b>Begin</b>



<b>Write(‘Nhập N:’); Readln(N);</b>
<b>S:=0;</b>


</div>
<span class='text_page_counter'>(127)</span><div class='page_container' data-page=127>

<b>Writeln(‘S= ‘, S);</b>
<b>Readln;</b>


<b>End.</b>


<i>Mở rộng bài tốn tính tổng: Tính tổng đan dấu: </i>
S = 12- 22+ 32- 42+...+(-1)N-1N2


Ta viết:


S = 12+ (- 22) + 32+ (- 42) + ... +(-1)N-1N2


Nhận thấy, số hạng thứ i của vế phải có giá trị tuyệt đối
bằng i2, mang dấu cộng nếu i lẻ, mang dấu trừ nếu i chẵn. Nói
cách khác, ta sẽ cộng dồn i2vào S nếu i lẻ, và cộng dồn (- i2 )
vào S nếu i chẵn. Việc xác định i lẻ hay chẵn dựa vào hàm
Odd(i) hay kết quả của phép toán i Mod 2. Vậy, các lệnh sẽ
dùng là:


<b>S:=0;</b>


<b>For i:=1 To N DO</b>


<b>if i mod 2 <> 0 then S:=S+ i*i else S:= S- i*i;</b>


Các bạn hãy viết chương trình để tính tổng đan dấu này.


<i><b>+ Ví dụ 9_2: Bài tốn tính tích:</b></i>


</div>
<span class='text_page_counter'>(128)</span><div class='page_container' data-page=128>

Bước 10: gán S:=S*10; {được S=1*2*3*...*10 =10!}
<i>Nếu trong ví dụ 1, ta phải cộng dồn vào biến S thì trong ví</i>
<i>dụ này ta phải nhân dồn vào biến S. Tại bước thứ i, lấy giá trị </i>
của biến S nhân với i, rồi lại gán kết quả cho biến S. Khi i thay
đổi từ 1 đến 10 thì S sẽ tích lũy đủ các thừa số 1, 2, 3,...,10, và
giá trị của S sau bước thứ 10 đúng bằng 1*2*3*...*10 =10!.


Quá trình thực hiện từ bước 1 đến bước thứ 10 được mô tả
bằng câu lệnh For:


<b>For i:=1 to 10 DO S:=S*i;</b>


Một cách tổng quát, để tính tích: S= 1*2*...*N , trong đó N
là một số nguyên dương bất kỳ, ta dùng hai lệnh:


<b>S:=1;</b>


<b>For i:=1 To N DO S:=S* i;</b>
Dưới đây là chương trình cụ thể:
<b>PROGRAM VIDU9_2;</b>


<b>{Tính S=N!}</b>
<b>Var</b>


<b>N, i: Integer;</b>
<b>S: LongInt;</b>
<b>Begin</b>



<b>Write(‘Nhập số dương N: ‘); Readln(N);</b>
<b>S:=1;</b>


<b>For i:=1 to N do S:=S * i;</b>
<b>Writeln(‘Giai thua = ‘, S);</b>
<b>Readln;</b>


</div>
<span class='text_page_counter'>(129)</span><div class='page_container' data-page=129>

<i><b>+ Ví dụ 9_3: Bài tốn tính lũy thừa:</b></i>


Nhập số tự nhiên N và một số thực x bất kỳ, tính S= xN.


Tương tự như tính N!: đầu tiên ta gán S:=1, sau đó tại mỗi
bước lặp, ta nhân dồn x vào S bằng lệnh S:=S*x. Sau N bước
như vậy, S sẽ được nhân với x đúng N lần. Vậy hai lệnh cần
dùng là:


<b>S:=1;</b>


<b>For i:=1 to N do S:=S*x;</b>
Dưới đây là chương trình cụ thể:
<b>PROGRAM VIDU9_3;</b>


<b>{Tính S=lũy thừa N của x}</b>
<b>Var</b>


<b>N, i: Byte;</b>
<b>S, x: Real;</b>
<b>Begin</b>


</div>
<span class='text_page_counter'>(130)</span><div class='page_container' data-page=130>

<b>+ Ví dụ 9_4: In bảng các chữ cái từ A đến Z thành bốn cột </b>


như sau:


KÝ TỰ MÃ KÝ TỰ MÃ


A 65 a 97


B 66 b 98


Yêu cầu in thành từng trang màn hình, mỗi trang 15 dịng.
<i>Trong chương trình ta dùng biến Dem để đếm số dịng đã in,</i>
<i>mỗi khi in xong một dịng thì biến Dem được cộng thêm 1. Khi</i>
<i>Dem = 15, 30, 45, ... (tức Dem mod 15=0) thì phải làm lệnh </i>
Readln; lệnh này sẽ dừng màn hình cho đến khi ta gõ Enter mới
in tiếp.


<b>PROGRAM VIDU9_4;</b>
<b>{In bảng các chữ cái}</b>
<b>Uses Crt;</b>


<b>Var</b>


<b>ch, ch1: Char;</b>
<b>Dem: Integer;</b>
<b>Begin</b>


<b>Clrscr;</b>


<b>Writeln(‘Ky tu # Ma</b> <b>#</b> <b>Ky tu #</b> <b>Ma’);</b>
<b>Dem:=0;</b>



<b>For ch:=‘a’to ‘z’do</b>
<b>Begin</b>


<b>ch1:=Upcase(ch);</b>


</div>
<span class='text_page_counter'>(131)</span><div class='page_container' data-page=131>

<b>If Dem mod 15 = 0 then</b>
<b>Begin</b>


<b>Write(‘Enter để xem tiếp‘);</b>
<b>Readln;</b>


<b>End;</b>
<b>End;</b>


<b>Writeln(‘HET‘);</b>
<b>Readln;</b>


<b>End.</b>


Chương trình trên là một ví dụ về cách dùng biến chạy kiểu
ký tự (ch) trong lệnh FOR, ngồi ra, đóng vai trò LệnhP là một
lệnh ghép, gồm nhiều lệnh đặt trong khối begin và end.


<b>9.2. Dạng 2 </b>
<i>+ Cú pháp</i>


<b>FOR biến:= m2 DOWNTO m1 DO LệnhP;</b>
<i>+ Cách thức hoạt động của FOR dạng 2 </i>


<i><b>Bước 1: Gán giá trị biến:= m2;</b></i>



</div>
<span class='text_page_counter'>(132)</span><div class='page_container' data-page=132>

<b>+ Ví dụ 9_5: Ðể tính S= N!, ta có thể viết:</b>
S=N*(N-1)*(N-2)*...*2*1


Cách viết cho thấy ngay cách tính: đầu tiên gán S:=1, sau đó
thực hiện việc nhân dồn S:=S* i với i= N, N-1,..., 2, 1, tức là:


<b>S:=1;</b>


<b>For i:=N downto 1 do S:=S* i;</b>


Tương tự, để tính S=xN, ta cũng có thể dùng FOR dạng 2:
<b>S:=1;</b>


<b>For i:=N downto 1 do S:=S*x;</b>


</div>
<span class='text_page_counter'>(133)</span><div class='page_container' data-page=133>

<b>+ Ví dụ 9_6: In các chữ cái theo thứ tự ngược từ Z đến A </b>
thành hai dòng:


Z, Y, X, ..., C, B, A
z, y, x, ... , c, b, a


Chương trình được viết như sau:
<b>PROGRAM VIDU9_6;</b>


<b>{In các chữ cái theo thứ tự đảo ngược từ Z đến A}</b>
<b>Var</b>


<b>Ch: Char;</b>
<b>Begin</b>



<b>For ch:=‘Z’downto ‘A’do write(ch:3);</b>
<b>Writeln;</b>


<b>For ch:=‘z’downto ‘a’do write(ch:3 );</b>
<b>Writeln;</b>


<b>Readln;</b>
<b>End.</b>


<b>9.3. Câu lệnh FOR lồng nhau</b>


</div>
<span class='text_page_counter'>(134)</span><div class='page_container' data-page=134>

Bây giờ tăng: biến1:=Succ(biến1), rồi lại làm lệnh FOR ở
dòng {2}, kết quả lệnhP được làm thêm n2-n1+1 lần nữa.


Quá trình trên cứ tiếp tục cho đến khi biến1=m2+1 thì dừng.
Lệnh FOR {1} làm m2-m1+1 lần lệnh FOR {2}, còn chính
lệnh FOR {2} lại làm n2-n1+1 lần LệnhP. Vì thế lệnhP được
làm cả thảy là (m2-m1+1)*(n2-n1+1) lần.


<b>+ Ví dụ 9_7: In hình chữ nhật đặc như dưới đây:</b>


Ta thấy mỗi dịng gồm m chữ A, tức là chữ A được in liên
tiếp cả thảy m lần, việc này được làm bằng lệnh:


<b>For j:=1 to m do write(‘A’);</b>


Lệnh Write in m chữ A trên một dòng. In xong, con trỏ vẫn
nằm ở cuối dịng đó, vì thế trước khi in dịng tiếp theo, cần phải
đưa con trỏ xuống dòng dưới bằng lệnh:



<b>Writeln;</b>


<b>Tóm lại, muốn in dịng thứ i, cần phải làm hai lệnh:</b>
<b>For j:=1 to m do write(‘A’);</b>


<b>Writeln;</b>


</div>
<span class='text_page_counter'>(135)</span><div class='page_container' data-page=135>

<b>Thay In dịng i bằng hai lệnh nói trên (đặt trong khối begin </b>
... end), ta có thuật tốn để in hình chữ nhật đặc là:


<b>For i:=1 to n do</b>
<b>Begin</b>


<b>for j:=1 to m do write(‘A’);</b>
<b>Writeln;</b>


<b>End;</b>


Các bạn hãy viết chương trình cụ thể cho ví dụ này, ở đây m
và n là hai số nguyên dương nhập từ bàn phím.


<b>9.4. Các ứng dụng khác của lệnh FOR</b>


Lệnh For rất thông dụng, dễ dùng và giải quyết được nhiều
bài toán trong khoa học kỹ thuật và trong thực tiễn. Dưới đây
chỉ xin nêu hai ứng dụng .


<i><b>+ Ví dụ 9_8: Tìm các số Fibonaci.</b></i>



Dãy số Fibonaci {1, 1, 2, 3, 5, 8, 13, 21,...} được xây dựng
như sau:


U0=1, U1=1 , Uk=Uk-1+ Uk-2với mọi k= 2, 3, 4, ...


Gọi U là số hạng thứ k, U0 và U1 lần lượt là hai số hạng


</div>
<span class='text_page_counter'>(136)</span><div class='page_container' data-page=136>

Kết quả là Uo=1 và U1=2.


Bước 2: tính U:=U0+U1và in U. Lúc này U=3 chính là U3.


Ðể chuẩn bị tính U4, ta lại cho U0đóng vai trị của U1và U1


đóng vai trị của U, tức là gán:
U0:=U1;


U1:=U;


Kết quả là U0=2 và U1=3.


.v.v.


Tóm lại các lệnh phải lặp đi lặp lại là:
U:=U0+U1;


U0:=U1;


U1:=U;


Vì sang bước sau thì giá trị của U sẽ bị thay đổi nên tại mỗi


bước ta đều phải in U. Chương trình được viết như sau:


<b>PROGRAM VIDU9_8;</b>
{In N+1 số Fibonaci đầu tiên}
<b>Var</b>


<b>N, i, U, Uo, U1: Integer;</b>
<b>Begin</b>


<b>Write(‘Nhập N:’);</b>
<b>Readln(N);</b>


<b>Uo:=1;</b>
<b>U1:=1;</b>


</div>
<span class='text_page_counter'>(137)</span><div class='page_container' data-page=137>

<b>For i:=2 to N do</b>
<b>Begin</b>


<b>U:=Uo+U1;</b>
<b>Write(U:3);</b>
<b>Uo:=U1;</b>
<b>U1:=U;</b>
<b>End;</b>
<b>Readln;</b>
<b>End.</b>


<i><b>+ Ví dụ 9_9: Bài tốn tính tiền lãi gửi ngân hàng:</b></i>


Nhập tiền vốn ban đầu, số tháng gửi N và lãi suất hàng
tháng. Tính số tiền nhận được sau mỗi tháng gửi biết rằng tiền


lãi hàng tháng được gộp vào tiền vốn.


Ví dụ, tiền vốn là100, lãi suất tháng là 2%. Sau 1 tháng gửi
sẽ có số tiền là:


Số tiền=100 + 100*0.02 = 102
Sau 2 tháng gửi sẽ có số tiền là:


Số tiền=102 + 102*0.02 = 104.04


</div>
<span class='text_page_counter'>(138)</span><div class='page_container' data-page=138>

<b>Var</b>


<b>Tienvon, Laisuat, Sotien: Real;</b>
<b>N, i: Byte;</b>


<b>Begin</b>


<b>Write(‘Nhập tiền vốn, lãi suất và số tháng gửi: ‘);</b>
<b>Readln(Tienvon, Laisuat, N);</b>


<b>For i:=1 to N do</b>
<b>Begin</b>


<b>Sotien:= Tienvon + Tienvon*Laisuat;</b>


<b>Writeln(‘Số tiền sau‘, i ,‘tháng=‘, Sotien:8:2);</b>
<b>Tienvon:=Sotien;</b>


<b>End;</b>
<b>Readln;</b>


<b>End.</b>


<b>10. CÂU LỆNH LẶP WHILE VÀ REPEAT</b>
<b>10.1. Câu lệnh While</b>


<i>+ Cú pháp:</i>


<b>WHILE Ðiềukiện DO LệnhP;</b>


<i>+ Ý nghĩa: Chừng nào Ðiềukiện còn đúng thì cứ làm LệnhP, </i>
cho đến khi Ðiềukiện sai thì không làm LệnhP nữa mà chuyển
sang lệnh kế tiếp ở phía dưới.


<i>+ Cách thức hoạt động của WHILE: </i>


</div>
<span class='text_page_counter'>(139)</span><div class='page_container' data-page=139>

Lệnh P được gọi là thân của vòng lặp WHILE.


Nếu Ðiềukiện khơng bao giờ sai thì LệnhP sẽ phải làm hồi,
lúc đó ta có vịng lặp vơ hạn. Trong trường hợp này, để dừng
chương trình, hãy gõ đồng thời hai phím Ctrl và Pause (viết tắt
là ^Pause).


Ðể tránh các vịng lặp vơ hạn, trong thân của vịng WHILE
cần có ít nhất một lệnh có tác dụng làm biến đổi các đại lượng
tham gia trong Ðiềukiện để đến một lúc nào đó thì Ðiềukiện sẽ
sai và do đó vòng lặp sẽ kết thúc.


</div>
<span class='text_page_counter'>(140)</span><div class='page_container' data-page=140>

<b>Write(‘Nhập N > 0: ‘); </b>
<b>Readln(N);</b>



<b>S:=1;</b>


<b>i:=1;</b> {9}
<b>While i<= N do</b>


<b>Begin</b>


<b>S:=S*i;</b>


<b>i:=i+1;</b> <b>{13}</b>
<b>End;</b>


<b>Writeln(‘Giai thua = ‘, S);</b>
<b>Readln;</b>


<b>End.</b>


Khởi đầu biến i được gán giá trị 1 (dòng {9}). Trong vòng
lặp WHILE, sau mỗi lệnh S:=S*i; biến i được tăng lên 1 đơn vị
bằng lệnh i:=i+1; (dịng {13}). Khi i=N+1 thì điều kiện i<=N bị
sai và lúc đó vịng lặp kết thúc, kết quả là lệnh S:=S*i; được
thực hiện đúng N lần ứng với i=1, 2, 3, ..., N.


Trong chương trình trên, nếu khơng có dịng lệnh {13}:
i:=i+1;


thì i ln ln bằng 1 nên điều kiện i<=N ln ln đúng (vì N
 1), và do đó vịng lặp sẽ vô hạn .


Sự khác nhau của lệnh WHILE so với FOR là ở chỗ: trong


lệnh FOR, biến i được tự động gán giá trị ban đầu và sau mỗi
bước lặp được tự động tăng lên, còn trong WHILE thì khơng, ta
phải viết các lệnh đó.


</div>
<span class='text_page_counter'>(141)</span><div class='page_container' data-page=141>

<i>tốn dạng này là số lần lặp của các vòng lặp đã được biết </i>
<i>trước.</i>


<i>Lệnh WHILE đặc biệt thích hợp với các vịng lặp có số lần </i>
<i>lặp chưa biết trước, trong khi lệnh FOR khơng giải quyết được. </i>
Ðây chính là điểm mạnh của lệnh WHILE. Hãy xem ví dụ sau.


<b>+ Ví dụ 10_2: Trở lại bài toán tính tiền gửi ngân hàng có</b>
tiền lãi hàng tháng gộp vào vốn (ví dụ 9.9). Câu hỏi bây giờ là:
<i>cần gửi tối thiểu là bao nhiêu tháng để có được số tiền S cho </i>
<i>trước.</i>


Giả sử tiền vốn là 100, lãi suất hàng tháng là 2%, số tiền cần
có là S=108. Ta tính số tiền có được sau mỗi tháng gửi:


Sau 1 tháng gửi: Số tiền=100+100*0.02 = 102
Sau 2 tháng gửi: Số tiền=102+102*0.02 = 104.04


Sau 3 tháng gửi: Số tiền=104.04+104.04*0.02= 106.1208
Sau 4 tháng gửi: Số tiền=106.1208+106.1208*0.02=
108.2432


Vậy chỉ cần gửi N=4 tháng, số tiền sẽ có là 108.2431.
Q trình lặp kết thúc khi tới tháng đầu tiên có Số tiền  S.
Chương trình như sau:



</div>
<span class='text_page_counter'>(142)</span><div class='page_container' data-page=142>

<b>Readln(Tienvon, Laisuat, S);</b>
<b>Sotien:=Tienvon;</b>


<b>N:=0; {N là số tháng gửi}</b>
<b>While Sotien< S do</b>


<b>Begin</b>
<b>N:=N+1;</b>


<b>Sotien:= Tienvon + Tienvon*Laisuat;</b>
<b>Tienvon:=Sotien;</b>


<b>End;</b>


<b>Writeln(‘Cần gửi‘, N , ‘tháng‘);</b>
<b>Writeln(‘Số tiền sẽ có = ‘, Sotien:6:2);</b>
<b>Readln;</b>


<b>End.</b>


<b>Số lần lặp của lệnh: While Sotien < S do . . . không phải do </b>
<b>ta ấn định từ trước mà tùy thuộc vào biểu thức Sotien < S là</b>
mau bị sai hay chậm bị sai. Số lần lặp ít hay nhiều phụ thuộc
vào giá trị S nhỏ hay lớn và vào tốc độ tăng nhanh hay chậm
của số tiền.


<b>10.2. Câu lệnh Repeat </b>
<i>+ Cú pháp:</i>


<b>REPEAT</b>


<b>LệnhP;</b>


<b>UNTIL Ðiềukiện;</b>


</div>
<span class='text_page_counter'>(143)</span><div class='page_container' data-page=143>

<i>+ Cách thức hoạt động của REPEAT: </i>


<i><b>Bước 1: Làm LệnhP, rồi kiểm tra Ðiềukiện, nếu Ðiềukiện </b></i>
đúng thì chuyển sang lệnh tiếp theo ở phía dưới, ngược lại, nếu
Ðiềukiện sai thì quay lại bước 1.


<i>LệnhP cũng được gọi là thân của vòng lặp REPEAT, nếu nó </i>
<i><b>gồm nhiều lệnh thì các lệnh đó khơng cần phải đặt trong khối</b></i>
<b>Begin và End.</b>


</div>
<span class='text_page_counter'>(144)</span><div class='page_container' data-page=144>

<i><b>+ Ví dụ 10_3: Ðảm bảo tính hợp lý của dữ liệu nhập từ bàn</b></i>
<i>phím.</i>


Khi giải phương trình bậc hai Ax2+Bx+C=0, ta thường giả
thiết A≠0, khi tính S=N!, ta thường yêu cầu N≥0. Sự hạn chế
phạm vi đối với các dữ liệu nhập sẽ đảm bảo tính hợp lý của
chúng và làm giảm bớt các phức tạp khi biện luận.


Ðể buộc người sử dụng phải nhập A0, nếu nhập A=0 thì
bắt nhập lại cho tới khi nhập A0 mới thơi, ta dùng cấu trúc:


<b>Repeat</b>


<b>Write(‘Nhập A khác không: ‘);</b>
<b>Readln(A);</b>



<b>Until A<> 0;</b>


Ðể đảm bảo chắc chắn nhập N thỏa điều kiện 0<N<20, ta
dùng cấu trúc:


<b>Repeat</b>


<b>Write(‘Nhập N (0<N<20): ‘);</b>
<b>Readln(N);</b>


<b>If (N<=0) or (N>=20) then write(#7);</b>
<b>Until (0<N) and (N<20);</b>


Lệnh write(chr(7) ) hay write(#7) có cơng dụng phát ra
tiếng kêu bip để cảnh báo người dùng đã nhập dữ liệu sai u
cầu.


<i><b>+ Ví dụ 10_4: Tìm bội số chung nhỏ nhất của hai số nguyên</b></i>
<i>dương M và N.</i>


</div>
<span class='text_page_counter'>(145)</span><div class='page_container' data-page=145>

Vì N>M nên ta sẽ tìm trong tập các bội số của N: {9, 18, 27,
36, 45, ...} số nhỏ nhất chia hết cho M, đó là số 45.


Một cách tổng quát, gọi Max là số lớn nhất của M và N.
Ðầu tiên ta gán:


BSCNN:=0;


Sau đó cứ làm lệnh BSCNN:=BSCNN+Max; hồi cho đến
khi BSCNN chia hết cho cả M và N thì dừng.



Trong chương trình ta dùng lệnh repeat để nhập hai số M, N
đảm bảo dương.


<b>PROGRAM VIDU10_4;</b>
{Tìm BSCNN của M và N}
<b>Var</b>


<b>M, N, Max, BSCNN: Integer;</b>
<b>Begin</b>


<b>Repeat</b>


<b>Write(‘Nhập M và N dương:’);</b>
<b>Readln(M, N);</b>


</div>
<span class='text_page_counter'>(146)</span><div class='page_container' data-page=146>

<b>Writeln(‘Bội số chung nhỏ nhất= ‘, BSCNN);</b>
<b>Readln;</b>


<b>End.</b>


<i><b>+ Ví dụ 10_5: Thiết kế để chạy nhiều lần một chương trình.</b></i>
Trong Turbo Pascal, mỗi lần muốn chạy chương trình ta
phải gõ cặp phím Ctrl và F9 (viết tắt là ^F9), điều này sẽ bất
tiện nếu cần chạy chương trình nhiều lần ứng với các bộ dữ liệu
thử khác nhau. Cấu trúc sau đây cho phép ta chạy chương trình
một số lần theo ý muốn:


<b>REPEAT</b>



<b>{Các lệnh của chương trình}</b>


<b>Write(‘Tiếp tục nữa khơng (Y/N)?’);</b>
<b>Readln(Traloi); {5}</b>


<b>UNTIL (Traloi =‘N’) or ( Traloi=‘n’);</b>
Ở đây, Traloi là một biến kiểu ký tự (Char);


Sau khi thực hiện xong {các lệnh của chương trình}, nếu
muốn chạy tiếp thì ta gõ phím Y, nếu muốn dừng thì gõ N.


Chú ý: lệnh Readln(Traloi); ở dịng thứ {5} có thể thay
bằng:


<b>Traloi:=Readkey;</b>


Hàm Readkey thuộc thư viện CRT cho kết quả là một ký tự
gõ từ bàn phím, nó khác lệnh Readln(Traloi) ở chỗ là khi nhập
ký tự ta không cần phải Enter.


</div>
<span class='text_page_counter'>(147)</span><div class='page_container' data-page=147>

<b>PROGRAM VIDU10_5;</b>
{In tam giác cân đặc}
<b>Uses CRT;</b>


<b>Const</b>
<b>sao =‘*’;</b>
<b>Var</b>


<b>k, j, m: integer;</b>
<b>Traloi: Char;</b>


<b>Begin</b>


<b>REPEAT</b> <b>{9}</b>
<b>Clrscr;</b>


</div>
<span class='text_page_counter'>(148)</span><div class='page_container' data-page=148>

<b>Begin</b>


<b>Write(chr(32): m-k-1); {in m-k-1 ký tự trắng}</b>
<b>for j:=1 to 2*k+1 do Write(sao); {in 2k+1 dấu *}</b>
<b>Writeln;</b>


<b>End;</b>


<b>For k:=1 to 2*m-1 do Write(sao); {in cạnh đáy}</b>
<b>Writeln;</b>


<b>Write(‘Tiếp tục nữa không (Y/N)?‘);</b>
<b>Readln(Traloi);</b>


<b>UNTIL (Traloi=‘N’) or ( Traloi=‘n’);</b> {28}
<b>End.</b>


Chương trình 10.5 là một ví dụ về hai câu lệnh Repeat lồng
nhau, điều này xảy ra khi thân của một lệnh Repeat lại chứa
một lệnh Repeat khác: lệnh Repeat thứ nhất, từ dòng {9} đến
dòng {28}, chứa lệnh Repeat thứ hai từ dòng {11} đến dòng
{15}.


<b>10.3. So sánh các lệnh For, While và Repeat:</b>



<i>+ Lệnh For dùng cho các vịng lặp có số lần lặp đã biết </i>
trước


+ Lệnh While hay Repeat tổng quát hơn lệnh For, dùng
được cho tất cả các loại vịng lặp, nhưng thường dùng cho các
vịng lặp có số lần lặp chưa biết trước.


</div>
<span class='text_page_counter'>(149)</span><div class='page_container' data-page=149>

<i>+ Ngoài ra, lệnh While kết thúc khi điều kiện sai, lệnh </i>
Repeat kết thúc khi điều kiện đúng.


<b>11.</b> <b>KIỂU LIỆT KÊ và KIỂU ÐOẠN CON</b>
<b>11.1. Kiểu liệt kê (enumerated type)</b>


<b>11.1.1.</b> <b>Cách khai báo</b>


Ngoài các kiểu dữ liệu đã có sẵn như <i>kiểu nguyên,thực, ký</i>


<i>tự, </i> <i>lơgic</i> <i>và</i> <i>chuỗi, Turbo Pascal cịn cho phép người thảo </i>


chương có thể tự xây dựng các kiểu dữ liệu mới.


Kiểu liệt kê được định nghĩa bằng cách sử dụng từ khóa
TYPE và liệt kê ra tất cả các giá trị của kiểu, theo mẫu sau:


<b>Type</b>


<b>Tênkiểu = (tên1, tên2, ..., tênN);</b>


trong đó tên1, tên2, ..., tênN là các tên tự đặt theo đúng quy ước
về đặt tên. Ví dụ:



<b>Type</b>


Phai=(nam, nu);


</div>
<span class='text_page_counter'>(150)</span><div class='page_container' data-page=150>

Trong chương trình, ta có thể gán:
Ph1:=nam;


Ph2:=nu;
M1:=den;
M2:=trang;


Pascal cịn cho phép khai báo trực tiếp biến kiểu liệt kê
không cần qua giai đoạn định nghĩa Type bằng cách liệt kê các
giá trị mà biến có thể nhận.


Ví dụ: các biến Ph1, Ph2, M1, M2 nói trên có thể khai báo
trực tiếp như sau:


<b>Var</b>


Ph1, Ph2: (nam, nu);


M1, M2: ( den, trang, xanh, vang, tim, nau);
<b>11.1.2.</b> <b>Các hàm liên quan</b> <b>đến kiểu liệt kê</b>


+ <b>Hàm ORD(tên): Trả về số thứ tự của tên trong kiểu liệt </b>
kê. Các giá trị liệt kê được đánh số thứ tự bắt đầu từ 0. Ví dụ:


Ord(nam)=0,


Ord(xanh)=2


Thơng qua hàm Ord, các giá trị liệt kê có thể so sánh với
nhau theo quy tắc: giá trị nào có số thứ tự nhỏ hơn thì nhỏ hơn:


den < trang < xanh< vang< tim< nau


<b>+ Hàm PRED(tên) và hàm SUCC(tên): trả về giá trị đứng </b>
ngay trước và ngay sau tên trong kiểu liệt kê tương ứng. Ví dụ:


</div>
<span class='text_page_counter'>(151)</span><div class='page_container' data-page=151>

<b>+ Hàm Tênkiểu(k): trả về giá trị liệt kê có số thứ tự là k</b>
trong Tênkiểu, ví dụ:


Phai(0)=nam
Ten_mau(2)= xanh


Hàm này là hàm ngược của hàm Ord.
<b>11.1.3.</b> <b>Nhập, xuất kiểu liệt kê</b>


<i>Các giá trị liệt kê không thể nhập, xuất trực tiếp bằng lệnh </i>
<i>Readln và Write được. Ðây là hạn chế của kiểu liệt kê, khiến nó </i>
không thông dụng.


Khi muốn nhập hay xuất kiểu liệt kê, ta có thể dùng một
biến trung gian St kiểu chuỗi. Chẳng hạn, muốn nhập màu xanh
cho biến M1, ta dùng hai lệnh:


Readln(St);


If St=‘xanh’then M1:=xanh;



Tương tự, muốn in màu xanh lên màn hình, ta dùng lệnh:
If M1=xanh then Writeln(‘xanh’);


</div>
<span class='text_page_counter'>(152)</span><div class='page_container' data-page=152>

<b>VAR</b>


<b>Tênbiến: hằng1..hằng2;</b>


trong đó, hằng1< hằng2 là hai hằng thuộc cùng một kiểu dữ
<i>liệu. Kiểu dữ liệu của hằng1 và hằng2 chỉ có thể là kiểu ngun,</i>
<i>ký tự, lơgic, hay liệt kê</i>


Ví dụ:
<b>Type</b>


Chu_Hoa =‘A’..’Z’;
Tuoi= 0..200;
<b>Var</b>


Ch: Chu_hoa;
T: Tuoi;


Theo khai báo này thì ch là một biến kiểu đoạn con, có thể
nhận các giá trị là các ký tự từ ‘A’đến ‘Z’, tương tự, biến T có
thể nhận các giá trị là các số nguyên từ 0 đến 200.


Cũng có thể khai báo hai biến Ch và T trực tiếp theo cách
sau:


<b>Var</b>



Ch: ‘A’..’Z’;
T: 0..200;


<b>11.2.2.</b> <b>Tác dụng của kiểu đoạn con</b>


Trong nhiều trường hợp, việc khai báo đoạn con có tác dụng
tiết kiệm bộ nhớ. Tùy theo phạm vi hằng1..hằng2 mà Turbo
Pascal sẽ cấp phát cho biến một số byte tối thiểu. Trong ví dụ
trên, mỗi biến Ch hay T sẽ được chứa trong 1 byte.


</div>
<span class='text_page_counter'>(153)</span><div class='page_container' data-page=153>

<i>biến T mà gán T:=201; thì máy sẽ báo lỗi "const out of range".</i>
Ngoài ra khi chạy chương trình trong mode {$R+}, chương
trình sẽ dừng ngay nếu biến nhận giá trị vượt khỏi phạm vi.


Kiểu liệt kê và kiểu đoạn con thuộc loại đơn giản và đếm
được.


<b>12.</b> <b>KIỂU TẬP HỢP</b>


<b>12.1. Khai báo</b>


Một tập hợp thì gồm nhiều giá trị có chung một kiểu dữ
liệu, gọi là kiểu cơ bản. Kiểu cơ bản phải là kiểu vô hướng đếm
được, tức chỉ có thể là kiểu byte, ký tự, lôgic hay liệt kê. Số
phần tử của tập hợp tối đa là 256 phần tử.


Kiểu tập hợp được mô tả bằng từ khóa SET OF, kế đến là
kiểu cơ bản của các phần tử.



<b>Ví dụ:</b>
<b>TYPE</b>


<b>Kky_tu = SET OF Char;</b>
<b>Kchu_hoa = SET OF ‘A’.. ‘Z’;</b>
<b>Kso = SET OF Byte;</b>


</div>
<span class='text_page_counter'>(154)</span><div class='page_container' data-page=154>

TapH: SET OF ‘A’.. ‘Z’;
TapS: SET OF Byte;


Chú ý rằng các khai báo dưới đây là sai, vì kiểu cơ bản
khơng thể là Integer, và nếu là đoạn con thì phạm vi của đoạn
con không được vượt quá phạm vi của kiểu Byte:


<b>Var</b>


T1: SET OF Integer;
T2: SET OF 1..256;
<b>12.2. Xác định một tập hợp</b>


Một tập hợp được xác định bằng cách liệt kê các phần tử
của nó, các phần tử được phân cách nhau bởi dấu phẩy, và đặt
giữa hai dấu ngoặc vuông.


[ ]: tập rỗng


[3..6]: tập các số nguyên 4, 3, 5, 6


[3..6, 9, 12]: tập các số nguyên 3, 4, 5, 6, 9, 12



[‘A’..’C’, ‘X’, ‘Z’]: tập các chữ ‘A’, ‘B’, ‘C’, ‘X’, ‘Z’
Các phần tử của tập hợp có thể là biến hay biểu thức, ví dụ:
[3, 5, i+j, 2*j]: tập hợp này có 4 phần tử là 3, 5, hai phần tử
kia có giá trị bằng i+j và 2*j, trong đó i, j là các số nguyên sao
cho i+j và 2*j nằm trong phạm vi từ 0 đến 255.


<b>12.3. Các phép toán</b>
<b>+ Phép gán</b>


Có thể gán một tập hợp cho một biến tập hợp cùng kiểu. Ví
dụ, với các biến khai báo ở trên, có thể gán:


</div>
<span class='text_page_counter'>(155)</span><div class='page_container' data-page=155>

TapS:=[15..20, 30, 40];


Tập rỗng [ ] gán cho biến tập hợp kiểu nào cũng được:
TapA:=[ ];


TapH:=[ ];


Lệnh gán dưới đây là sai vì hai vế khơng cùng kiểu dữ liệu:
TapA:=[1..8];


TapS:=[‘1’..’9’];
<b>+ Phép hợp</b>


Hợp của hai tập hợp A và B, ký hiệu là A+B, là một tập hợp
gồm các phần tử hoặc thuộc tập A hoặc thuộc tập B. Ví dụ:


[3..5]+[4..6,10, 15]=[ 3..6, 10, 15]
<b>+ Phép giao</b>



Giao của hai tập hợp A và B, ký hiệu là A*B, là một tập hợp
gồm các phần tử đồng thời thuộc A và B.


<b>Ví dụ:</b>


[1..10]*[5..15] =[5..10]
<b>+ Phép hiệu</b>


</div>
<span class='text_page_counter'>(156)</span><div class='page_container' data-page=156>

<b>Ví dụ:</b>


‘N’IN [‘N’, ‘n’] cho kết quả là TRUE
‘y’IN [‘N’, ‘n’] cho kết quả là FALSE
<b>+ Các phép so sánh (=, <>, <=, >=)</b>


Cho A và B là hai tập hợp cùng kiểu, kết quả của các phép
so sánh A với B sẽ là TRUE hoặc FALSE.


<b>+ Phép bằng</b>


A=B khi và chỉ khi mỗi phần tử của A đều thuộc B và mỗi
phần tử của B đều thuộc A, trong trường hợp ngược lại, ta nói
A khác B và viết A<>B.


<b>Ví dụ:</b>


[3,2,4,5]= [2, 3..5]
[‘A’, ‘B’]<>[‘a’,’B’]
<b>+ Phép nhỏ hơn hoặc bằng</b>



A<=B khi và chỉ khi mọi phần tử của A đều thuộc B.
<b>Ví dụ:</b>


[3..5]<=[3..5]
[3..5]<=[1..6]


<b>+ Phép lớn hơn hoặc bằng</b>


A>=B khi và chỉ khi mọi phần tử của B đều thuộc A, nói
cách khác A>=B khi và chỉ khi B<=A.


<b>Ví dụ:</b>


[3..5]>=[3..5]


[‘A’..’Z’]>=[‘A’..’D’]


</div>
<span class='text_page_counter'>(157)</span><div class='page_container' data-page=157>

If (A<=B) and ( A<>B) then writeln (‘A < B’);
If (A>=B) and ( A<>B) then writeln (‘A > B’);
<b>12.4. Các ví dụ</b>


<b>+ Ví dụ 12_1</b>


Nhập vào một chuỗi St, cho biết trong St có những chữ hoa
nào. Ví dụ St= ‘ABc3BAFdzA’thì có các chữ hoa là A, B, F.


<b>PROGRAM VIDU12_1;</b>
<b>Var</b>


<b>Taphoa: Set of ‘A’..’Z’;</b>


<b>N, i: byte;</b>


<b>ch: char;</b>
<b>St: String;</b>
<b>Begin</b>


<b>Write(‘Nhập chuỗi St: ‘);</b>
<b>Readln(St);</b>


</div>
<span class='text_page_counter'>(158)</span><div class='page_container' data-page=158>

<b>Readln;</b>
<b>End.</b>


<b>+ Ví dụ 12_2</b>


Nhập N số nguyên trong phạm vi từ 0 đến 255. In ra các tập
số chẵn, lẻ và cho biết có bao nhiêu số chẵn, bao nhiêu số lẻ
(các số trùng nhau chỉ kể 1 lần). Ví dụ, nhập 9 số: 1, 2, 3, 4, 1,
2, 3, 4, 5 thì có hai số chẵn là 2 và 4 và có 3 số lẻ là 1, 3, 5.


<b>PROGRAM VIDU12_2;</b>
<b>Const</b>


<b>N=10;</b>
<b>Var</b>


<b>Tapchan, Taple: Set of byte;</b>
<b>N1, N2, i, k: byte;</b>


<b>Begin</b>



<b>Tapchan:=[];</b>
<b>Taple:=[];</b>


<b>For i:=1 to N do</b>
<b>Begin</b>


<b>Write(‘Nhap so thu ‘, i, ‘: ‘);</b>
<b>Readln(k);</b>


<b>If odd(k)=False then</b>


<b>Tapchan:=Tapchan+[k]</b>
<b>else</b>


</div>
<span class='text_page_counter'>(159)</span><div class='page_container' data-page=159>

<b>writeln(‘Các số chẵn là: ‘);</b>
<b>N1:=0;</b>


<b>For i:=0 to (255 div 2) do</b>
<b>if 2*i IN Tapchan then</b>


<b>Begin</b>


<b>Write(2*i: 3);</b>
<b>N1:=N1+1;</b>
<b>End;</b>


<b>Writeln( ‘Có ‘, N1, ‘số chẵn’); </b>
<b>Writeln(‘Các số lẻ là: ‘);</b>
<b>N2:=0;</b>



<b>For i:=0 to (255 div 2) do</b>
<b>if (2*i +1) IN Taple then</b>


<b>Begin</b>


<b>Write(2*i+1: 3);</b>
<b>N2:=N2+1;</b>
<b>End;</b>


</div>
<span class='text_page_counter'>(160)</span><div class='page_container' data-page=160>

Xuất phát từ tập số nguyên S=[2..N] ta loại ra số nguyên tố
đầu tiên và tất cả các bội số của nó ra khỏi S, lặp lại q trình
trên cho đến khi S thành tập rỗng.


<b>Ví dụ: S=[2..15];</b>


Bước 1: - đưa 2 vào tập số nguyên tố, Tapsnt:=[2]
- loại 2 và các bội của 2 ra khỏi S, ta được


S=[3,5,7,9,11,13,15 ]


Bước 2: - đưa 3 vào tập số nguyên tố, Tapsnt:=[2,3]
- loại 3 và các bội của 3 ra khỏi S, ta được


S=[5,7,11,13 ]


Bước 3: - đưa 5 vào tập số nguyên tố, Tapsnt:=[2,3,5]
- loại 5 và các bội của 5 ra khỏi S, ta được


S=[7,11,13]



Bước 4: - đưa 7 vào tập số nguyên tố, Tapsnt:=[2,3,5,7]
- loại 7 và các bội của 7 ra khỏi S, được


S=[11,13 ]


Bước 5: - đưa 11 vào tập số nguyên tố, Tapsnt:=[2,3,5,7,11]
- loại 11 và các bội của 11 ra khỏi S, được S=[13 ]
Bước 6: - đưa 13 vào tập số nguyên tố,
Tapsnt:=[2,3,5,7,11,13]


- loại 13 và các bội của 13 ra khỏi S, được S=[ ]
Kết quả được Tapsnt = [2,3,5,7,11,13].


<b>Tập S giống như một cái sàng để lọc và loại ra các số khơng </b>
phải số ngun tố. Chương trình cụ thể như sau:


</div>
<span class='text_page_counter'>(161)</span><div class='page_container' data-page=161>

<b>N=20;</b>
<b>Var</b>


<b>Tapsnt, S: Set of 1..N;</b>
<b>snt, i: Integer;</b>


<b>Begin</b>


<b>S:=[2..N];</b>
<b>Tapsnt:=[];</b>


<b>snt:=2; {so nguyen to nho nhat}</b>
<b>Writeln(‘Cac so nguyen to la:’);</b>
<b>Repeat</b>



<b>{tim snt la so nho nhat trong S}</b>


<b>While Not (snt IN S) do snt:=snt+1;</b>
<b>Tapsnt:= Tapsnt+[snt]; {dua vao Tapsnt}</b>
<b>Write(snt:4);</b>


<b>{Loại các bội của snt ra khỏi S}</b>
<b>i:=snt;</b>


</div>
<span class='text_page_counter'>(162)</span><div class='page_container' data-page=162>

<b>13.</b> <b>KIỂU MẢNG</b>
<b>13.1. Mảng một chiều</b>


<i><b>+ Khái niệm</b></i>


Mảng là một tập gồm nhiều phần tử có cùng chung một kiểu
dữ liệu. Mỗi phần tử của mảng có một đại lượng xác định vị trí
tương đối của phần tử đó so với các phần tử khác trong mảng,
<i>gọi là chỉ số. Các yếu tố để xác định một mảng gồm có:</i>


Tên mảng


Kiểu dữ liệu chung của các phần tử trong mảng
Kiểu dữ liệu của chỉ số và phạm vi của chỉ số.


Kiểu dữ liệu của các phần tử mảng là mọi kiểu dữ liệu
<i>mà một biến có thể có. Tuy nhiên, kiểu dữ liệu của chỉ số thì</i>
<i>khơng được là kiểu thực hay kiểu chuỗi, nó chỉ có thể là kiểu </i>
đếm được: nguyên, ký tự, lôgic, liệt kê hay đoạn con.



<b>13.1.1.</b> <b>Khai báo mảng một chiều</b>


Mảng một chiều, còn gọi là dãy, hay đơn giản là mảng, có
thể khai báo theo một trong hai cách:


<b>* Cách 1: Khai báo trực tiếp theo cách sau</b>
<b>Var</b>


<b>Tênmảng: Array[m1 . . m2] of Tênkiểudữliệu;</b>
Ở đây m1, m2 là hai hằng xác định phạm vi của chỉ số,
chúng có chung một kiểu dữ liệu, và m1 ≤ m2.


Ví dụ: Cho khai báo dưới đây:
<b>Var</b>


A: Array[0..10] of Real;


</div>
<span class='text_page_counter'>(163)</span><div class='page_container' data-page=163>

Theo khai báo trên, ta có ba mảng:


+ Mảng thứ nhất tên là A, gồm 11 phần tử cùng kiểu Real,
ứng với các chỉ số 0, 1, 2, ..., 10, đó là:


A[0], A[1], A[2], ..., A[10]


+ Mảng thứ hai tên là HTen gồm 5 phần tử cùng kiểu dữ
liệu là String[18] ứng với các chỉ số từ 1 đến 5:


Hten[1], Hten[2], Hten[3], Hten[4], Hten[5]


+ Mảng thứ ba tên là B, gồm 4 phần tử cùng kiểu Integer


ứng với các chỉ số ‘a’, ‘b’, ‘c’, ‘d’:


B[‘a’], B[‘b’], B[‘c’], B[‘d’]


Ðể có một hình ảnh về mảng, đối với mảng A, ta hình dung
có một dãy nhà một tầng, tên gọi là dãy A, gồm 11 phòng liên
tiếp giống hệt nhau được đánh số thứ tự từ 0,1, 2, ..., đến 10:


A0 A1 A2 A3 A4 A5 A6 A7 A8 A9


Tương tự, mảng B cũng giống như dãy nhà B một tầng có
bốn phòng được đánh số thứ tự là các chữ a, b, c, d:


Ba Bb Bc Bd


<b>* Cách 2: Khai báo qua một kiểu dữ liệu mới, gồm hai </b>


</div>
<span class='text_page_counter'>(164)</span><div class='page_container' data-page=164>

Ví dụ, đối với các mảng A, B và Hten ở trên ta có thể khai
báo theo cách 2, như sau:


<b>Type</b>


Mang1 = array[0..10] of Real;
Mang2 = array[1..5] of String[18];
Mang3 = array[‘a’..’d’] of Integer;
<b>Var</b>


A: Mang1;
Hten: Mang2;
B: Mang3;



<b>13.1.2.</b> <b>Khai báo mảng có gán trị ban đầu</b>


Pascal cho phép vừa khai báo mảng vừa gán giá trị ban đầu
cho các phần tử mảng, chẳng hạn như dưới đây:


<b>Const</b>


X: array[1..5] of Integer = (12, 14, 16, 18, 20);
Khi đó X là một mảng gồm năm phần tử cùng kiểu nguyên
và có giá trị X[1]=12, X[2]=14, X[3]=16, X[4]=18, X[5]=20.


Mặc dù từ khóa ở đây là Const song X lại được dùng như là
một biến mảng, tức là các phần tử của X có thể thay đổi giá trị
được. Ví dụ, trong chương trình ta có thể gán:


X[1]:= 2;
X[2]:=5+20;


<b>13.1.3.</b> <b>Truy xuất các phần tử mảng </b>


</div>
<span class='text_page_counter'>(165)</span><div class='page_container' data-page=165>

<b>Tênmảng [chỉ số của phần tử]</b>
<b>Ví dụ: có thể gán:</b>


A[0]:= 15.8;
A[1]:= 2*A[0];


Hten[3]:= ‘Nguyen Thi Loan’;
B[‘a’]:=100;



Chỉ số của một phần tử có thể là một biến, một hằng, hay
một biểu thức. Ví dụ, cho i là biến kiểu nguyên, khi đó ta có thể
dùng các lệnh:


i:=6;


A[i]:=100.25;


Hai lệnh trên tương đương với một lệnh:
A[6]:=100.25;


Nếu biến i có giá trị là 6 thì lệnh:


A[ i div 2 +1]:= 4.5; tương đương với lệnh:
A[4]:=4.5; vì biểu thức i div 2 +1 có giá trị là 4.


Khi nhập dữ liệu cho các phần tử của một mảng, ta có thể
dùng câu lệnh For, While hay Repeat.


</div>
<span class='text_page_counter'>(166)</span><div class='page_container' data-page=166>

i:=0;


While i<= 10 do
begin


Write(‘Nhập phần tử thứ ‘, i, ‘: ‘);
Readln(A[i]);


i:=i+1;
end;



Tương tự để nhập dữ liệu cho các phần tử của mảng B, ta
viết:


For ch:=‘a’to ‘d’do
begin


Write(‘Nhap phần tử thứ ‘, ch, ‘: ‘);
Readln(B[ch]);


end;


Ðể in các giá trị của mảng A lên màn hình, ta viết:
<b>For i:=0 to 10 do Write(A[i]:6:2);</b>


Các giá trị của mảng A sẽ được in liên tiếp nhau trên cùng
một dòng. Còn nếu muốn in mỗi phần tử trên một dòng, ta thay
lệnh Write bằng Writeln.


Tương tự, mảng B được in lên màn hình bằng lệnh:
<b>For ch:=‘a’to ‘d’do Write(B[ch]);</b>


<i><b>Chú ý: Turbo Pascal cho phép gán một mảng này cho một </b></i>
<i>mảng khác.</i>


</div>
<span class='text_page_counter'>(167)</span><div class='page_container' data-page=167>

có nghĩa là lấy giá trị của từng phần tử của mảng Y gán cho
phần tử tương ứng trong mảng X. Ví dụ, cho khai báo:


<b>Var</b>


X, Y: Array[1..10] of Real;


Khi đó, lệnh:


X:= Y;


tương đương với lệnh:


For i:=1 to 10 do X[i]:=Y[i];


<b>13.1.4.</b> <b>Các bài tốn cơ bản về mảng</b>


<i><b>+ Ví dụ 13_1: Ðếm số lần xuất hiện của giá trị x trong dãy</b></i>
<i>A1, A2, ..., An .</i>


Ví dụ giá trị x=6 xuất hiện 3 lần trong dãy 6 7 1 2 6 0 6 1.
<i>Ta dùng biến Dem kiểu nguyên để đếm số lần xuất hiện của </i>
<i>x. Ðầu tiên ta gán Dem:=0, sau đó duyệt từng phần tử A1, </i>
<i>A2,… An, mỗi khi có một phần tử bằng x thì tăng biến Dem</i>
<i>lên một đơn vị. Kết quả là biến Dem có giá trị đúng bằng số </i>
phần tử bằng x. Hai lệnh chính của thuật tốn là:


Dem:=0;


For i:=1 to N do


</div>
<span class='text_page_counter'>(168)</span><div class='page_container' data-page=168>

là: hãy đếm số phần tử của mảng A thỏa mãn một điều kiện cho
trước. Trong lệnh For ở trên, khi thay đẳng thức A[i]=x bằng
<i>A[i] thỏa điều kiện , ta được thuật toán tổng quát hơn:</i>


Dem:=0;



For i:=1 to N do


<i>If A[i] thỏa điều kiện then Dem:=Dem+1;</i>


Chương trình sau nhập một mảng A có N phần tử, in mảng
A lên màn hình, và đếm xem mảng A có bao nhiêu số dương:


<b>PROGRAM VIDU13_1;</b>
{Ðếm số dương trong mảng}
<b>Type</b>


<b>Kmang = Array[1..20] of Real;</b>
<b>Var</b>


<b>A: Kmang;</b>


<b>i, N, Dem: Integer;</b>
<b>Begin</b>


<b>Repeat</b>


<b>Write(‘Nhập số phần tử N: ‘);</b>
<b>Readln(N);</b>


<b>Until (N>0) and ( N<21);</b>
{nhập mảng}


<b>For i:=1 to N do</b>
<b>Begin</b>



<b>Write(‘Nhập A[‘, i , ‘]: ‘);</b>
<b>Readln( A[i] );</b>


</div>
<span class='text_page_counter'>(169)</span><div class='page_container' data-page=169>

{In mảng A}


<b>Writeln(‘Mảng A là: ’);</b>


<b>For i:=1 to N do Write(A[i]:3:0);</b>
<b>Writeln;</b>


{đếm số dương}
<b>Dem:=0;</b>


<b>For i:=1 to N do</b>


<b>If A[i]>0 then Dem:=Dem+1;</b>
<b>Writeln(‘Số số dương = ‘, Dem );</b>
<b>Readln;</b>


<b>End.</b>


<i><b>+ Ví dụ 13_2: Tìm số lớn nhất của dãy A1, A2, ..., An.</b></i>
Trong ví dụ 8_1, ta đã chỉ ra cách tìm số lớn nhất của hai số,
của ba số. Có thể mở rộng thuật tốn đó để tìm số lớn nhất của
n số:


Gọi Max là biến chứa số lớn nhất phải tìm, thế thì:
<b>Bước 1: Gán Max:=A[1];</b>


</div>
<span class='text_page_counter'>(170)</span><div class='page_container' data-page=170>

Q trình trên được mơ tả bằng hai lệnh:


Max:=A[1];


For i:=2 to n do


if Max<A[i] then Max:=A[i];
<i><b>Nhận xét</b></i>


- Trong lệnh For trên, biến i chạy bắt đầu từ 2, nhưng kết
quả vẫn đúng nếu cho i chạy bắt đầu từ 1.


- Không nhất thiết phải gán giá trị ban đầu cho Max là A[1],
mà có thể gán cho Max một phần tử tùy ý trong mảng, ví dụ
phần tử A[n] chẳng hạn, nhưng khi đó biến i trong lệnh For phải
chạy bắt đầu từ 1.


<i><b>+ Ví dụ 13_3: Bài toán sắp xếp mảng tăng dần (hay giảm </b></i>
<i>dần)</i>


Cho dãy A[1], A[2],..., A[n], nói rằng A là một dãy tăng nếu
A[1]  A[2] ... A[n], tương tự, A là dãy giảm nếu
A[1] A[2]  ... A[n]. Dãy đồng nhất A[1]=A[2]= ... =A[n]
là trường hợp đặc biệt, vừa là dãy tăng, vừa là dãy giảm.


Ví dụ


Dãy 1 3 3 5 5 6 6 6 là dãy tăng
Dãy 9 9 8 5 5 4 0 0 là dãy giảm


Dãy 1 3 3 2 5 4 6 6 là dãy khơng tăng khơng giảm.
Bài tốn đặt ra là: cho một dãy A[1], A[2], ..., A[n] bất kỳ,


hãy thực hiện các hoán đổi các giá trị của các phần tử trong
mảng A để A lập thành một dãy tăng.


Ví dụ, cho dãy A có 5 phần tử A[1]=9, A[2]=7, A[3]=5,
A[4]=8, và A[5]= 2, cần thực hiện các hoán đổi như thế nào để
có A[1]=2, A[2]=5, A[3]=7, A[4]=8 và A[5]=9.


</div>
<span class='text_page_counter'>(171)</span><div class='page_container' data-page=171>

đơn giản và dễ hiểu cho những người mới lập trình, đó là
phương pháp lựa chọn trực tiếp (Straight selection sort).


Ý tưởng của phương pháp là như sau:


<b>Bước 1: Tìm số nhỏ nhất trong các phần tử A[1], A[2], .., </b>
A[n] và để vào vị trí đầu tiên A[1].


<b>Bước 2: Tìm số nhỏ nhất trong các phần tử A[2], A[3], .., </b>
A[n] và để vào vị trí thứ hai A[2].


.v.v.


<b>Bước n-1: Tìm số nhỏ nhất trong hai phần tử A[n-1], A[n]</b>
và để vào vị trí n-1. Sau bước này thì A[n] sẽ là giá trị lớn nhất.


Chẳng hạn, xét dãy A có 4 phần tử: {5,3,4,1}:


<b>Bước 1: Nếu A[1] > A[2] thì đổi A[1] với A[2], được: </b>
{3,5,4,1}


Nếu A[1] > A[3] thì đổi A[1] với A[3]: khơng đổi
Nếu A[1] > A[4] thì đổi A[1] với A[4], được:


{1,5,4,3}


<b>Bước 2: Nếu A[2] > A[3] thì đổi A[2] với A[3], được: </b>
{1,4,5,3}


</div>
<span class='text_page_counter'>(172)</span><div class='page_container' data-page=172>

For j:=i+1 to 4 do


<b>if A[i]>A[j] then Ðổi chỗ A[i] và A[j];</b>


Mảng A ở trên chỉ có 4 phần tử, trong trường hợp tổng quát
khi mảng A có N phần tử thì lệnh For thứ nhất sẽ có biến i chạy
từ 1 đến N-1, và lệnh For thứ hai sẽ có biến j chạy từ i+1 đến N,
tức là:


For i:=1 to N-1 do
For j:=i+1 to N do


<b>if A[i]>A[j] then Ðổi chỗ A[i] và A[j];</b>


Việc đổi chỗ các giá trị trong A[i] và A[j] được tiến hành
bằng cách dùng một biến Z trung gian cùng kiểu dữ liệu với
A[i] và A[j]. Ðầu tiên gởi tạm giá trị của A[i] vào biến Z, sau
đó đưa giá trị của A[j] vào A[i], và cuối cùng đưa giá trị trong Z
vào A[j], tức là phải làm ba lệnh:


Z:=A[i];
A[i]:=A[j];
A[j]:=Z;


Tóm lại, thuật tốn sắp xếp dãy A tăng được viết như sau:


<b>For i:=1 to N-1 do</b>


<b>For j:=i+1 to N do</b>
<b>if A[i]>A[j] then</b>


<b>Begin {Ðổi chỗ A[i] và A[j]}</b>
<b>Z:=A[i];</b>


</div>
<span class='text_page_counter'>(173)</span><div class='page_container' data-page=173>

Trong đó N là số phần tử của dãy A cịn Z là một biến trung
gian có cùng kiểu dữ liệu với các phần tử của mảng A.


Chương trình dưới đây tìm số lớn nhất của mảng A và sắp
dãy A tăng dần:


<b>PROGRAM VIDU13_3;</b>


<b>{Tìm Max và sắp dãy A tăng dần}</b>
<b>Uses CRT;</b>


<b>Type</b>


<b>Kmang = array[1..20] of Real;</b>
<b>Var</b>


<b>i, j, N: Integer;</b>
<b>A: Kmang;</b>
<b>z, Max: Real;</b>
<b>Begin</b>


<b>Clrscr;</b>


<b>Repeat</b>


</div>
<span class='text_page_counter'>(174)</span><div class='page_container' data-page=174>

<b>Max:=A[1];</b>
<b>For i:=1 to N do</b>


<b>if Max< A[i] then Max:=A[i];</b>
<b>Writeln(‘Số lớn nhất là: ‘, Max: 4:1);</b>
{sắp xếp dãy tăng}


<b>For i:=1 to N-1 do</b>
<b>For j:=i+1 to N do</b>


<b>If A[i]>A[j] then</b> {23}
<b>Begin</b> <b>{đổi chỗ A[i] và A[j]}</b>


<b>z:=A[i];</b>
<b>A[i]:=A[j];</b>
<b>A[j]:=z;</b>
<b>End;</b>


<b>Writeln(‘Dãy đã sắp tăng là: ‘);</b>
<b>For i:=1 to N do</b>


<b>Write(A[i]:3:0);</b>
<b>Readln;</b>


<b>End.</b>


<i><b>Chú ý 1: Muốn sắp dãy A giảm dần thì trong chương trình</b></i>
trên chỉ cần thay dịng {23}:



If A[i] > A[j] then ...
bằng dòng:


If A[i] < A[j] then ...


</div>
<span class='text_page_counter'>(175)</span><div class='page_container' data-page=175>

<i><b>Chú ý 2: Sắp xếp một bộ phận của dãy.</b></i>


Gọi m và h là hai số nguyên sao cho 1 ≤ m < h ≤ N, khi đó
A[m], A[m+1], ..., A[h] là một dãy con của dãy A. Muốn sắp
dãy con A[m], A[m+1], ..., A[h] tăng (hay giảm) mà không làm
ảnh hưởng đến các phần còn lại của dãy A, ta dùng lệnh sau:


<b>For i:= m to h-1 do</b>
<b>For j:=i+1 to h do</b>


<b>if A[i]>A[j] then</b>


<b>Begin {Ðổi chỗ A[i] và A[j]}</b>
<b>Z:=A[i];</b>


<b>A[i]:=A[j];</b>
<b>A[j]:=Z;</b>
<b>End;</b>


<i><b>+ Ví dụ 13_4: Kiểm tra mảng có thỏa một tính chất khơng. </b></i>
Ta thường gặp bài toán kiểm tra xem mọi phần tử của mảng
A có thỏa mãn một điều kiện khơng, ví dụ mảng A có phải là
dãy tăng khơng, có phải là dãy đối xứng khơng, có phải là một
cấp số cộng khơng, ...



</div>
<span class='text_page_counter'>(176)</span><div class='page_container' data-page=176>

<b>if A[i] không thỏa điều kiện then Kiemtra:= FALSE;</b>
Việc xác định điều kiện là tùy từng bài tốn cụ thể.


Ví dụ: Kiểm tra xem A có phải là một dãy đối xứng không?
Dãy 1 3 5 4 5 3 1 là đối xứng.


Dãy 1 3 5 4 2 3 1 là khơng đối xứng vì A[3] khác A[5].
Như vậy, dãy N phần tử A1, A2, ..., An là đối xứng nếu


A1=An, A2=An-1, ..., An=A1, tức Ai= An-i+1với mọi i=1, 2, ..., n.


Ðẳng thức: Ai = An-i+1 chính là điều kiện mà mọi phần tử của


dãy A phải thỏa để A là một dãy đối xứng.


Giả thiết biến Kiemtra đã được khai báo kiểu Boolean.
Trong chương trình ta dùng các lệnh sau:


<b>Kiemtra:=TRUE;</b>
<b>For i:=1 to N do</b>


<b>if A[i]<>A[N-i+1] then Kiemtra:=FALSE;</b>
<b>If Kiemtra=TRUE then</b>


<b>writeln(‘Dãy A đối xứng’)</b>
<b>else</b>


<b>Writeln(‘Dãy A khơng đối xứng‘);</b>
Trong thuật tốn trên, lệnh For có thể thay bằng lệnh While,


tốc độ sẽ nhanh hơn song cũng khó hiểu hơn:


<b>Kiemtra:=TRUE;</b>
<b>i:=1;</b>


<b>While (i <=N ) and (Kiemtra=TRUE) do</b>
<b>if A[i]<>A[N-i+1] then</b>


</div>
<span class='text_page_counter'>(177)</span><div class='page_container' data-page=177>

<b>If Kiemtra=TRUE then</b>
<b>writeln (‘Dãy A đối xứng’)</b>
<b>else</b>


<b>writeln(‘Dãy A không đối xứng ‘);</b>


Bạn đọc hãy viết chương trình cho ví dụ này.
<i>Chú ý Câu lệnh:</i>


<b>If Kiemtra=TRUE then</b>
writeln(‘Dãy A đối xứng’)
else


writeln(‘Dãy A khơng đối xứng ‘);
hồn tồn tương đương với lệnh:
<b>If Kiemtra then</b>


writeln(‘Dãy A đối xứng’)
else


writeln(‘Dãy A khơng đối xứng ‘);
<b>+ Ví dụ 13_5: Tính giá trị của đa thức:</b>



P = ao+ a1x + a2x2+ ... + anxn


trong đó số nguyên n, số thực x và các hệ số a0, a1, ..., an


</div>
<span class='text_page_counter'>(178)</span><div class='page_container' data-page=178>

Chương trình được viết như sau:
<b>PROGRAM VIDU13_5;</b>
{Tính giá trị của đa thức bậc N}
<b>Var</b>


<b>i, N: Integer;</b>


<b>A: Array[0..20] of Real;</b>
<b>x, P, U: Real;</b>


<b>Begin</b>
<b>Repeat</b>


<b>Write(‘Nhập N và x: ‘);</b>
<b>Readln(N, x);</b>


<b>Until (N>0) and ( N<21);</b>


<b>For i:=0 to N do {nhập mảng các hệ số}</b>
<b>Begin</b>


<b>Write(‘Nhập hệ số A[‘, i, ‘]: ‘);</b>
<b>Readln(A[i]);</b>


<b>End;</b>


<b>U:=1;</b>
<b>P:=A[0];</b>


<b>For i:=1 to N do</b>
<b>Begin</b>


<b>U:=U*x;</b>
<b>P:=P+A[i]*U;</b>
<b>End;</b>


</div>
<span class='text_page_counter'>(179)</span><div class='page_container' data-page=179>

<b>Readln;</b>
<b>End.</b>


<b>13.2.</b> <b>Mảng hai chiều (ma trẬn)</b>
<b>13.2.1.</b> <b>Khai báo mảng hai chiều</b>


Mảng hai chiều, còn gọi là ma trận, là sự mở rộng trực tiếp
của mảng một chiều. Ta cũng có hai cách khai báo.


<b>+ Cách 1: Khai báo trực tiếp:</b>
<b>VAR</b>


<b>Tênmảng: Array[n1..n2 , m1..m2] of Tênkiểudữliệu;</b>
trong đó n1, n2 là các hằng có cùng kiểu dữ liệu và n1 n2,
chúng xác định phạm vi của chỉ số thứ nhất, gọi là chỉ số dòng.
Tương tự m1, m2 là các hằng có cùng kiểu dữ liệu và m1 m2,
chúng xác định phạm vi của chỉ số thứ hai, gọi là chỉ số cột.
Giống như mảng một chiều, kiểu dữ liệu của các chỉ số chỉ có
thể là kiểu đếm được: nguyên, ký tự, lôgic, liệt kê hay đoạn con,
<i>khơng được là kiểu thực hay chuỗi.</i>



Ví dụ, cho khai báo:
<b>Var</b>


</div>
<span class='text_page_counter'>(180)</span><div class='page_container' data-page=180>

Y[‘b’,1], Y[‘b’,2], Y[‘b’, 3]
Y[‘c’,1], Y[‘c’,2], Y[‘c’, 3]


Có thể ví X là một nhà hai tầng, mỗi tầng có ba phịng giống
nhau. Các tầng được đánh số từ 1 đến 2, trong mỗi tầng, các
phòng được đánh số từ 1 đến 3. Tương tự, Y là một nhà ba tầng,
các tầng được đánh số lần lượt là ‘a’, ‘b’, ‘c’, mỗi tầng có ba
phòng được đánh số lần lượt là 1, 2, 3.


<b>+ Cách 2: Biến mảng được khai báo thông qua một kiểu </b>
mảng đã được định nghĩa trước đó bằng từ khóa TYPE, tức là:


<b>TYPE</b>


<b>Tênkiểumảng=Array[n1..n2,m1..m2] of Tênkiểudliệu;</b>
<b>VAR</b>


<b>Tênmảng: Tênkiểumảng;</b>


Ví dụ: Hai mảng X và Y nói trên có thể được khai báo theo
hai bước sau:


<b>Type</b>


Kmang1 = array[1..2, 1..3] of Real;



Kmang2 = array[‘a’..’c’, 1..3] of String[15];
<b>Var</b>


X: Kmang1;
Y: Kmang2;


<i><b>Chú ý: - Có thể xem mảng hai chiều là mảng một chiều mà</b></i>
mỗi phần tử của nó lại là một mảng một chiều.


Hai mảng X, Y nói trên có thể khai báo như sau:
<b>Type</b>


Kmang1 = array[1..2] of array[1..3] of Real;


</div>
<span class='text_page_counter'>(181)</span><div class='page_container' data-page=181>

<b>Var</b>


X: Kmang1;
Y: Kmang2;


Hiểu theo cách này thì X là một mảng gồm hai phần tử X[1]
và X[2] mà mỗi phần tử này lại là một mảng gồm ba phần tử:


X[1] là mảng có ba phần tử kiểu thực X[1][1], X[1][2],
X[1][3]


X[2] là mảng có ba phần tử kiểu thực X[2][1], X[2][2],
X[2][3]


Ðiều tương tự cũng áp dụng cho biến mảng Y.
Hai cách viết X[i][j] và X[i,j] cùng chỉ một phần tử.


<i><b>- Khai báo và gán giá trị ban đầu:</b></i>


Có thể khai báo và gán giá trị ngay cho một mảng hai chiều,
chẳng hạn:


<b>Type</b>


Kmang1 = array[1..2, 1..3] of Real;
<b>Const</b>


X: Kmang1 = ((1.5, 2.5, 3.5), (5.0, 6.5, 7.0));


</div>
<span class='text_page_counter'>(182)</span><div class='page_container' data-page=182>

<b>Tênbiếnmảng[chỉ số 1, chỉ số 2]</b>
Ví dụ:


X[1,1]:=12.5;
X[2,1]:=X[1,1]+15;
Y[‘a’,1]:=‘Tran Thi Mai’;


Ðể nhập dữ liệu cho một mảng hai chiều, ta phải dùng hai
vòng lặp duyệt theo hai chỉ số, chẳng hạn muốn nhập dữ liệu
cho mảng X, ta viết:


<b>For i:=1 to 2 do</b>
<b>For j:=1 to 3 do</b>


<b>Begin</b>


<b>Write(‘nhập phần tử hàng ‘, i, ‘cột ‘, j , ‘: ‘);</b>
<b>Readln(X[i, j]);</b>



<b>End;</b>


Tương tự, lệnh nhập dữ liệu cho mảng Y được viết là:
<b>For ch:=‘a’to ‘c’do</b>


<b>For j:=1 to 3 do</b>
<b>Begin</b>


<b>Write(‘nhập phần tử hàng ‘, ch , ‘cột ‘, j , ‘:‘);</b>
<b>Readln(X[ch, j]);</b>


<b>End;</b>


trong đó ch là biến kiểu ký tự, còn i và j là các biến nguyên.
Ðể in mảng X lên màn hình, trình bày giống như cách viết
ma trận, mỗi hàng in trên một dòng, ta dùng lệnh:


</div>
<span class='text_page_counter'>(183)</span><div class='page_container' data-page=183>

<b>Begin</b>


<i><b>For j:=1 to 3 do write(X[i,j]:3:1); {in hàng thứ i}</b></i>
<i><b>Writeln; {xuống dòng, chuẩn bị in hàng tiếp theo}</b></i>
<b>End;</b>


<b>13.2.3.</b> <b>Các ví dụ về ma trận </b>


Vì ma trận là mảng một chiều của các mảng một chiều nên
nhiều bài toán về mảng được mở rộng tự nhiên cho ma trận.


<i><b>+ Ví dụ 13_6: Tính tổng của hai ma trận</b></i>



Nhập vào hai ma trận A, B cấp NxM. Tính ma trận C là
tổng của hai ma trận A và B, in ma trận C lên màn hình.


Cơng thức tính các phần tử của ma trận C= A+B:
C[i,j ] = A[i, j] + B[i, j] với i=1,..., N, và j=1,..., M
Chương trình như sau:


<b>PROGRAM VIDU13_6;</b>
{Tính tổng hai ma trận}
<b>Uses CRT;</b>


<b>Var</b>


</div>
<span class='text_page_counter'>(184)</span><div class='page_container' data-page=184>

<b>For i:=1 to N do</b>
<b>For j:=1 to M do</b>


<b>Begin</b>


<b>Write(‘Nhập A[‘, i, ‘,’, j , ‘]: ‘);</b>
<b>Readln(A[i,j]);</b>


<b>End;</b>


{nhập B và tính C ln}
<b>For i:=1 to N do</b>


<b>For j:=1 to M do</b>
<b>Begin</b>



<b>Write(‘Nhập B[‘, i, ‘,’, j , ‘]: ‘);</b>
<b>Readln(B[i,j]);</b>


<b>C[i, j]:=A[i, j] + B[i, j];</b>
<b>End;</b>


{In ma trận A lên màn hình}
<b>Writeln(‘Ma tran A la:’);</b>
<b>For i:=1 to N do</b>


<b>Begin</b>


<b>For j:=1 to M do</b>


<b>write(A[i, j]:3:0);</b>
<b>Writeln;</b>


<b>End;</b>


</div>
<span class='text_page_counter'>(185)</span><div class='page_container' data-page=185>

<b>For i:=1 to N do</b>
<b>Begin</b>


<b>For j:=1 to M do</b>


<b>write(B[i, j]:3:0);</b>
<b>Writeln;</b>


<b>End;</b>


{In ma trận C lên màn hình}


<b>Writeln(‘Ma tran C la:’);</b>
<b>For i:=1 to N do</b>


<b>Begin</b>


<b>For j:=1 to M do</b>


<b>write(C[i, j]:3:0);</b>
<b>Writeln;</b>


<b>End;</b>
<b>Readln;</b>
<b>End.</b>


</div>
<span class='text_page_counter'>(186)</span><div class='page_container' data-page=186>

<b>Writeln(‘Số lớn nhất là ’, Max);</b>


<i><b>+ Ví dụ 13_8: Tìm số lớn nhất (hay số nhỏ nhất) trong từng </b></i>
<i>hàng (hay từng cột) của ma trận A:</i>


Hàng i ( 1 i N ) của ma trận A có dạng:
A[i,1], A[i,2], ..., A[i,M]


Nếu xem i là cố định thì đó là mảng một chiều có M phần
tử, nên số lớn nhất của hàng i được tìm bằng các lệnh:


Max:=A[i, 1];
For j:=1 to M do


if Max< A[i, j] then Max:=A[i, j];
Writeln(‘Sln của hàng ‘, i, ‘là: ‘, Max);



Vì có cả thảy N hàng nên công việc trên phải làm N lần ứng
với i=1, 2, ..., N, tức là:


<b>For i:=1 to N do</b>


<b>Begin {tìm số lớn nhất của hàng i}</b>
<b>Max:=A[i, 1];</b>


<b>For j:=1 to M do</b>


<b>if Max< A[i, j] then Max:=A[i, j];</b>
<b>Writeln(‘Sln của hàng ‘, i, ‘là: ‘, Max);</b>
<b>End;</b>


<i><b>+ Ví dụ 13_9: Kiểm tra ma trận vuông A có đối xứng </b></i>
<i>khơng?</i>


</div>
<span class='text_page_counter'>(187)</span><div class='page_container' data-page=187>

thì A là đối xứng, cịn B khơng đối xứng vì B[1,2] B[2,1].
Chỉ cần có một cặp i, j sao cho A[i,j]<>A[j,i] thì A là ma
trận không đối xứng.


Vậy các lệnh kiểm tra tính đối xứng của ma trận A là:
<b>Kiemtra:= TRUE;</b>


<b>For i:=1 to N do</b>
<b>For j:=1 to N do</b>


<b>if A[i, j]<>A[j, i] then</b>
<b>Kiemtra:=FALSE;</b>


<b>If Kiemtra=TRUE then</b>


<b>writeln(‘Ðối xứng‘)</b>
<b>else</b>


<b>writeln(‘Khơng đối xứng‘);</b>
trong đó Kiemtra là một biến kiểu lơgic.


</div>
<span class='text_page_counter'>(188)</span><div class='page_container' data-page=188>

Thuật tốn tốt hơn được đề nghị là:
<b>Kiemtra:= TRUE;</b>


<b>For i:=2 to N do</b>
<b>For j:=1 to i-1 do</b>


<b>if A[i, j]<>A[j, i] then</b>
<b>Kiemtra:=FALSE;</b>
<b>If Kiemtra=TRUE then</b>


<b>writeln(‘Ðối xứng ‘)</b>
<b>else</b>


<b>writeln(‘Không đối xứng ‘);</b>


Hai câu lệnh For trên vẫn còn một nhược điểm là: khi xảy ra
A[i,j]<>A[j, i] rồi, lẽ ra có thể dừng lại và kết luận không đối
xứng ngay thì các vịng For vẫn tiếp tục, i chạy đến N và j đến
i-1.


Sử dụng câu lệnh While sẽ khắc phục được nhược điểm
này. Chỉ cần xảy ra A[i,j]<>A[j,i] một lần là biến Kiemtra được


gán ngay giá trị FALSE, khi đó điều kiện Kiemtra=TRUE bị sai
và cả hai vòng lặp đều kết thúc .


<b>Kiemtra:=TRUE;</b>
<b>i:=2;</b>


</div>
<span class='text_page_counter'>(189)</span><div class='page_container' data-page=189>

<b>j:=1;</b>


<b>While ( Kiemtra=TRUE) and ( j<=i-1) do</b>
<b>if A[i, j] <> A[j, i] then</b>


<b>Kiemtra:=FALSE</b>
<b>else</b>


<b>j:=j+1;</b>
<b>i:=i+1;</b>
<b>End;</b>


<b>If Kiemtra=TRUE then</b>
<b>writeln(‘Ðối xứng‘)</b>
<b>else</b>


<b>writeln(‘Không đối xứng‘);</b>


Chương trình dưới đây thực hiện các cơng việc sau:


- Nhập vào ma trận vuông A cấp N và in ma trận A lên màn
hình


- Ðếm trong ma trận A có bao nhiêu số 0


- Tìm số lớn nhất trong A


</div>
<span class='text_page_counter'>(190)</span><div class='page_container' data-page=190>

<b>i, j , N, Dem: Integer;</b>
<b>Max, Min: Real;</b>
<b>Kiemtra: Boolean;</b>
<b>Begin</b>


<b>Clrscr;</b>
<b>Repeat</b>


<b>Write(‘Nhập cấp N: ‘);</b>
<b>Readln(N);</b>


<b>Until ( N>0) and ( N<11);</b>
<b>For i:=1 to N do</b>


<b>For j:=1 to N do</b>
<b>Begin</b>


<b>Write(‘Nhập A[‘, i, ‘,’, j , ‘]: ‘);</b>
<b>Readln(A[i,j]);</b>


<b>End;</b>


{In ma trận A lên màn hình}
<b>Writeln(‘Ma tran A la: ’);</b>
<b>For i:=1 to N do</b>


<b>Begin</b>



<b>For j:=1 to N do</b>


<b>write(A[i, j]: 3:0);</b>
<b>Writeln;</b>


</div>
<span class='text_page_counter'>(191)</span><div class='page_container' data-page=191>

<b>Dem:=0;</b>


<b>For i:=1 to N do</b>


<b>For j:=1 to N do</b>
<b>if A[i, j]=0 then</b>


<b>Inc(Dem);</b>
<b>Writeln(‘Có ‘, Dem, ‘số khơng’); </b>
{Tìm số lớn nhất của ma trận}
<b>Max:=A[1,1];</b>


<b>For i:=1 to N do</b>
<b>For j:=1 to N do</b>


<b>if Max < A[i,j] then</b>
<b>Max:=A[i,j];</b>


<b>Writeln(‘Số lớn nhất của ma trận= ‘, Max: 4:1);</b>
{Tìm số nhỏ nhất trong từng hàng của ma trận}
<b>For i:=1 to N do</b>


<b>Begin</b>


</div>
<span class='text_page_counter'>(192)</span><div class='page_container' data-page=192>

<b>Kiemtra:=True;</b>


<b>For i:=1 to N do</b>


<b>For j:=1 to i-1 do</b>


<b>if A[i ,j]<>A[j ,i] then</b>
<b>Kiemtra:=False;</b>
<b>If Kiemtra=True then</b>


<b>Writeln(‘Ðối xứng’) </b>
<b>else</b>


<b>Writeln(‘Không đối xứng’);</b>
<b>Readln;</b>


<b>End.</b>


<b>14. KIỂU CHUỖI KÝ TỰ</b>
<b>14.1. Khai báo biến chuỗi</b>


Một dãy các ký tự đặt trong cặp nháy đơn gọi là một hằng
chuỗi, hay đơn giản là một chuỗi. Dưới đây là ba chuỗi:


‘Ngon ngu Pascal’
‘Tin hoc 1998’
‘12345678’


Chuỗi khơng có ký tự nào ‘‘(chỉ gồm hai dấu nháy đơn liên
tiếp) gọi là chuỗi rỗng.


<i>Số ký tự có trong chuỗi gọi là độ dài của chuỗi. Chuỗi </i>


‘ABCD’có độ dài 4, chuỗi ‘Pascal’có độ dài là 6. Chuỗi rỗng có
độ dài bằng khơng.


</div>
<span class='text_page_counter'>(193)</span><div class='page_container' data-page=193>

<b>Var</b>


<b>Tênbiếnchuỗi: String[N]; hoặc:</b>
<b>Tênbiếnchuỗi: String;</b>


trong đó N là một hằng nguyên (0 ≤ N ≤ 255) ấn định số ký tự
tối đa mà biến có thể nhận và gọi là độ dài tối đa của biến
chuỗi. Nếu khơng có chỉ thị [N] thì chuỗi có độ dài tối đa là 255
ký tự.


Ví dụ, cho khai báo:
<b>Var</b>


St: String[17];
Diachi: String;


Khi đó St là biến chuỗi có độ dài tối đa là 17 ký tự, cịn biến
Diachi có độ dài tối đa là 255 ký tự.


<i>Cần phân biệt độ dài với độ dài tối đa của biến chuỗi: độ </i>
dài tối đa được xác định ngay khi khai báo là khả năng có thể
<i>chứa của biến chuỗi, cịn độ dài của chuỗi là số ký tự đang thực </i>
có trong chuỗi.


Nếu gán:


St:= ‘Nguyen Thi Mai’;



</div>
<span class='text_page_counter'>(194)</span><div class='page_container' data-page=194>

Trong bộ nhớ của máy, một biến chuỗi sẽ chiếm một số
byte bằng độ dài tối đa của nó cộng thêm 1. Byte đầu tiên, gọi
là byte 0, chứa một ký tự có mã bằng độ dài thực của chuỗi,
mỗi byte còn lại chứa một ký tự. Cấu trúc của biến St nói trên
có dạng:


N g u y e n T h i M a i


Ðộ dài N (=14) của biến St và ký tự trong byte 0 (ký hiệu là
St[0]) liên quan với nhau như sau:


N = Ord (St[0])
St[0]= Chr(N)


Turbo Pascal có sẵn hàm Length(chuỗi) cho ngay độ dài
thực của chuỗi mà không cần phải dùng đến byte 0. Ví dụ:


Length(St)=14.


<i><b>Chú ý Cũng có thể khai báo chuỗi thông qua việc định </b></i>
nghĩa một kiểu dữ liệu mới bằng từ khóa Type. Chẳng hạn có
thể khai báo chuỗi St nói trên theo cách sau:


Type


<i>KStr17 = String[17];</i>
Var


<i>St: KStr17;</i>



<i>Khi một biến chuỗi được dùng làm đối số của hàm hay thủ </i>
<i>tục thì nó cần phải được khai báo theo cách này (trừ các biến </i>
<i>chuỗi có kiểu String).</i>


<b>14.2. Truy nhập vào từng phần tử của chuỗi</b>


Giống như mảng, mỗi phần tử của chuỗi được truy nhập
thông qua tên chuỗi và chỉ số của phần tử.


</div>
<span class='text_page_counter'>(195)</span><div class='page_container' data-page=195>

Ví dụ, cho:
St:=‘ABC’;


thì N=3 và St[1]=‘A’, St[2]=‘B’, St[3]=‘C’.


Lệnh St[1]:=‘a’; sẽ biến đổi St thành St=‘aBC’.


Như vậy mỗi ký tự St[i] được dùng như một biến kiểu ký tự,
và chuỗi có thể xem là một mảng các ký tự. Chẳng hạn để in
chuỗi ta có thể in từng ký tự như sau:


For i:=1 to Length(St) do write(St[i]);


Ðiều này cho thấy chuỗi là một kiểu dữ liệu có tính cấu
trúc.


Nhưng mặt khác, mỗi chuỗi lại có thể xem là một giá trị duy
nhất, vì có thể nhập và in chuỗi trực tiếp bằng các lệnh:


Readln(St);


Write(St);


Ðặc điểm này cho thấy chuỗi còn là một kiểu dữ liệu có tính
đơn giản.


<b>14.3. Các thao tác trên chuỗi</b>
+ Phép cộng (nối) chuỗi:


</div>
<span class='text_page_counter'>(196)</span><div class='page_container' data-page=196>

Ví dụ:


‘Hong’> ‘Han’vì ‘o’> ‘a’
‘thanh’> ‘thao’vì ‘n’> ‘o’


Nếu so sánh hết chiều dài của chuỗi ngắn hơn mà khơng có
cặp nào khác nhau thì chuỗi ngắn hơn sẽ nhỏ hơn.


Ví dụ:


‘an’< ‘anh’
‘chu’< ‘chung’


Hai chuỗi bằng nhau khi chúng cùng độ dài và các ký tự ở
các vị trí tương ứng thì bằng nhau.


<b>14.4. Các hàm liên quan đến chuỗi</b>


<b>+ Hàm Length(St): cho độ dài của chuỗi St.</b>
Ví dụ


Length(‘ABCD’)=4 vì chuỗi ‘ABCD’có 4 ký tự.


Chuỗi rỗng có độ dài bằng 0.


<b>+ Hàm Pos(S, St)</b>


Cho vị trí đầu tiên tìm thấy chuỗi S trong chuỗi St, nếu
khơng tìm thấy thì hàm cho kết quả bằng 0.


Ví dụ


Pos(‘Ab’, ‘cdAb3Abm’) = 3,
Pos(‘Ab’, ‘1bA3b’) = 0.


<b>+ Hàm Copy(St, k, m): cho m ký tự của St tính từ vị trí k.</b>
Ví dụ


Copy (‘ABCDEF’, 4, 2) =‘DE’.


</div>
<span class='text_page_counter'>(197)</span><div class='page_container' data-page=197>

Nếu m> số ký tự đứng sau kể từ vị trí k thì hàm Copy chỉ
lấy các ký tự từ vị trí k đến hết chiều dài của St.


Ví dụ


Copy (‘ABCD’, 3, 10) = ‘CD’
<b>+ Hàm Concat( St1, St2, ..., Stn):</b>


Ghép nối các chuỗi St1, St2, ..., Stn theo thứ tự đó thành
một chuỗi duy nhất. Vậy:


Concat(St1, St2, ..., Stn) = St1+St2+...+Stn.
<b>14.5. Các thủ tục liên quan đến chuỗi</b>



<b>+ Thủ tục Delete(St, k, m)</b>


Xóa m ký tự trong biến chuỗi St bắt đầu từ vị trí thứ k. Ví
dụ, sau khi thực hiện các lệnh:


St:=‘TurboPascal’;
Delete(St, 1, 5);


thì giá trị của St=‘Pascal’vì năm ký tự đầu đã bị xóa.
Nếu k > Length(St) thì khơng xóa gì cả.


Nếu m > số ký tự đứng sau kể từ vị trí k thì xóa hết từ vị trí
k đến cuối chuỗi.


</div>
<span class='text_page_counter'>(198)</span><div class='page_container' data-page=198>

St:=‘ABCD’;
Sau khi thực hiện lệnh:


Insert(‘**’, St, 3);


thì St bị biến đổi thành St=‘AB**CD’.


Nếu k> Length(St) thì S được nối vào cuối của St. Ví dụ,
sau khi thực hiện hai lệnh:


St:=‘XYZ’;


Insert(‘ABC’, St, 6); thì St=XYZABC’.
<b>+ Thủ tục Str(x, St)</b>



Biến đổi số nguyên hay thực x thành kiểu chuỗi và gán cho
biến chuỗi St.


Ví dụ, sau khi thực hiện lệnh:
Str(4752, St);


thì kết quả là St= ‘4752’.


Số x có thể được định dạng như khi in ra màn hình.
Lệnh Str(4752: 6, St);


<i>cho kết quả St=‘4752’(trước số 4752 có 2 ký tự trắng) .</i>
Nếu x là biến thực và giá trị của x=34.95 thì lệnh:


<i>Str(x:7:3, St); cho kết quả St=‘34.950’(trước số 34.950 </i>
<i>có 1 ký tự trắng) .</i>


<b>+ Thủ tục Val(St, x, k)</b>


Biến đổi chuỗi số St thành số nguyên hay thực và gán cho
biến nguyên hay thực x. Số nguyên k dùng để phát hiện lỗi: nếu
đổi được thì k=0, ngược lại, giá trị của k là vị trí có lỗi trong
chuỗi St.


</div>
<span class='text_page_counter'>(199)</span><div class='page_container' data-page=199>

St:=‘385’;
Val(St, n, j);
Val(‘12.59’, x, k);
thì n=385, j=0, x=12.59 và k=0.


Nếu gán St:= ‘3a7’; và thực hiện lệnh:


Val(St, n, k);


thì giá trị của n khơng xác định cịn k=2 là vị trí của chữ a trong
chuỗi St, tại đó khơng đổi ra số được.


<b>14.6. Các ví dụ về chuỗi</b>


<i><b>+ Ví dụ 14_1: Ðổi một chuỗi ra chữ hoa hay chữ thường.</b></i>
Ðể đổi cả chuỗi St thành chữ hoa, ta đổi từng ký tự của
chuỗi đó ra chữ hoa, tức là:


For i:=1 to Length(St) do St[i]:=Upcase(St[i]);


Tương tự, để đổi cả chuỗi St thành chữ thường, ta cũng đổi
từng ký tự của chuỗi St ra chữ thường:


For i:=1 to Length(St) do


</div>
<span class='text_page_counter'>(200)</span><div class='page_container' data-page=200>

Muốn xóa hết các ký tự trắng ở đầu chuỗi ta dùng lệnh:
While St[1]=#32 do Delete(St,1,1);


<i>Diễn giải: chừng nào ký tự đầu tiên của St vẫn cịn là ký tự </i>
trắng thì cứ xóa nó đi cho đến khi ký tự đầu tiên là khác trắng.


Sở dĩ phải dùng vòng lặp While là vì số ký tự trắng ở đầu
chuỗi là khơng biết trước.


<i>b) Xóa các ký tự trắng ở cuối chuỗi</i>


Tương tự, muốn xóa tất cả các ký tự trắng ở cuối của chuỗi


St, ta dùng lệnh:


While St[ length(St) ]= #32 do Delete(St, length(St), 1);
<i>Diễn giải: chừng nào ký tự cuối cùng của St cịn là khoảng </i>
trắng thì cứ xóa nó đi cho đến khi ký tự cuối cùng là khác trắng.


<i>c) Xóa các ký tự trắng thừa ở giữa hai từ trong chuỗi</i>


Muốn xóa các ký tự trắng thừa để giữa hai từ chỉ còn đúng
một ký tự trắng ta làm như sau: tìm trong St chỗ nào có hai ký
tự trắng thì xóa đi một, và lặp lại thao tác trên cho đến khi trong
St khơng cịn chỗ nào có hai ký tự trắng liên tiếp. Tức là:


<i>k:=Pos(‘‘, St); {‘‘là 2 ký tự trắng}</i>
While k > 0 do


begin


Delete(St, k, 1);
k:=Pos(‘‘, St);
end;


<i><b>+ Ví dụ 14_3: Đếm trong chuỗi St có bao nhiêu chữ pascal.</b></i>
Vì chữ pascal có 6 ký tự, nên ta so sánh từng cụm 6 ký tự
của St với chuỗi pascal, bắt đầu từ vị trí 1:


</div>

<!--links-->

×