Bỏ qua nội dung

Lập trình

Khoa học máy tính A-Level · Chủ đề 11

Bài học video cho chủ đề này Mở trang video
24:05

Cơ sở lập trình

Một chương trình phải yêu cầu mật khẩu, và tiếp tục yêu cầu cho đến khi đúng. Đơn giản — nhưng bạn nên dùng vòng lặp nào? Chương trình đưa ra quyết định và lặp lại công việc, và việc lựa chọn…

Giọng đọc tiếng Anh · phụ đề tiếng Anh + 中文 được ghi trực tiếp

11.1

Cơ bản lập trình

Chương trình
Thí sinh cần có thể: Ghi chú và hướng dẫn
Triển khai và viết pseudocode từ thiết kế đã cho được trình bày dưới dạng sơ đồ luồng chương trình hoặc tiếng Anh có cấu trúc
Viết giả mã cho: • khai báo và khởi tạo hằng số • khai báo biến • gán giá trị cho biến • biểu thức liên quan đến các toán tử số học hoặc logic, nhập từ bàn phím và xuất ra màn hình
Sử dụng các hàm tích hợp và thủ tục thư viện Bất kỳ hàm nào không có trong hướng dẫn pseudocode sẽ được cung cấp Các hàm thao tác chuỗi luôn được cung cấp

Nguồn: Chương trình Cambridge International

Dòng mã nguồn trên màn hình tối
Lập trình biến thiết kế thành các lệnh được viết dưới dạng mã
Một lập trình viên đang làm việc tại máy tính
Người lập trình viết mã và kiểm thử khi đang thực hiện

Từ thiết kế đến mã

Bạn cần có khả năng chuyển một thiết kế — một sơ đồ khối (sơ đồ luồng chương trình) hoặc tiếng Anh có cấu trúc — thành giả mã, và sau đó thành ngôn ngữ thực tế:

  1. xác định các biến và kiểu dữ liệu của chúng.
  2. chuyển các hộp nhập/xuất thành INPUT / OUTPUT.
  3. chuyển các kim cương quyết định thành IF...ELSE...ENDIF (hoặc CASE).
  4. chuyển các mũi tên vòng lặp thành WHILE, REPEAT...UNTIL, hoặc FOR.
  5. chuyển các hộp xử lý thành phép gán hoặc tính toán.
  6. kiểm tra bằng cách truy vết với một đầu vào nhỏ.
Sơ đồ ánh xạ từ ký hiệu sơ đồ khối sang giả mã: một hình bình hành nhập/xuất trở thành INPUT hoặc OUTPUT, một kim cương quyết định trở thành IF...THEN hoặc CASE, một hộp xử lý trở thành phép gán x = biểu thức, và một mũi tên vòng lặp trở thành WHILE, FOR hoặc REPEAT
Mỗi ký hiệu sơ đồ khối trở thành một từ khóa giả mã

Hằng và biến

Một hằng chứa giá trị không bao giờ thay đổi; một biến chứa giá trị có thể thay đổi. Khai báo chúng với một kiểu:

Giá trị của biến có thể thay đổi; hằng số vẫn giữ nguyên
Giá trị của biến có thể thay đổi; hằng luôn cố định
CONSTANT Pi = 3.14159
DECLARE Radius : REAL
DECLARE Area : REAL

Radius ← 5
Area ← Pi * Radius * Radius

Dùng hằng cho các giá trị cố định xuất hiện nhiều lần (Pi, MaxScore); chúng giúp mã rõ ràng hơn và dễ thay đổi ở một nơi duy nhất.

Trong bài thi, một hằng là câu trả lời cho yêu cầu "xác định cách biểu diễn phù hợp hơn" đối với một giá trị cố định, chẳng hạn như tỷ lệ thuế hoặc điểm tối đa, xuất hiện ở nhiều nơi trong giả mã. Các lợi ích mà bộ đề liệt kê: giá trị được đặt một lần và không thể bị thay đổi vô tình bởi chương trình; một sự thay đổi được thực hiện ở một nơi và tác động đến mọi câu lệnh sử dụng nó; danh hiệu gán cho giá trị đó một ý nghĩa (MaxScore thay vì 100), nên mã dễ đọc và dễ kiểm tra hơn; và giảm thiểu rủi ro lỗi đánh máy trong một giá trị dài như 3.14159. Câu hỏi "nêu một giá trị có thể được thay thế bằng hằng" đòi hỏi lấy chính xác từ giả mã (0.2, 40), không phải đặt tên mới.

Mỗi biến được khai báo một lần, với một danh hiệu (tên của nó) và kiểu dữ liệu, trước khi được sử dụng. Sáu kiểu trong hướng dẫn giả mã 9618:

Kiểu Chứa Viết trong mã như Sử dụng điển hình
INTEGER số nguyên 42, -3 bộ đếm, chỉ số mảng, bộ đếm vòng lặp
REAL số có phần thập phân 3.75 giá, trung bình
CHAR một ký tự 'A' (nhất dấu) chữ grade, phím menu
STRING một chuỗi ký tự "Hello" (hai nhất dấu) tên, mã bưu chính
BOOLEAN TRUE hoặc FALSE TRUE cờ như Found
DATE ngày lịch 12/05/2026 ngày sinh

Câu hỏi "cho biết kiểu dữ liệu phù hợp" được trả lời dựa vào cách biến được sử dụng trong giả mã: một giá trị có dấu phẩy thập phân là REAL; cái gì đó được gán cho TRUE hoặc FALSE là BOOLEAN; một giá trị trong nhất dấu là CHAR; một giá trị được dùng làm chỉ số mảng, hoặc với DIV và MOD, là INTEGER. Viết kiểu bằng chữ in hoa, chính tả giống như hướng dẫn.

Ví dụ minh họa. Nêu kiểu dữ liệu phù hợp cho mỗi biến.

Found ← FALSE
Initial ← 'K'
Price ← 12.99
Count ← Count + 1
Name ← "Li Wei"

Found là BOOLEAN (chứa FALSE); Initial là CHAR (một ký tự trong nhất dấu); Price là REAL (giá trị thập phân); Count là INTEGER (bộ đếm tăng lên một); Name là STRING (văn bản trong hai nhất dấu).

Gán và biểu thức

Dùng ← cho phép gán:

Total ← Total + 1
Average ← Sum / Count

Biểu thức sử dụng toán tử:

  • toán học + - * /, cộng DIV (phép chia lấy phần nguyên) và MOD (phần dư): 7 DIV 2 = 3; 7 MOD 2 = 1.
  • so sánh =, <>, <, >, <=, >=.
  • logic AND, OR, NOT.

Độ ưu tiên (cao đến thấp): NOT → * / DIV MOD → + - → so sánh → AND → OR. Dùng ngoặc đơn khi không chắc chắn.

Nhập và xuất

OUTPUT "Enter your name:"
INPUT Name
OUTPUT "Hello, ", Name

Hàm tích hợp và thủ tục thư viện

Nhiều tác vụ đã có sẵn thủ tục thư viện, nên bạn không cần viết chúng. Lời giải thích (insert) của Bài 2 liệt kê những thủ tục bạn có thể sử dụng, kèm theo tên chính xác, tham số và kiểu trả về; bất kỳ hàm nào khác mà câu hỏi yêu cầu đều được cung cấp trong chính câu hỏi đó. Các tên dưới đây là tên gọi trong lời giải thích. VAL và STR là tên gọi IGCSE và không xuất hiện trong tài liệu 9618, do đó không mang điểm. UCASE và LCASE thuộc trường hợp khác: chúng là một phần của 9618, được định nghĩa trong Hướng dẫn Pseudocode, nhưng chỉ nhận một CHAR, và lời giải thích không liệt kê chúng — đối với một chuỗi hoàn chỉnh trong Bài 2, thủ tục sẽ là TO_UPPER.

Một thư viện chương trình chứa các thủ tục đã được viết, biên dịch và kiểm tra sẵn; một chương trình gọi chúng thay vì tự viết riêng. Những lợi ích mà đề bài chấp nhận, cho câu hỏi "liệt kê ba lợi ích": các thủ tục đã được kiểm tra, nên ít khả năng chứa lỗi; chúng tiết kiệm thời gian phát triển; chúng có thể thực hiện những việc mà lập trình viên khó tự viết (thống kê phức tạp, đồ họa); chúng được viết bởi chuyên gia và tái sử dụng trên nhiều chương trình; và một thủ tục có giao diện cố định có thể được gọi từ bất cứ đâu trong chương trình.

Thủ tục Trả về Ví dụ
LENGTH(s) số ký tự trong s LENGTH("Hello") = 5
LEFT(s, n) / RIGHT(s, n) n ký tự đầu tiên / cuối cùng RIGHT("Hello", 2) = "lo"
MID(s, start, n) n ký tự bắt đầu từ vị trí start (vị trí tính từ 1) MID("Hello", 2, 3) = "ell"
TO_UPPER(s) / TO_LOWER(s) s in hoa / in thường TO_UPPER("ab1") = "AB1"
NUM_TO_STR(x) / STR_TO_NUM(s) một số thành chuỗi / một chuỗi thành số STR_TO_NUM("3.5") = 3.5
IS_NUM(s) TRUE nếu s là số hợp lệ IS_NUM("12a") = FALSE
ASC(c) / CHR(n) mã ký tự của c / ký tự có mã n ASC('A') = 65, CHR(66) = 'B'
INT(x) phần nguyên của x INT(7.9) = 7
RAND(n) một số thực ngẫu nhiên từ 0 đến (không bao gồm) n INT(RAND(6)) + 1 là kết quả tung xúc xắc
DAY(d), MONTH(d), YEAR(d) các phần của một DATE YEAR(TODAY())
DAYINDEX(d), SETDATE(d, m, y), TODAY() ngày trong tuần (1 = Chủ nhật); một ngày tháng được xây dựng từ ba số nguyên; ngày hôm nay
EOF(f) TRUE khi tập tin f không còn dòng nào để đọc WHILE NOT EOF("data.txt")

Các chuỗi được nối với nhau bằng & (nối chuỗi): "A" & "BC" là "ABC". Sử dụng đúng tên gọi từ lời giải thích, với các tham số theo đúng thứ tự của nó.

Ngày tháng và số ngẫu nhiên thường xuất hiện dưới dạng câu lệnh một dòng. SETDATE(17, 11, 2007) tạo ra ngày 17 tháng 11 năm 2007; 12 - MONTH(MyDOB) là số tháng từ tháng sinh đến hết năm; IF DAYINDEX(MyDOB) = 5 THEN kiểm tra xem có phải thứ Năm hay không, vì Chủ nhật là ngày 1. RAND(n) trả về một số thực từ 0 đến (không bao gồm) n, do đó một số nguyên ngẫu nhiên từ Low đến High (bao gồm cả hai đầu mút) sẽ là INT(RAND(High - Low + 1)) + Low: INT(RAND(21)) - 10 cho một giá trị từ -10 đến 10.

Chuỗi COMPUTER được hiển thị dưới dạng tám ô ký tự đánh số (vị trí 1 đến 8), với các kết quả mẫu: LENGTH(s) = 8, LEFT(s, 3) = COM, MID(s, 4, 3) = PUT, RIGHT(s, 2) = ER, và UCASE/LCASE thay đổi chữ in hoa/thường
Các thủ tục chuỗi phổ biến tác động lên s = "COMPUTER" (vị trí 1–8)

Ví dụ có hướng dẫn. Tính giá trị của mỗi biểu thức, biết rằng Word ← "Program", Code ← 'Q' và N ← 7.

Biểu thức Giá trị Lý do
LENGTH(Word) 7 bảy ký tự
MID(Word, 4, 2) "gr" hai ký tự, bắt đầu từ vị trí 4
LEFT(Word, 3) & "!" "Pro!" được nối với &
TO_UPPER(RIGHT(Word, 2)) "AM" hàm bên trong chạy trước
ASC(Code) - ASC('A') 16 'Q' là 81 và 'A' là 65
N DIV 2 + N MOD 2 4 3 + 1
NUM_TO_STR(N) & "th" "7th" số trở thành chuỗi trước
INT(N / 2) 3 3.5 bị cắt xuống phần nguyên

Tính từ trong ra ngoài, và giữ nguyên dấu ngoặc kép: "7" là chuỗi và 7 là số.

Ví dụ có hướng dẫn. Mỗi câu lệnh có thể chứa lỗi trong cách sử dụng hàm hoặc toán tử. Mô tả lỗi, hoặc viết KHÔNG CÓ LỖI. (Giả sử mọi biến đều có đúng kiểu dữ liệu.)

Câu lệnh Lỗi
Result ← 2 & 4 & dùng để nối chuỗi; 2 và 4 là số nguyên, nên cần +
SubString ← MID("pseudocode", 4, 1) KHÔNG CÓ LỖI: lấy một ký tự từ vị trí 4, "u"
IF x = 3 OR 4 THEN OR cần một giá trịBoolean ở mỗi bên: IF x = 3 OR x = 4 THEN
Result ← Status AND INT(x / 2) AND cần hai giá trịBoolean; INT(x / 2) là số nguyên
Message ← "Done" + LENGTH(MyString) + không thể cộng chuỗi với số nguyên: "Done" & NUM_TO_STR(LENGTH(MyString))

Mỗi toán tử hoạt động trên các kiểu cụ thể: & trên chuỗi, + - * / DIV MOD trên số, AND OR NOT trên Boolean, và = <> trên hai giá trị có cùng kiểu. Một bảng "tính giá trị mỗi biểu thức, hoặc viết LỖI" được chấm điểm tương tự: LENGTH(42) và "A" + 1 là LỖI, vì kiểu dữ liệu không khớp với hàm hoặc toán tử.

Ví dụ có hướng dẫn. Với Points ← 100, Active ← TRUE và Exempt ← FALSE, hãy tính giá trị của mỗi biểu thức.

Biểu thức Giá trị Lý do
(Points > 99) OR Active TRUE cả hai vế đều đúng; một trong hai sẽ đủ
(Points MOD 2 = 0) OR Exempt TRUE 100 MOD 2 là 0
(Points <= 75) AND (Active OR Exempt) FALSE vế trái sai, và AND cần cả hai
(Active OR NOT Active) AND NOT Exempt TRUE Active OR NOT Active luôn đúng

Biểu thức cuối cùng rút gọn: X OR NOT X là TRUE bất kể X là gì, nên toàn bộ biểu thức chỉ còn NOT Exempt. Tính ngoặc trước, sau đó đến NOT, rồi AND, và cuối cùng là OR.

Khám phá

Một biến là một hộp có nhãn

Mỗi phép gán lưu một giá trị vào một hộp tên; việc gán lại cùng tên sẽ ghi đè lên nó. Hãy lần lượt thực thi chương trình và xem mỗi hộp nhận giá trị hiện tại của nó.

Từ vựng Luyện tập
English Tiếng Việt
pseudocode/ˈsuːdəʊkəʊd/ A language-independent description of an algorithm using structured, programming-like statements.
variables/ˈveərɪəblz/ variables
data types/ˈdeɪtə taɪps/ data types
assignment/əˈsaɪnmənt/ Storing a value in a variable or other named location.
constant/ˈkɒnstənt/ A named or literal value that does not change during the relevant part of a program.
identifier/aɪˈdentɪfaɪə/ identifier
function/ˈfʌŋkʃn/ A mapping that assigns exactly one output to each allowed input.
library routines/ˈlaɪbrəri ruːˈtiːnz/ library routines
insert/ˈɪnsɜːt/ insert
parameters/pəˈræmɪtəz/ Values that specify a model or function, or named inputs that a subroutine receives.
program library/ˈprəʊɡræm ˈlaɪbrəri/ program library
concatenation/kənˌkætəˈneɪʃn/ concatenation
selection/sɪˈlekʃn/ Choosing which branch of instructions to execute according to a condition.
nested/ˈnestɪd/ nested
logic error/ˈlɒdʒɪk ˈerə/ A mistake in an algorithm or program that produces an incorrect result despite valid syntax.
trace table/treɪs ˈteɪbl/ trace table
iteration/ˌɪtəˈreɪʃn/ Repeating a sequence of instructions or calculations.
count-controlled loop/kaʊnt kənˈtrəʊld luːp/ A loop that repeats according to a counter, usually for a specified number of iterations.
pre-condition loop/priː kənˈdɪʃn luːp/ A loop that tests its continuation condition before executing its body, so the body may run zero times.
post-condition loop/pəʊst kənˈdɪʃn luːp/ A loop that tests its continuation or termination condition after executing its body, so it runs at least once.
dry run/draɪ rʌn/ dry run
11.2

Chọn lọc

Chương trình
Thí sinh cần có thể: Ghi chú và hướng dẫn
Sử dụng giả mã để viết: • câu lệnh ‘IF’ bao gồm cả mệnh đề ‘ELSE’ và câu lệnh IF lồng nhau • cấu trúc ‘CASE’ • vòng lặp ‘điều khiển bằng đếm’: • vòng lặp ‘điều kiện hậu’ • vòng lặp ‘điều kiện tiền’
Giải thích tại sao một cấu trúc vòng lặp này có thể phù hợp hơn để giải quyết bài toán so với các cấu trúc khác

Nguồn: Chương trình Cambridge International

Chọn lọc quyết định bước nào sẽ được thực thi.

IF age >= 18 THEN
    OUTPUT "Adult"
ELSE
    OUTPUT "Minor"
ENDIF
Sơ đồ luồng: từ Start, kim cương quyết định kiểm tra age >= 18; nhánh TRUE xuất Adult và nhánh FALSE xuất Minor, và cả hai gặp nhau tại End
Câu lệnh IF...ELSE kiểm tra điều kiện một lần, sau đó chạy đúng một nhánh

Đối với hơn hai trường hợp, bạn có thể dùng IF lồng nhau, nhưng lồng sâu quá khó đọc — một CASE sạch sẽ hơn khi kiểm tra một giá trị so với nhiều tùy chọn:

CASE OF Grade
    "A": OUTPUT "Excellent"
    "B": OUTPUT "Good"
    OTHERWISE: OUTPUT "Try again"
ENDCASE

Cambridge CASE cho phép các giá trị đơn lẻ, danh sách giá trị (1, 2, 3:), và khoảng giá trị (1 TO 5:).

Một IF lồng nhau là một IF nằm trong một nhánh của một IF khác. Mỗi IF cần có riêng một ENDIF, và giám khảo kiểm tra xem mọi cấu trúc đều được đóng:

IF Mark >= 50 THEN
    IF Mark >= 80 THEN
        OUTPUT "Distinction"
    ELSE
        OUTPUT "Pass"
    ENDIF
ELSE
    OUTPUT "Fail"
ENDIF

Các biên giới là nơi bị mất điểm. "Điểm từ 50 trở lên mới đạt" là Mark >= 50, không phải Mark > 50; nhánh cuối cùng CASE cho "bất cứ cái gì khác", được viết là OTHERWISE, không phải một điều kiện như > 200. Một phép so sánh sai ở đây là lỗi logic: chương trình vẫn chạy, nhưng đưa ra kết quả sai cho một số đầu vào — và bảng truy vết với một giá trị biên như 50 chính là cách để tìm ra lỗi này.

Sơ đồ khối của một lệnh CASE OF Grade: giá trị được kiểm tra lần lượt với mỗi bảo vệ (một giá trị đơn, danh sách giá trị, sau đó là khoảng giá trị); nhánh khớp đầu tiên thực thi câu lệnh của nó, nếu không thì nhánh OTHERWISE sẽ chạy, và tất cả các nhánh hội tụ lại tại ENDCASE
Lệnh CASE chạy nhánh khớp với giá trị

Ví dụ đã giải. Viết lại đoạn mã này sao cho giữ nguyên chức năng, nhưng không sử dụng cấu trúc CASE.

CASE OF MySwitch
    1: ThisChar ← 'a'
    2: ThisChar ← 'y'
    3: ThisChar ← '7'
    OTHERWISE: ThisChar ← '*'
ENDCASE

Mỗi giá trị trở thành một nhánh của chuỗi các IF, và OTHERWISE trở thành nhánh ELSE cuối cùng:

IF MySwitch = 1 THEN
    ThisChar ← 'a'
ELSE
    IF MySwitch = 2 THEN
        ThisChar ← 'y'
    ELSE
        IF MySwitch = 3 THEN
            ThisChar ← '7'
        ELSE
            ThisChar ← '*'
        ENDIF
    ENDIF
ENDIF

Hai mệnh đề gán cùng một giá trị được gộp thành một mệnh đề với danh sách giá trị: 1, 2: ThisChar ← 'a'. Các bảo vệ được kiểm tra theo thứ tự: với các khoảng như 1 TO 50: theo sau bởi 40 TO 60:, một giá trị 45 sẽ chọn nhánh đầu tiên khớp, do đó một phép gán trong nhánh sau có thể bị bỏ qua hoàn toàn — và khi các nhánh trước đó đã bao phủ hết mọi giá trị có thể xảy ra, nhánh OTHERWISE cũng sẽ không bao giờ được thực hiện.

Ngược lại, các IF lồng nhau kiểm tra nhiều biến Boolean sẽ rõ ràng hơn nếu mỗi kết quả có một điều kiện duy nhất: IF A AND B AND C THEN CALL Sub1(), sau đó là IF A AND B AND NOT C THEN CALL Sub2(), v.v. Việc nối các phép kiểm tra bằng AND và OR giúp loại bỏ sự lồng nhau, và IF A THEN được chấp nhận thay cho IF A = TRUE THEN.

Khám phá

Chọn lọc (IF / ELSE)

Thay đổi đầu vào và xem nhánh nào chạy — bản chất của việc chọn lọc.

Từ vựng Luyện tập
English Tiếng Việt
flowchart/ˈfləʊtʃɑːt/ A diagram showing the sequence of steps and decisions in a process or algorithm.
structured English/ˈstrʌktʃəd ˈɪŋɡlɪʃ/ structured English
11.2

Lặp

Lặp thực thi lặp đi lặp lại một khối lệnh. Ba loại vòng lặp khác nhau về số lần thân vòng lặp được thực hiện.

Vòng lặp kiểm soát đếm (FOR)

Một vòng lặp kiểm soát đếm — hãy dùng nó khi bạn biết trước số lần cần lặp:

FOR i ← 1 TO 10
    OUTPUT i
NEXT i

Một STEP có thể thay đổi bộ đếm (ví dụ: FOR i ← 10 TO 1 STEP -1). Phù hợp nhất cho số lần lặp cố định hoặc xử lý từng phần tử của một mảng.

Vòng lặp tiền điều kiện (WHILE)

Một vòng lặp tiền điều kiện kiểm tra điều kiện trước mỗi lần lặp, nên nó có thể được thực hiện không lần nào:

WHILE total < 100 DO
    INPUT n
    total ← total + n
ENDWHILE

Vòng lặp hậu điều kiện (REPEAT...UNTIL)

Một vòng lặp hậu điều kiện kiểm tra điều kiện sau mỗi lần lặp, nên nó luôn được thực hiện ít nhất một lần:

REPEAT
    INPUT password
UNTIL password = correctPassword

Chọn vòng lặp phù hợp

Ba cột sơ đồ khối. FOR: một ô đếm (i = 1 đến N) rồi ô thân, quay lại, cho số lần lặp xác định. WHILE: kim cương kiểm tra trên ô thân, nên điều kiện được kiểm tra trước thân và vòng lặp có thể chạy không lần. REPEAT: ô thân trên kim cương kiểm tra, nên điều kiện được kiểm tra sau thân và vòng lặp chạy ít nhất một lần
Ba vòng lặp khác nhau ở vị trí kiểm tra điều kiện — trước thân (WHILE), sau thân (REPEAT), hoặc số lần lặp xác định (FOR)
  • đếm biết trước → FOR.
  • có thể cần không lần lặp nào → WHILE.
  • luôn ít nhất một lần lặp → REPEAT...UNTIL.

Giải thích lựa chọn của bạn dựa vào việc liệu đếm có biết trước hay không và liệu thân vòng lặp có bắt buộc chạy ít nhất một lần hay không. Một câu hỏi điển hình đưa ra tình huống ("hỏi mật khẩu cho đến khi đúng, nhưng luôn hỏi ít nhất một lần") và yêu cầu xác định vòng lặp nào phù hợp.

Hai điểm đánh giá thuộc về tên của vòng lặp và lý do, theo đúng thuật ngữ của phương án chấm điểm: kiểm soát đếm, vì số lần lặp đã biết trước khi vòng lặp bắt đầu; hậu điều kiện, vì thân vòng lặp phải được thực hiện ít nhất một lần; tiền điều kiện, vì vòng lặp có thể không cần thực hiện gì cả. Một vòng lặp duyệt qua bốn phần tử của mảng được viết dưới dạng WHILE kèm theo bộ đếm sẽ bị coi là "không phải lựa chọn tối ưu": vì đếm (bốn) đã biết trước, nên vòng lặp FOR sẽ phù hợp hơn.

Ví dụ đã giải. Vòng lặp nào phù hợp với mỗi nhiệm vụ? (a) in bảng nhân 12; (b) tiếp tục đọc số cho đến khi người dùng nhập 0; (c) hỏi mật khẩu cho đến khi đúng. Hãy chọn bằng cách đặt câu hỏi số lần thân vòng lặp chạy và khi nào phép kiểm tra diễn ra. (a) Đếm biết trước (12), nên dùng vòng lặp FOR. (b) Đếm không biết trước, và ngay cả đầu vào đầu tiên đã có thể là 0 - nên phép kiểm tra phải nằm trước thân: vòng lặp WHILE, chạy không hoặc nhiều lần. (c) Đếm không biết trước, nhưng bạn luôn phải hỏi ít nhất một lần trước khi có dữ liệu để kiểm tra - nên phép kiểm tra nằm sau thân: REPEAT...UNTIL, chạy một hoặc nhiều lần. Câu hỏi quyết định là liệu thân vòng lặp có bắt buộc chạy ít nhất một lần hay không: WHILE có thể chạy không lần, REPEAT luôn chạy ít nhất một lần.

Chạy thử tay với bảng theo dõi

Một bảng theo dõi ghi lại giá trị của mỗi biến khi bạn chạy thử tay (thực hiện bằng tay) một thuật toán. Đây là cách bạn kiểm tra vòng lặp trên giấy, và là một câu hỏi 6 điểm trong hầu hết các đề thi Paper 2.

DECLARE Count, Total : INTEGER
Count ← 1
Total ← 0
WHILE Total < 10
    Total ← Total + Count * 2
    Count ← Count + 1
ENDWHILE
OUTPUT Count, Total
Đếm Tổng Tổng < 10 OUTPUT
1 0 TRUE
2 2 TRUE
3 6 TRUE
4 12 FALSE 4, 12

Các quy tắc để lấy điểm: một cột cho mỗi biến, theo thứ tự mà đề bài cung cấp; chỉ ghi giá trị khi nó thay đổi; bắt đầu dòng mới mỗi khi vòng lặp lặp lại; đánh giá điều kiện với các giá trị hiện tại, và dừng ngay khi nó là FALSE; đặt kết quả đầu ra trong cột riêng, đúng y như cách nó hiển thị. Theo dõi thuật toán như đã viết, không phải như bạn nghĩ nó nên được viết — nếu nó không bao giờ dừng, hãy ghi rõ điều đó.

Ví dụ đã giải. Mỗi dòng sử dụng những cấu trúc nào — chọn, lặp hay gọi thủ tục con?

Mã giả Chọn Lặp Thủ tục con
IF Ready = TRUE THEN
CALL Start()

ENDIF | FOR I ← 1 TO 20 ... NEXT I | | yes | | | WHILE NOT IsFull() ... ENDWHILE | | yes | yes | | CASE OF Key ... OTHERWISE ... ENDCASE | yes | | |

IF và CASE là chọn lọc; FOR, WHILE và REPEAT là lặp lại; một tên theo sau bởi dấu ngoặc — Start(), IsFull() — là lời gọi một thủ tục hoặc hàm, ở bất cứ đâu, bao gồm cả bên trong điều kiện.

Khám phá

Theo dõi vòng lặp, từng bước một

Bảng theo dõi ghi lại mỗi biến sau mỗi lần lặp của vòng lặp. Hãy xem bộ đếm i tăng dần trong khi tổng tích lũy đang hình thành — đúng những gì câu hỏi theo dõi đề thi yêu cầu bạn điền.

Khám phá

Theo dõi vòng lặp

Từng bước một vòng lặp và quan sát các biến thay đổi sau mỗi lượt — đúng những gì bảng truy vết ghi lại.

11.3

Thủ tục và hàm

Chương trình
Thí sinh cần có thể: Ghi chú và hướng dẫn
Định nghĩa và sử dụng thủ tục
Giải thích vị trí thích hợp trong quá trình xây dựng thuật toán để sử dụng một thủ tục
Sử dụng tham số Một thủ tục có thể không có, một hoặc nhiều tham số Một tham số có thể được truyền theo chỉ trỏ hoặc theo giá trị
Định nghĩa và sử dụng hàm
Giải thích nơi nào trong quá trình xây dựng thuật toán thì phù hợp để sử dụng một hàm Một hàm được sử dụng trong biểu thức, ví dụ: giá trị trả về thay thế cho lời gọi
Sử dụng thuật ngữ liên quan đến thủ tục và hàm bao gồm header thủ tục/hàm, giao diện thủ tục/hàm, tham số, thực tham số, giá trị trả về
Viết giả mã hiệu quả

Nguồn: Chương trình Cambridge International

Lập trình có cấu trúc xây dựng chương trình từ các phần tử con có tên nhỏ, mỗi phần tử thực hiện một nhiệm vụ.

Thủ tục

Một thủ tục là một khối có tên thực hiện một hành động; nó có thể nhận tham số nhưng không trả về giá trị.

PROCEDURE Greet(name : STRING)
    OUTPUT "Hello, ", name
ENDPROCEDURE

CALL Greet("Ada")

Hàm

Một hàm giống như thủ tục nhưng nó trả về một giá trị trở thành một phần của biểu thức.

FUNCTION Square(x : INTEGER) RETURNS INTEGER
    RETURN x * x
ENDFUNCTION

result ← Square(5) + 1     // result = 26

Sử dụng thủ tục khi phần tử con thực hiện một hành động; sử dụng hàm khi nó tính toán một giá trị cho người gọi.

Chương trình yêu cầu nơi nào trong việc xây dựng thuật toán thì từng loại phù hợp. Một thủ tục phù hợp nơi cùng một nhóm bước được cần ở nhiều điểm (kiểm tra đầu vào, in menu, hoán đổi hai giá trị): các bước được viết một lần và CALL bằng tên. Một hàm phù hợp nơi một giá trị đơn lẻ phải được tính toán rồi sử dụng trong biểu thức — tổng, kết quả TRUE/FALSE, số lớn hơn của hai số — vì giá trị trả về thay thế cho lời gọi: IF IsValid(Code) THEN.

Hai bảng. Thủ tục: gọi Greet(Ada) thực hiện hành động và in Hello, Ada, không trả về giá trị. Hàm: gán y = Square(5) tính 5 nhân 5 = 25, trả về 25, nên y lúc này chứa 25
A thủ tục thực hiện một hành động và không trả về gì; một hàm trả về một giá trị bạn dùng trong biểu thức

Tham số

Một tham số là biến mà phần tử con khai báo để nhận đầu vào; các giá trị người gọi cung cấp là đối số. Hai cách truyền chúng:

  • truyền theo giá trị — routine nhận được một bản sao; những thay đổi bên trong nó không ảnh hưởng đến người gọi. Dùng cho đầu vào chỉ đọc.
  • truyền theo tham chiếu — routine nhận được một tham chiếu đến biến của người gọi; những thay đổi có ảnh hưởng đến người gọi. Dùng khi nó phải cập nhật tham số.
Hai sơ đồ ô bộ nhớ. Truyền theo giá trị: biến x = 5 của người gọi được sao chép vào ô tham số riêng a = 5, nên thay đổi a giữ nguyên x là 5. Truyền theo tham chiếu: tham số a là mũi tên trỏ đến ô x của chính người gọi, nên thay đổi a cũng làm x thay đổi
Truyền theo giá trị sao chép giá trị vào ô mới; truyền theo tham chiếu cho phép routine thay đổi biến của chính người gọi
PROCEDURE Swap(BYREF a : INTEGER, BYREF b : INTEGER)
    DECLARE temp : INTEGER
    temp ← a
    a ← b
    b ← temp
ENDPROCEDURE

Cambridge pseudocode ghi chế độ trong header, BYVAL hoặc BYREF, trước mỗi tham số. Nếu không ghi gì, BYVAL được mặc định, nên routine cần thay đổi biến của người gọi — Swap, hoặc thủ tục cập nhật tổng tích lũy — cần BYREF trong header của nó.

Ví dụ minh họa. Kết quả là gì?

PROCEDURE Adjust(BYREF X : INTEGER, BYVAL Y : INTEGER)
    X ← X + Y
    Y ← Y * 2
ENDPROCEDURE

A ← 5
B ← 3
CALL Adjust(A, B)
OUTPUT A, B

X là tham chiếu đến A, nên A trở thành 8. Y là bản sao của B, nên nhân đôi Y giữ nguyên B ở 3. Kết quả là 8, 3. Nếu header nói BYVAL X, A vẫn sẽ là 5.

Biến cục bộ và toàn cục

Một biến cục bộ được khai báo bên trong phần tử con và chỉ tồn tại khi nó chạy. Một biến toàn cục được khai báo bên ngoài và khả thị ở mọi nơi. Ưu tiên biến cục bộ và tham số — sử dụng quá mức biến toàn cục khiến code khó theo dõi và kiểm thử. (Vùng mà tên khả thị là phạm vi của nó.)

Sự khác biệt một dòng: biến toàn cục có thể truy cập từ bất cứ đâu trong chương trình, biến cục bộ chỉ bên trong phần tử con khai báo nó. Lợi ích của biến cục bộ mà đề thi chấp nhận: cùng một danh định danh có thể được dùng trong phần tử con khác mà không gây va chạm; giá trị không thể bị thay đổi vô tình bởi các phần khác của chương trình; bộ nhớ được giải phóng khi phần tử con kết thúc; và phần tử con là tự chứa, nên nó có thể được kiểm thử độc lập và tái sử dụng trong chương trình khác.

Biến cục bộ được tạo ra mỗi lần phần tử con được gọi và bị hủy khi nó trả về, nên nó không thể mang giá trị từ lần gọi này sang lần khác. Một thủ tục xây dựng chuỗi qua nhiều lần gọi do đó cần chuỗi đó là toàn cục (hoặc truyền BYREF). Nếu MyString bị đổi từ toàn cục sang cục bộ được khai báo bên trong MyOutput(), mỗi lần gọi bắt đầu với MyString mới, rỗng, văn bản thêm bởi các lần gọi trước bị mất, và thủ tục "không hoạt động như mong đợi".

Ba lần gọi thủ tục giống nhau trên trục thời gian; mỗi lần gọi tạo ô MyString cục bộ riêng của nó, mới và rỗng, biến mất khi lần gọi trả về, trong khi một ô MyString toàn cục phía trên giữ nguyên giá trị giữa các lần gọi
Biến cục bộ là một ô mới, rỗng mỗi lần gọi; chỉ biến toàn cục (hoặc tham số BYREF) giữ giá trị giữa các lần gọi
Một ô lớn bên ngoài mang nhãn phạm vi toàn cục chứa biến toàn cục Total, khả thị ở mọi nơi, và một ô nhỏ bên trong mang nhãn PROCEDURE Calc, phạm vi cục bộ, chứa biến cục bộ temp, chỉ tồn tại khi Calc chạy
Biến toàn cục khả thị ở mọi nơi; biến cục bộ chỉ tồn tại bên trong thủ tục của chính nó

Khi nào sử dụng phần tử con

Sử dụng phần tử con khi:

  • logic tương tự xuất hiện ở nhiều hơn một nơi — viết nó một lần, gọi nó nhiều lần.
  • một khối có mục đích đặt tên rõ ràng — tên tài liệu hóa những gì nó làm.
  • chương trình phức tạp — chia nó thành các phần (phân rã).
  • bạn muốn kiểm thử một phần độc lập.

Đừng làm chúng quá nhỏ đến mức chi phí lời gọi cao hơn công việc bên trong.

Thuật ngữ

  • định nghĩa — khối PROCEDURE ... ENDPROCEDURE (hoặc hàm).
  • lời gọi — nơi nó được kích hoạt. Đối số — giá trị được truyền vào. Tham số — biến nhận giá trị đó.
  • giá trị trả về — thứ hàm gửi lại.
  • header thủ tục/hàm — dòng đầu tiên đưa ra tên và tham số (PROCEDURE Name(params) hoặc FUNCTION Name(params) RETURNS type).
  • giao diện/hàm/thủ tục / chữ ký (signature) — tên + tham số + kiểu trả về: những gì người gọi cần biết để sử dụng nó.

Ví dụ minh họa. Giải thích từng thuật ngữ được sử dụng trong phần header FUNCTION Pass2(Count : INTEGER) RETURNS BOOLEAN.

Thuật ngữ Ý nghĩa
FUNCTION một thủ tục con trả về giá trị
Pass2 định danh được dùng để gọi nó
Count tham số: định danh nhận giá trị đối số được truyền vào
INTEGER kiểu dữ liệu của tham số
RETURNS BOOLEAN kiểu dữ liệu của giá trị mà hàm trả về

Hai định danh trong PROCEDURE MyProc(Count : INTEGER, Message : STRING) là tham số: chúng nhận các giá trị được truyền vào khi thủ tục được gọi, và được sử dụng bên trong như các biến cục bộ.

Để chuyển đổi một thủ tục thành hàm: thay PROCEDURE bằng FUNCTION và thêm RETURNS <type>; thay thế OUTPUT (hoặc tham số BYREF mang kết quả ra ngoài) bằng câu lệnh RETURN; và thay đổi mọi lời gọi sao cho giá trị trả về được sử dụng, Result ← Unpack(Text) thay vì CALL Unpack(Text, Result). Đối với câu hỏi "viết header", hãy viết toàn bộ dòng: FUNCTION Calculate(Expression : STRING) RETURNS INTEGER. Một tham số mảng được truyền theo tham chiếu, nên một thủ tục ghi vào mảng sẽ thay đổi mảng của người gọi.

Khi chương trình có thêm một mô-đun mới, giao diện là điều được thống nhất trước tiên: tên, các tham số (số lượng, thứ tự, kiểu loại) và kiểu trả về, cùng bất kỳ dữ liệu toàn cục nào mô-đun đọc hoặc ghi. Một mô-đun gửi nhắc nhở trước ngày hạn chót cần bản ghi (hoặc chỉ mục) làm tham số và không trả về gì, nên nó là một thủ tục; chương trình chính gọi nó một lần cho mỗi bản ghi.

Viết một mô-đun cho Bài thi 2

Một nửa Bài thi 2 là "viết pseudocode cho mô-đun X". Bộ đề chấm điểm dựa trên từng tính năng, nên một mô-đun chưa hoàn chỉnh vẫn nhận điểm cho từng phần đúng. Các phần mà giám khảo tìm kiếm:

Hàm pseudocode có chú thích, CountAbove, với chú thích giải thích từng phần nhận điểm: header với tham số và kiểu trả về, khai báo cục bộ, tổng được khởi tạo trước vòng lặp, vòng lặp FOR duyệt qua từng phần tử, điều kiện IF với giới hạn phải, cập nhật bên trong IF, các cấu trúc đóng, và RETURN sau vòng lặp
Mỗi phần của câu trả lời mô-đun đều có điểm riêng, nên hãy viết tất cả chúng ngay cả khi bạn không chắc chắn về một phần
  1. Header, như mô tả trong câu hỏi: PROCEDURE Name(Param : TYPE) hoặc FUNCTION Name(Param : TYPE) RETURNS TYPE, với BYREF ở nơi thủ tục cần thay đổi đối số.
  2. Khai báo cục bộ: DECLARE cho mỗi biến cục bộ kèm kiểu của nó, và khởi tạo bộ đếm/tổng (Count ← 0).
  3. Vòng lặp truy cập mọi phần tử: FOR Index ← 1 TO 50 cho mảng có kích thước đã cho; WHILE NOT EOF(...) cho tệp tin.
  4. Điều kiện, với phép so sánh và giới hạn đúng, áp dụng cho phần tử phải: IF Score[Index] > Limit THEN.
  5. Cập nhật bên nhánh: tăng bộ đếm, lưu giá trị, hoặc xuất thông điệp.
  6. Kết thúc: RETURN một lần, sau vòng lặp, trong hàm; ENDFUNCTION hoặc ENDPROCEDURE; và mọi IF, FOR và WHILE phải được đóng lại.

Ví dụ minh họa. Một mảng toàn cục Score : ARRAY[1:50] OF INTEGER chứa điểm kiểm tra. Viết hàm CountAbove(Limit : INTEGER) trả về số điểm lớn hơn Limit.

FUNCTION CountAbove(BYVAL Limit : INTEGER) RETURNS INTEGER
    DECLARE Index, Count : INTEGER
    Count ← 0
    FOR Index ← 1 TO 50
        IF Score[Index] > Limit THEN
            Count ← Count + 1
        ENDIF
    NEXT Index
    RETURN Count
ENDFUNCTION

Điểm: header với tham số và RETURNS INTEGER; Count được khai báo và gán 0; vòng lặp duyệt qua tất cả 50 phần tử; phép so sánh > Limit (không phải >=); cập nhật bộ đếm bên trong IF; RETURN Count sau vòng lặp. Chương trình chính sử dụng giá trị trả về trong biểu thức hoặc đầu ra: OUTPUT "Above 70: ", CountAbove(70).

Ví dụ minh họa. Viết hàm IsValid(Code : STRING) trả về TRUE khi Code giống hai chữ cái in hoa theo sau là bốn chữ số — định dạng AB1234 — và FALSE nếu không.

FUNCTION IsValid(BYVAL Code : STRING) RETURNS BOOLEAN
    DECLARE Index : INTEGER
    DECLARE Ch : STRING
    IF LENGTH(Code) <> 6 THEN
        RETURN FALSE
    ENDIF
    FOR Index ← 1 TO 6
        Ch ← MID(Code, Index, 1)
        IF Index <= 2 THEN
            IF Ch < "A" OR Ch > "Z" THEN
                RETURN FALSE
            ENDIF
        ELSE
            IF Ch < "0" OR Ch > "9" THEN
                RETURN FALSE
            ENDIF
        ENDIF
    NEXT Index
    RETURN TRUE
ENDFUNCTION

Kiểm tra độ dài đến trước, nên MID không bao giờ bị yêu cầu vị trí không tồn tại. Xác thực như vậy trả về một BOOLEAN để người gọi có thể viết IF IsValid(Entry) THEN ... ELSE OUTPUT "Invalid code" ENDIF: một thông điệp đến người dùng được xuất bởi người gọi, không phải bởi hàm — hàm thực hiện tính toán, thủ tục thực thi hành động.

Ví dụ minh họa. Viết hàm IsPalindrome(Word : STRING) trả về TRUE khi Word đọc ngược lại giống nhau, ví dụ như "RACECAR".

So sánh các ký tự từ hai đầu, di chuyển vào trong: vị trí Index được ghép đôi với vị trí Len - Index + 1, và chỉ cần kiểm tra nửa đầu.

Từ RACECAR nằm trong bảy ô đánh số; cung nối vị trí 1 với 7, 2 với 6 và 3 với 5, được gán nhãn vị trí i và vị trí Len trừ i cộng 1; ký tự ở giữa không có cặp đối xứng
Kiểm tra chuỗi đảo ngược ghép đôi vị trí i với vị trí Len - i + 1 và dừng lại ở giữa
FUNCTION IsPalindrome(BYVAL Word : STRING) RETURNS BOOLEAN
    DECLARE Len, Index : INTEGER
    Len ← LENGTH(Word)
    FOR Index ← 1 TO Len DIV 2
        IF MID(Word, Index, 1) <> MID(Word, Len - Index + 1, 1) THEN
            RETURN FALSE
        ENDIF
    NEXT Index
    RETURN TRUE
ENDFUNCTION

Ba công cụ tương tự nhau — một FOR duyệt qua các vị trí, MID(s, i, 1) để đọc một ký tự, và & để xây dựng chuỗi mới — giải quyết hầu hết các mô-đun chuỗi trong Bài thi 2: đếm số lần một ký tự xuất hiện (IF MID(s, i, 1) = Ch THEN Count ← Count + 1), thay thế mọi instance của một ký tự (thêm hoặc NewChar hoặc ký tự gốc vào NewString tại mỗi vị trí), ẩn tất cả ngoại trừ bốn chữ số cuối của số thẻ (thêm '*' cho mọi vị trí cho đến Len - 4), hoặc viết MID() riêng bằng cách nối các ký tự từ Start đến Start + Length - 1. Việc gọi MID cho một vị trí vượt quá độ dài chuỗi là lỗi thời gian chạy, nên hãy kiểm tra LENGTH trước.

Tệp tin. Giá trị trong biến mất đi khi chương trình kết thúc, nên một mô-đun cần giữ dữ liệu cho lần chạy tiếp theo sẽ ghi nó vào tệp: OPENFILE "scores.txt" FOR WRITE, một WRITEFILE "scores.txt", NUM_TO_STR(Score[Index]) mỗi dòng bên trong vòng lặp, và CLOSEFILE "scores.txt" một lần, sau vòng lặp; đọc lại sử dụng FOR READ, READFILE và WHILE NOT EOF("scores.txt"). Chủ đề 10 có phần đầy đủ về tệp; ở đây điểm số dành cho mở ở chế độ đúng, đọc hoặc ghi bên trong vòng lặp, và đóng một lần sau khi kết thúc.

Khám phá

Ngăn gọi (call stack): đẩy vào khi gọi, rút ra khi trả về

Gọi một thủ tục sẽ đẩy một khung mới lên trên; trả về sẽ xóa nó đi và gửi lại một giá trị cho người gọi. Khung đang thực thi luôn là khung nằm ở vị trí trên cùng.

Từ vựng Luyện tập
English Tiếng Việt
array/əˈreɪ/ An indexed collection of elements arranged in one or more dimensions.
operators/ˈɒpəreɪtəz/ Symbols or keywords specifying operations to perform on values or expressions.
precedence/ˈpresɪdəns/ The rules determining which operators or actions are applied before others.
procedure/prəˈsiːdʒə/ A named sequence of instructions that performs a task when called.
structured programming/ˈstrʌktʃəd ˈprəʊɡræmɪŋ/ structured programming
subroutines/ˈsʌbruːtiːnz/ Named groups of instructions that can be called to carry out particular tasks.
return value/rɪˈtɜːn ˈvæljuː/ What a function passes back.
arguments/ˈɑːɡjuːmənts/ arguments
pass by value/pæs baɪ ˈvæljuː/ The routine gets a copy.
pass by reference/pæs baɪ ˈrefrəns/ The routine gets a reference to the caller's variable.
global variable/ˈɡləʊbl ˈveərɪəbl/ Declared outside every subroutine; it can be used anywhere in the program.
local variable/ˈləʊkl ˈveərɪəbl/ Declared inside a subroutine; it exists only while the subroutine runs and can be used only inside it.
scope/skəʊp/ scope
decomposition/ˌdiːkɒmpəˈzɪʃn/ The breakdown of a substance or system into simpler components.
signature/ˈsɪɡnɪtʃə/ signature
format/ˈfɔːmæt/ format
Validation/ˌvælɪˈdeɪʃn/ Validation
run-time error/rʌn taɪm ˈerə/ run-time error
invariant/ɪnˈveərɪənt/ invariant
linear search/ˈlɪnɪə sɜːtʃ/ Checking items in sequence until the required item is found or the list ends.
syntax error/ˈsɪntæks ˈerə/ A mistake that breaks the grammatical rules of a programming language.
11.3

Viết pseudocode hiệu quả

Ba đặc điểm làm cho mã giả dễ hiểu hơn — câu trả lời cho câu hỏi "nêu ba đặc điểm" — là tên gọi có ý nghĩa (Total, không phải t), thụt lề của các câu lệnh bên trong mỗi cấu trúc, và ghi chú (// ...) giải thích mục đích; các từ khóa viết hoa, một câu lệnh trên mỗi dòng và khoảng trắng giữa các phần cũng được chấp nhận. Mã giả hiệu quả còn tiến xa hơn:

  • di chuyển bất biến ra khỏi vòng lặp — nếu một giá trị (một bất biến) không thay đổi theo bộ đếm vòng lặp, hãy tính toán nó một lần trước khi bắt đầu vòng lặp.
  • thoát vòng lặp sớm khi tìm thấy đáp án (dừng tìm kiếm tuyến tính ngay khi mục tiêu xuất hiện).
  • tránh công việc dư thừa — lưu kết quả và tái sử dụng nó thay vì tính toán lại.
  • chọn cấu trúc dữ liệu phù hợp — mảng tốt hơn nhiều biến riêng lẻ khi các mục thuộc về nhau.
  • thay thế IF lồng sâu bằng CASE khi kiểm tra một giá trị với nhiều trường hợp.
  • ghi chú về ý định, không phải cơ chế (// validate the postcode, không phải // loop 6 times).
  • sử dụng tên gọi có ý nghĩa (numberOfPupils, không phải n) và khởi tạo biến trước khi sử dụng.
Di chuyển công việc không bao giờ thay đổi ra ngoài vòng lặp, để nó chạy một lần thay vì mọi lượt lặp
Di chuyển công việc không thay đổi ra ngoài vòng lặp để nó chỉ chạy một lần
11.3

Kiểm thử và lỗi

Ba loại lỗi, mỗi loại được phát hiện theo cách khác nhau:

Lỗi Ý nghĩa Ví dụ Phát hiện bởi
lỗi cú pháp một câu lệnh vi phạm quy tắc của ngôn ngữ thiếu ENDIF; OUTPT "Hi" trình biên dịch, trước khi chương trình chạy
lỗi thời gian thực thi chương trình chạy, nhưng một câu lệnh không thể thực hiện chia cho 0; chỉ số mảng là 0 hoặc 51; hàm được gọi với tham số không hợp lệ; vòng lặp không bao giờ kết thúc, khiến chương trình "đóng băng" khi đang chạy: chương trình dừng hoặc bị treo
lỗi logic chương trình chạy đến hết, nhưng đầu ra sai > nơi cần >=; tổng chưa bao giờ được gán 0 kiểm thử bằng bảng theo dõi và dữ liệu kiểm thử đã chọn

Một IDE giúp tìm hai loại lỗi cuối cùng: ngăn chặn dừng chương trình tại một dòng đã chọn; bước đơn sau đó chạy từng câu lệnh một; và cửa sổ báo cáo (hoặc theo dõi) hiển thị giá trị của mỗi biến tại thời điểm đó, nên dòng mà giá trị bị sai sẽ được nhìn thấy trực tiếp. Các phương pháp và dữ liệu kiểm thử có trong chủ đề 12.

Từ vựng Luyện tập
English Tiếng Việt
IDE/ˌaɪ diː ˈiː/ IDE
breakpoint/ˈbreɪkpɔɪnt/ breakpoint
single stepping/ˈsɪŋɡl ˈstepɪŋ/ single stepping
11.3

Các định nghĩa mà giám khảo chấp nhận

Một câu hỏi định nghĩa được chấm dựa trên từ ngữ cố định. Hãy học những câu này đúng chính xác.

Thuật ngữ Định nghĩa
thủ tục một hàm con thực hiện một tác vụ (một chuỗi các bước) và không trả về giá trị; nó được gọi với CALL
hàm một hàm con trả về một giá trị duy nhất về vị trí nơi nó được gọi, do đó có thể được sử dụng trong biểu thức
tham số tên gọi trong header của hàm con nhận giá trị hoặc tham chiếu khi hàm con được gọi
đối số giá trị (hoặc biến) được cung cấp trong lời gọi, khớp với một tham số
truyền theo giá trị một bản sao của giá trị đối số được giao cho hàm con, do đó những thay đổi bên trong nó không ảnh hưởng đến biến gốc
truyền theo tham chiếu địa chỉ của biến được giao cho hàm con, do đó những thay đổi bên trong nó sẽ thay đổi biến gốc
header dòng đầu tiên của định nghĩa hàm con: tên của nó, các tham số và, đối với hàm, kiểu trả về của nó
giao diện những gì chương trình gọi cần biết để sử dụng một hàm con: tên của nó, các tham số (số lượng, thứ tự, kiểu) và kiểu trả về của nó
giá trị trả về giá trị mà hàm truyền trở lại cho biểu thức đã gọi nó
biến cục bộ được khai báo bên trong một hàm con; nó chỉ tồn tại khi hàm con chạy và chỉ có thể được sử dụng bên trong hàm đó
biến toàn cục được khai báo bên ngoài mọi hàm con; nó có thể được sử dụng ở bất cứ đâu trong chương trình
vòng lặp điều khiển bởi đếm lặp lại một số lượng cố định, được điều khiển bởi bộ đếm (FOR ... NEXT)
vòng lặp tiền điều kiện kiểm tra điều kiện của nó trước mỗi lần lặp, do đó thân vòng có thể không bao giờ chạy (WHILE ... ENDWHILE)
vòng lặp hậu điều kiện kiểm tra điều kiện của nó sau mỗi lần lặp, do đó thân vòng chạy ít nhất một lần (REPEAT ... UNTIL)
hằng một giá trị có tên không thể thay đổi trong khi chương trình chạy
hàm con một khối mã độc lập thực hiện một tác vụ và được gọi theo tên: một thủ tục hoặc một hàm
hàm thư viện một hàm con đã được viết và kiểm thử sẵn, và có sẵn để gọi từ chương trình
11.3

Mẹo làm bài thi

  • Phân biệt thủ tục (không trả về giá trị) và hàm (trả về giá trị); hiểu truyền theo giá trị so với theo tham chiếu.
  • Chọn vòng lặp phù hợp: điều khiển bởi đếm (FOR) khi số lần lặp là known, điều khiển bởi điều kiện (WHILE/REPEAT) trong trường hợp ngược lại.
  • Phân biệt biến cục bộ so với toàn cục và phạm vi; ưu tiên biến cục bộ trong các mô-đun có thể tái sử dụng.
  • Sử dụng đúng tên routine và thứ tự tham số của sách hướng dẫn. VAL và STR là tên IGCSE và không điểm; UCASE và LCASE là các routine thật 9618 từ Hướng dẫn Mã giả nhưng hoạt động trên một ký tự, nên trong Bài thi 2, cả chuỗi sẽ chiếm TO_UPPER hoặc TO_LOWER.
  • Trong câu trả lời "viết mã giả", header, khai báo, vòng lặp, điều kiện, cập nhật và RETURN mỗi phần đều mang một điểm: viết tất cả sáu phần, ngay cả khi một phần không chắc chắn.

Lỗi thường gặp

  • Gọi một hàm và không sử dụng giá trị trả về. Gán kết quả, hoặc sử dụng nó trong biểu thức hoặc đầu ra: Sorted ← BubbleSort(MyArray, 7).
  • Truyền độ dài 1 ra: 6 cho mảng bảy phần tử, hoặc chỉ số cuối cùng nơi độ dài được yêu cầu. Quyết định xem tham số là độ dài hay chỉ số, và kiểm tra rằng phần tử cuối cùng được truy cập.
  • Đóng tệp bên trong vòng đọc tệp. Mở một lần, đóng một lần, sau vòng lặp.
  • Sử dụng đầu vào trực tiếp như tên tệp. Thêm phần mở rộng mà câu hỏi đã cung cấp: FileName ← Choice & ".txt".
  • Để các cấu trúc mở. Mỗi IF cần có ENDIF của nó, mỗi FOR cần có NEXT của nó, mỗi WHILE cần có ENDWHILE của nó, và mỗi hàm cần có RETURN của nó; sơ đồ chấm điểm sẽ trừ điểm cho lỗi này.
  • Sai biên giới: dùng > cho "ít nhất" (vốn là >=), hoặc dùng một mảng FOR bắt đầu từ 0 khi khai báo mảng là [1:50].
  • Biến đếm hoặc biến tổng mà chưa bao giờ được gán giá trị 0 trước khi vòng lặp bắt đầu.
  • Trong bảng theo dõi, viết lại mọi biến ở mỗi dòng, hoặc thay đổi giá trị trước khi câu lệnh thay đổi giá trị đó đã được thực thi.
  • Một nửa điều kiện: ví dụ IF x = 3 OR 4 — mỗi bên của OR và AND phải là một phép so sánh hoàn chỉnh. Và + không nối chuỗi; thay vào đó hãy dùng &.
  • Khai báo làm biến cục bộ một giá trị phải tồn tại giữa các lần gọi. Một biến tổng chạy hay một chuỗi được xây dựng qua nhiều lần gọi nên là biến toàn cục hoặc BYREF.

Bài học tương tác về chủ đề này

Làm theo từng bước, kèm theo bài tập kiểm tra ngay lập tức.

Đề thi cũ

Nhiều chủ đề hơn trong Khoa học máy tính A-Level

Đăng nhập hoặc tạo tài khoản

IGCSE, A-Level & AP