Перейти к содержанию

Программирование

A-Level Информатика · Тема 11

Видеоурок по этой теме Открыть страницу видео
24:05

Основы программирования

Программа должна запрашивать пароль и продолжать спрашивать, пока не введён правильный. Просто — но какой цикл использовать? Программы принимают решения и повторяют действия, и выбор…

Английское озвучивание · Английский + китайские субтитры (встроенные)

11.1

Основы программирования

Программа
Кандидаты должны уметь: Примечания и рекомендации
Реализовать и написать псевдокод по заданному дизайну, представленному в виде блок-схемы программы или структурированного английского языка
Написать псевдокод для: • объявления и инициализации констант • объявления переменных • присвоения значений переменным • выражений, использующих арифметические или логические операторы, ввода с клавиатуры и вывода на экран
Использовать встроенные функции и библиотеки Любые функции, не указанные в руководстве по псевдокоду, будут предоставлены. Функции обработки строк всегда предоставляются

Источник: Программа Cambridge International

Строки исходного кода на темном экране
Программирование превращает проект в инструкции, записанные в виде кода
Программист за компьютером
Программист пишет код и тестирует его по мере написания

От проекта к коду

Вы должны уметь преобразовать проект — блок-схему (блок-схема программы) или структурированный английский — в псевдокод, а затем в реальный язык:

  1. найти переменные и их типы данных.
  2. преобразовать блоки ввода/вывода в INPUT / OUTPUT.
  3. преобразовать ромбы решений в IF...ELSE...ENDIF (или CASE).
  4. преобразовать стрелки циклов в WHILE, REPEAT...UNTIL или FOR.
  5. преобразовать блоки процессов в присваивания или вычисления.
  6. проверить трассировкой небольшого входного значения.
Сопоставление символов блок-схемы с псевдокодом: параллелограмм ввода/вывода становится INPUT или OUTPUT, ромб решения — IF...THEN или CASE, прямоугольник процесса — присваивание x = выражение, а стрелка цикла — WHILE, FOR или REPEAT
Каждый символ блок-схемы становится ключевым словом псевдокода

Константы и переменные

Константа хранит значение, которое никогда не меняется; переменная хранит значение, которое может меняться. Объявляйте их с указанием типа:

Значение переменной может измениться; константа остается неизменной
Значение переменной может измениться; константа остается фиксированной
CONSTANT Pi = 3.14159
DECLARE Radius : REAL
DECLARE Area : REAL

Radius ← 5
Area ← Pi * Radius * Radius

Используйте константы для повторяющихся фиксированных значений (Pi, MaxScore); это делает код понятнее и легким для изменения в одном месте.

На экзамене константа — это ответ на вопрос «определите более подходящий способ представления» фиксированного значения, такого как ставка налога или максимальный балл, который встречается в нескольких местах псевдокода. Преимущества такой схемы: значение задается один раз и не может быть случайно изменено программой; изменение вносится в одном месте и распространяется на каждое утверждение, использующее его; идентификатор придает значению смысл (MaxScore вместо 100), поэтому код легче читать и проверять; и снижается риск опечатки в длинном значении, таком как 3.14159. Вопрос «назовите значение, которое можно заменить константой» требует дословного текста из псевдокода (0.2, 40), а не нового имени.

Каждая переменная объявляется один раз с идентификатором (ее именем) и типом данных перед использованием. Шесть типов в руководстве по псевдокоду 9618:

Тип Хранит Записывается в коде как Типичное применение
INTEGER целые числа 42, -3 счетчик, индекс массива, счетчик цикла
REAL числа с дробной частью 3.75 цена, среднее значение
CHAR один символ 'A' (одиночные кавычки) буква оценки, клавиша меню
STRING последовательность символов "Hello" (двойные кавычки) имя, почтовый индекс
BOOLEAN TRUE или FALSE TRUE флаг, такой как Found
DATE календарную дату 12/05/2026 дата рождения

Вопрос "укажите соответствующий тип данных" решается на основе того, как переменная используется в псевдокоде: значение с десятичной точкой является REAL; что-то, установленное в TRUE или FALSE, является BOOLEAN; значение в одинарных кавычках является CHAR; значение, используемое как индекс массива или вместе с DIV и MOD, является INTEGER. Записывайте тип заглавными буквами, так, как он написан в руководстве.

Разобранный пример. Укажите соответствующий тип данных для каждой переменной.

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

Found является BOOLEAN (он хранит FALSE); Initial является CHAR (один символ в одинарных кавычках); Price является REAL (десятичное значение); Count является INTEGER (счетчик, увеличивающийся на единицу); Name является STRING (текст в двойных кавычках).

Присваивание и выражения

Используйте ← для присваивания:

Total ← Total + 1
Average ← Sum / Count

Выражения используют операторы:

  • арифметические + - * /, плюс DIV (целочисленное деление) и MOD (остаток): 7 DIV 2 = 3; 7 MOD 2 = 1.
  • сравнения =, <>, <, >, <=, >=.
  • логические AND, OR, NOT.

Приоритет (от высшего к низшему): NOT → * / DIV MOD → + - → сравнения → AND → OR. Используйте скобки, если не уверены.

Ввод и вывод

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

Встроенные функции и библиотеки

Многие задачи имеют готовые библиотечные подпрограммы, поэтому их не нужно писать. В вставке к Бумаге 2 перечислены те, которые можно использовать, с их точными именами, параметрами и типами возвращаемых значений; любая другая функция, необходимая задаче, дается в самой задаче. Имена ниже — это имена из вставки. VAL и STR — это имена IGCSE и не встречаются ни в одном документе 9618, поэтому они не дают баллов. UCASE и LCASE — другой случай: они являются частью 9618, определены в Руководстве по псевдокоду, но принимают один CHAR, а вставка их вообще не перечисляет — для целой строки в Бумаге 2 используется подпрограмма TO_UPPER.

Библиотека программ содержит подпрограммы, которые уже написаны, скомпилированы и протестированы; программа обращается к ним вместо того, чтобы писать собственные. Преимущества, которые принимает экзаменационная схема для вопроса о «трех преимуществах»: подпрограммы уже протестированы, поэтому менее склонны содержать ошибки; они экономят время разработки; они могут выполнять то, что не мог бы написать программист (сложная статистика, графика); они написаны экспертами и переиспользуются во многих программах; и подпрограмму с фиксированным интерфейсом можно вызвать из любого места программы.

Подпрограмма Возвращает Пример
LENGTH(s) количество символов в s LENGTH("Hello") = 5
LEFT(s, n) / RIGHT(s, n) первые / последние n символов RIGHT("Hello", 2) = "lo"
MID(s, start, n) n символов начиная с позиции start (позиции нумеруются с 1) MID("Hello", 2, 3) = "ell"
TO_UPPER(s) / TO_LOWER(s) s заглавными буквами / строчными буквами TO_UPPER("ab1") = "AB1"
NUM_TO_STR(x) / STR_TO_NUM(s) число как строка / строка как число STR_TO_NUM("3.5") = 3.5
IS_NUM(s) TRUE если s — допустимое число IS_NUM("12a") = FALSE
ASC(c) / CHR(n) кодовое значение символа c / символ с кодом n ASC('A') = 65, CHR(66) = 'B'
INT(x) целую часть от x INT(7.9) = 7
RAND(n) случайное вещественное число от 0 включительно до, но не включая, n INT(RAND(6)) + 1 — бросок игральной кости
DAY(d), MONTH(d), YEAR(d) части от DATE YEAR(TODAY())
DAYINDEX(d), SETDATE(d, m, y), TODAY() день недели (1 = воскресенье); дата, составленная из трех целых чисел; сегодняшняя дата
EOF(f) TRUE когда файл f больше не имеет строк для чтения WHILE NOT EOF("data.txt")

Строки объединяются с помощью & (конкатенация): результат "A" & "BC" равен "ABC". Используйте точные имена из вставки, сохраняя порядок параметров.

Даты и случайные числа часто используются в виде однострочных выражений. SETDATE(17, 11, 2007) создает дату 17 ноября 2007 года; 12 - MONTH(MyDOB) — количество месяцев от месяца рождения до конца года; IF DAYINDEX(MyDOB) = 5 THEN проверяет четверг, так как воскресенье — это день 1. RAND(n) возвращает вещественное число от 0 включительно до, но не включая, n, поэтому случайное целое число от Low до High включительно вычисляется как INT(RAND(High - Low + 1)) + Low: INT(RAND(21)) - 10 дает значение от -10 до 10.

Строка COMPUTER, показанная как восемь пронумерованных ячеек символов (позиции 1–8), с решенными результатами: LENGTH(s) = 8, LEFT(s, 3) = COM, MID(s, 4, 3) = PUT, RIGHT(s, 2) = ER, а также UCASE/LCASE для изменения регистра букв
Распространенные подпрограммы работы со строками, действующие на s = "COMPUTER" (позиции 1–8)

Разбор примера. Вычислите каждое выражение, зная, что Word ← "Program", Code ← 'Q' и N ← 7.

Выражение Значение Причина
LENGTH(Word) 7 семь символов
MID(Word, 4, 2) "gr" два символа, начиная с позиции 4
LEFT(Word, 3) & "!" "Pro!" объединено со строкой &
TO_UPPER(RIGHT(Word, 2)) "AM" внутренняя функция выполняется первой
ASC(Code) - ASC('A') 16 'Q' равно 81, а 'A' равно 65
N DIV 2 + N MOD 2 4 3 + 1
NUM_TO_STR(N) & "th" "7th" число сначала преобразуется в строку
INT(N / 2) 3 3.5 обрезано до своей целой части

Вычисляйте изнутри наружу и сохраняйте кавычки: "7" — это строка, а 7 — число.

Разбор примера. Каждое утверждение может содержать ошибку в использовании функции или оператора. Опишите ошибку или напишите NO ERROR. (Предполагается, что все переменные имеют правильный тип.)

Утверждение Ошибка
Result ← 2 & 4 & соединяет строки; 2 и 4 являются целыми числами, поэтому требуется +
SubString ← MID("pseudocode", 4, 1) NO ERROR: один символ с позиции 4, "u"
IF x = 3 OR 4 THEN OR требует логического значения с каждой стороны: IF x = 3 OR x = 4 THEN
Result ← Status AND INT(x / 2) AND требует двух логических значений; INT(x / 2) — целое число
Message ← "Done" + LENGTH(MyString) + не может прибавить строку к целому числу: "Done" & NUM_TO_STR(LENGTH(MyString))

Каждый оператор работает с определенными типами: & со строками, + - * / DIV MOD с числами, AND OR NOT с булевыми значениями, а = <> требует два значения одного и того же типа. Таблица «вычислите каждое выражение или напишите ERROR» отмечается аналогично: значения LENGTH(42) и "A" + 1 являются ERROR, поскольку тип не соответствует функции или оператору.

Разбор примера. Используя Points ← 100, Active ← TRUE и Exempt ← FALSE, вычислите каждое выражение.

Выражение Значение Причина
(Points > 99) OR Active TRUE обе стороны истинны; достаточно одной
(Points MOD 2 = 0) OR Exempt TRUE 100 MOD 2 равно 0
(Points <= 75) AND (Active OR Exempt) FALSE первая сторона ложна, а AND требует оба значения
(Active OR NOT Active) AND NOT Exempt TRUE Active OR NOT Active всегда истинно

Последнее выражение упрощается: X OR NOT X равно TRUE при любом значении X, поэтому все выражение сводится просто к NOT Exempt. Сначала вычислите скобки, затем NOT, потом AND, и наконец OR.

Исследовать

Переменная — это помеченная коробка

Каждое присваивание хранит одно значение в именованной коробке; повторное присвоение того же имени перезаписывает его. Пройдите по программе и следите за тем, как каждая коробка принимает свое текущее значение.

English Русский
pseudocode/ˈsuːdəʊkəʊd/ псевдокод
variables/ˈveərɪəblz/ переменных
data types/ˈdeɪtə taɪps/ типы данных
assignment/əˈsaɪnmənt/ присваиванием
constant/ˈkɒnstənt/ постоянно
identifier/aɪˈdentɪfaɪə/ идентификатор
function/ˈfʌŋkʃn/ функцией
library routines/ˈlaɪbrəri ruːˈtiːnz/ библиотечные процедуры
insert/ˈɪnsɜːt/ insert
parameters/pəˈræmɪtəz/ параметрами
program library/ˈprəʊɡræm ˈlaɪbrəri/ библиотека программ
concatenation/kənˌkætəˈneɪʃn/ конкатенацией
11.2

Выбор

Программа
Кандидаты должны уметь: Примечания и рекомендации
Использовать псевдокод для написания: • оператора ‘IF’ с блоком ‘ELSE’ и вложенными операторами IF • структуры ‘CASE’ • цикла с управляющим счетчиком: • цикла с постусловием • цикла с предусловием
Обосновать, почему одна структура цикла может быть более подходящей для решения задачи, чем другие

Источник: Программа Cambridge International

Выбор определяет, какие шаги будут выполнены.

IF age >= 18 THEN
    OUTPUT "Adult"
ELSE
    OUTPUT "Minor"
ENDIF
Блок-схема: от начала ромб принятия решений проверяет условие age >= 18; ветвь TRUE выводит Adult, ветвь FALSE выводит Minor, и обе ветви снова объединяются в конце
Конструкция IF...ELSE проверяет условие один раз, затем выполняет ровно одну из ветвей

Для более чем двух случаев можно использовать вложенный IF, но глубокое вложение трудно читать — конструкция CASE чище при проверке одного значения против нескольких вариантов:

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

Cambridge CASE позволяет использовать одиночные значения, списки значений (1, 2, 3:) и диапазоны (1 TO 5:).

Вложенный IF — это конструкция IF внутри ветки другого IF. Каждая IF требует собственной ENDIF, и экзаменатор проверяет, что каждая конструкция завершена:

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

Границы — это места, где теряются баллы. Условие «Оценка 50 или выше означает успех» является Mark >= 50, а не Mark > 50; последняя CASE ветка для «всего остального» записывается как OTHERWISE, а не условие вроде > 200. Неправильное сравнение здесь — это логическая ошибка: программа работает, но выдает неверный результат для некоторых входных данных — и таблица трассировки со граничным значением, таким как 50, помогает её найти.

Схема алгоритма оператора CASE OF Grade: значение проверяется по очереди с каждым стражем (одиночное значение, список значений, диапазон); первая подходящая ветка выполняет свое действие, иначе выполняется ветка OTHERWISE, и все ветки объединяются в ENDCASE
Оператор CASE выполняет ветку, соответствующую значению

Разобранное решение. Перепишите это с той же функциональностью, не используя структуру CASE.

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

Каждое значение становится веткой цепочки IF, а OTHERWISE становится последней ELSE:

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

Два присваивания одному и тому же значению объединяются в один блок с перечислением значений: 1, 2: ThisChar ← 'a'. Охранительные условия проверяются в порядке: при наличии диапазонов, таких как 1 TO 50:, за которым следует 40 TO 60:, значение 45 попадет в первое подходящее ветвление, поэтому присваивание в последующем блоке может быть никогда не выполнено — а если предыдущие блоки уже охватывают все возможные значения, то ветвление OTHERWISE также никогда не будет достигнуто.

В обратном направлении, вложенные IF, проверяющие несколько булевых переменных, становятся понятнее, если на каждый исход использовать одно условие: IF A AND B AND C THEN CALL Sub1(), затем IF A AND B AND NOT C THEN CALL Sub2() и так далее. Объединение проверок с помощью AND и OR устраняет вложенность, а IF A THEN принимается вместо IF A = TRUE THEN.

Исследовать

Выбор (IF / ELSE)

Измените ввод и посмотрите, какая ветвь выполнится — суть выбора.

English Русский
flowchart/ˈfləʊtʃɑːt/ блок-схема
structured English/ˈstrʌktʃəd ˈɪŋɡlɪʃ/ структурированный английский
11.2

Итерация

Итерация повторяет блок. Три вида циклов различаются количеством повторений тела.

Цикл с управляющим счетчиком (FOR)

Цикл с управляющим счетчиком — используйте его, когда заранее знаете, сколько раз нужно повторить:

FOR i ← 1 TO 10
    OUTPUT i
NEXT i

Конструкция STEP может изменять счетчик (например, FOR i ← 10 TO 1 STEP -1). Лучше всего подходит для фиксированного числа повторений или обработки каждого элемента массива.

Цикл с предварительным условием (WHILE)

Цикл с предварительным условием проверяет условие перед каждой итерацией, поэтому он может выполниться ноль раз:

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

Цикл с постусловием (REPEAT...UNTIL)

Цикл с постусловием проверяет условие после каждой итерации, поэтому он всегда выполняется как минимум один раз:

REPEAT
    INPUT password
UNTIL password = correctPassword

Выбор подходящего цикла

Три столбца схем алгоритмов. FOR: блок счетчика (i = 1 to N), затем блок тела, возврат к началу, для заданного числа итераций. WHILE: ромб проверки над блоком тела, условие проверяется до тела, цикл может выполниться ноль раз. REPEAT: блок тела над ромбом проверки, условие проверяется после тела, цикл выполняется как минимум один раз
Три цикла различаются моментом проверки условия — до тела (WHILE), после него (REPEAT) или заданное количество раз (FOR)
  • счетчик известен заранее → FOR.
  • возможно нулевое количество итераций → WHILE.
  • обязательно хотя бы одна итерация → REPEAT...UNTIL.

Обоснуйте выбор тем, известен ли счетчик и должно ли тело выполниться хотя бы один раз. Типичный вопрос предлагает сценарий («спросите пароль до тех пор, пока он не будет введен верно, но спрашивайте как минимум один раз») и спрашивает, какой цикл подходит.

Два балла начисляются за название цикла и причину, словами схемы оценивания: с управляющим счетчиком, потому что число итераций известно до начала цикла; с постусловием, потому что тело цикла должно выполниться хотя бы один раз; с предварительным условием, потому что цикл может вообще не потребоваться. Цикл по четырем элементам массива, который был записан как WHILE со счетчиком, «не является наиболее подходящим»: счетчик, равный четырем, известен, поэтому подходит цикл FOR.

Разобранное решение. Какой цикл подходит для каждой задачи? (a) распечатать таблицу умножения на 12; (b) продолжать читать числа, пока пользователь не введет 0; (c) запрашивать пароль до тех пор, пока он не будет введен верно. Выбирайте, задавая вопросы о количестве итераций и о том, когда происходит проверка. (a) Счетчик известен заранее (12), поэтому используйте цикл FOR. (b) Счетчик неизвестен, и первый ввод может уже быть 0 — значит, проверка должна стоять до тела: цикл WHILE, который выполняется ноль или больше раз. (c) Счетчик неизвестен, но вы должны спросить хотя бы один раз, прежде чем появится что-то для проверки — значит, проверка стоит после тела: цикл REPEAT...UNTIL, который выполняется один или больше раз. Решающий вопрос: должно ли тело выполниться хотя бы один раз? WHILE может выполниться ноль раз, REPEAT всегда выполняется один раз.

Прогон без выполнения (dry run) с таблицей трассировки

Таблица трассировки фиксирует значение каждой переменной во время прогона без выполнения (ручного прохождения алгоритма). Это способ протестировать цикл на бумаге, и задание на шесть баллов в большинстве Paper 2.

DECLARE Count, Total : INTEGER
Count ← 1
Total ← 0
WHILE Total < 10
    Total ← Total + Count * 2
    Count ← Count + 1
ENDWHILE
OUTPUT Count, Total
Count Total Total < 10 OUTPUT
1 0 TRUE
2 2 TRUE
3 6 TRUE
4 12 FALSE 4, 12

Правила, за которые ставятся баллы: один столбец на переменную, в порядке, указанном в задании; пишите значение только тогда, когда оно изменяется; начинайте новую строку каждый раз, когда цикл повторяется; вычисляйте условие с текущими значениями и останавливайтесь, как только оно станет FALSE; выводите результат в отдельном столбце точно так, как он выглядел бы. Трассируйте алгоритм именно так, как он написан, а не так, как вы думаете, что он должен был быть написан — если он никогда не останавливается, напишите об этом.

Разобранное решение. Какие конструкции использует каждая строка — selection (выбор), iteration (итерация) или вызов подпрограммы?

Pseudocode Selection Iteration Subroutine
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 и CASE — это выбор; FOR, WHILE и REPEAT — это итерация; имя, за которым следуют скобки — Start(), IsFull(), — это вызов процедуры или функции, где бы он ни появлялся, включая условия.

Исследовать

Отследите цикл, проход за проходом

Таблица трассировки фиксирует каждую переменную после каждого прохода цикла. Следите за тем, как счетчик i растет, пока накапливается текущая сумма — именно это требуется заполнить в вопросе по трассировке на экзамене.

Исследовать

Отслеживание цикла

Шагайте по циклу и наблюдайте, как меняются переменные при каждом проходе — именно это фиксирует таблица отслеживания.

English Русский
selection/sɪˈlekʃn/ выбор
nested/ˈnestɪd/ вложенный
logic error/ˈlɒdʒɪk ˈerə/ логическая ошибка
trace table/treɪs ˈteɪbl/ трассировочная таблица
iteration/ˌɪtəˈreɪʃn/ итерации
count-controlled loop/kaʊnt kənˈtrəʊld luːp/ цикл с числовым управлением
pre-condition loop/priː kənˈdɪʃn luːp/ цикл с предварительным условием
post-condition loop/pəʊst kənˈdɪʃn luːp/ цикл с последующим условием
dry run/draɪ rʌn/ сухой прогон
11.3

Процедуры и функции

Программа
Кандидаты должны уметь: Примечания и рекомендации
Определить и использовать процедуру
Объяснить, где при построении алгоритма уместно использовать процедуру
Использовать параметры Процедура может иметь ноль, один или несколько параметров. Параметр может передаваться по ссылке или по значению
Определить и использовать функцию
Объясните, где в процессе построения алгоритма уместно использовать функцию Функция используется в выражении, например, возвращаемое значение заменяет вызов функции
Использовать терминологию, связанную с процедурами и функциями включая заголовок процедуры/функции, интерфейс процедуры/функции, параметр, аргумент, возвращаемое значение
Писать эффективный псевдокод

Источник: Программа Cambridge International

Структурное программирование строит программу из небольших именованных подпрограмм, каждая из которых выполняет одну задачу.

Процедура

Процедура — это именованный блок, который выполняет действие; она может принимать параметры, но не возвращает значение.

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

CALL Greet("Ada")

Функция

Функция похожа на процедуру, но она возвращает значение, которое становится частью выражения.

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

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

Используйте процедуру, когда подпрограмма выполняет действие; используйте функцию, когда она вычисляет значение для вызывающего кода.

Спецификация экзамена спрашивает, где в построении алгоритма уместно применение каждой из них. Процедура уместна там, где одна и та же группа шагов требуется в нескольких местах (валидация ввода, вывод меню, обмен двумя значениями): шаги записываются один раз и CALLаются по имени. Функция уместна там, где необходимо вычислить одно значение, а затем использовать его в выражении — сумму, результат деления/умножения на TRUE/FALSE, наибольшее из двух чисел, — поскольку возвращаемое значение заменяет вызов: IF IsValid(Code) THEN.

Две панели. Процедура: вызов Greet(Ada) выполняет действие и выводит Hello, Ada, не возвращая значения. Функция: присваивание y = Square(5) вычисляет 5 умножить на 5 = 25, возвращает 25, поэтому y теперь содержит 25
Процедура выполняет действие и ничего не возвращает; функция возвращает значение, которое используется в выражении

Параметры

Параметр — это переменная, которую подпрограмма объявляет для получения входных данных; значения, которые предоставляет вызывающий код, называются аргументами. Два способа передачи:

  • передача по значению — подпрограмма получает копию; изменения внутри нее не влияют на вызывающий код. Используйте для входных данных, которые только читаются.
  • передача по ссылке — подпрограмма получает ссылку на переменную вызывающего кода; изменения влияют на вызывающий код. Используйте, когда необходимо обновить параметр.
Диаграммы ячеек памяти. Передача по значению: переменная x = 5 вызывающего кода копируется в отдельную ячейку параметра a = 5, поэтому изменение a оставляет x равным 5. Передача по ссылке: параметр a — это стрелка, указывающая на собственную ячейку x вызывающего кода, поэтому изменение a также меняет x
Передача по значению копирует значение в новую ячейку; передача по ссылке позволяет подпрограмме изменить переменную вызывающего кода
PROCEDURE Swap(BYREF a : INTEGER, BYREF b : INTEGER)
    DECLARE temp : INTEGER
    temp ← a
    a ← b
    b ← temp
ENDPROCEDURE

В псевдокоде Кембриджа тип параметра указывается в заголовке, BYVAL или BYREF, перед каждым параметром. Если ни один из них не указан, по умолчанию предполагается BYVAL. Следовательно,dirname, который должен изменить переменную вызывающей программы — например, Swap, или процедура, обновляющая накопленную сумму, — требует указания BYREF в своем заголовке.

Разобранный пример. Что будет выведено?

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 является ссылкой на A, поэтому A становится равно 8. Y представляет собой копию B, поэтому удвоение Y оставляет B равным 3. Выводом будет 8, 3. Если бы в заголовке было указано BYVAL X, значение A всё равно осталось бы равным 5.

Локальные и глобальные переменные

Локальная переменная объявляется внутри подпрограммы и существует только во время ее выполнения. Глобальная переменная объявляется вне подпрограммы и доступна повсюду. Предпочтайте локальные переменные и параметры — активное использование глобальных переменных затрудняет понимание и тестирование кода. (Область видимости имени называется его областью действия.)

Однострочное отличие: глобальную переменную можно использовать из любой части программы, локальную — только внутри подпрограммы, где она объявлена. Преимущества локальных переменных, принимаемые схемой экзамена: тот же идентификатор можно использовать в другой подпрограмме без коллизий; значение нельзя случайно изменить другими частями программы; память освобождается при завершении подпрограммы; и подпрограмма является самодостаточной, поэтому ее можно протестировать отдельно и использовать в другой программе.

Локальная переменная создается каждый раз при вызове подпрограммы и уничтожается при ее завершении, поэтому она не может сохранять значение от одного вызова к другому. Поэтому процедуре, накапливающей строку при повторных вызовах, необходимо, чтобы эта строка была глобальной (или передавалась BYREF). Если MyString меняется с глобальной на локальную, объявленную внутри MyOutput(), каждый вызов начинается с новой пустой MyString, текст, добавленный предыдущими вызовами, теряется, и процедура «работает не так, как ожидается».

Три вызова одной и той же процедуры на временной шкале; каждый вызов создает свою собственную локальную ячейку MyString, новую и пустую, которая исчезает после завершения вызова, тогда как одна глобальная ячейка MyString над ними сохраняет свое значение между вызовами
Локальная переменная — это новая, пустая ячейка при каждом вызове; только глобальная переменная (или параметр BYREF) сохраняет значение между вызовами
Большая внешняя рамка с меткой глобальная область действия содержит глобальную переменную Total, доступную повсюду, и меньшую внутреннюю рамку с меткой PROCEDURE Calc, локальная область действия, содержащую локальную переменную temp, которая существует только во время выполнения Calc
Глобальная переменная видна повсюду; локальная переменная существует только внутри своей собственной процедуры

Когда использовать подпрограмму

Используйте подпрограмму, когда:

  • одна и та же логика встречается в нескольких местах — запишите ее один раз, вызывайте много раз.
  • блок имеет ясную именованную цель — имя документирует, что он делает.
  • программа сложна — разбейте ее на части (декомпозиция).
  • вы хотите протестировать фрагмент изолированно.

Не делайте их настолько мелкими, чтобы стоимость вызова превышала работу внутри.

Терминология

  • определение — блок ⟨PROCEDURE ... ENDPROCEDURE⟩ (или функции).
  • вызов — место, где он invoked. аргумент — значение, передаваемое внутрь. параметр — переменная, которая его принимает.
  • возвращаемое значение — то, что функция возвращает обратно.
  • заголовок процедуры/функции — первая строка, дающая имя и параметры (PROCEDURE Name(params) или FUNCTION Name(params) RETURNS type).
  • интерфейс/подпись процедуры/функции — имя + параметры + тип возвращаемого значения: то, что должен знать вызывающий код для использования её.

Разобранное решение. Опишите каждый термин, используемый в заголовке FUNCTION Pass2(Count : INTEGER) RETURNS BOOLEAN.

Термин Значение
FUNCTION подпрограмма, возвращающая значение
Pass2 идентификатор, используемый для её вызова
Count параметр: идентификатор, принимающий переданный аргумент
INTEGER тип данных параметра
RETURNS BOOLEAN тип данных значения, которое возвращает функция

Два идентификатора в PROCEDURE MyProc(Count : INTEGER, Message : STRING) являются параметрами: они принимают значения, передаваемые при вызове процедуры, и используются внутри неё как локальные переменные.

Чтобы преобразовать процедуру в функцию: замените PROCEDURE на FUNCTION и добавьте RETURNS <type>; замените OUTPUT (или параметр BYREF, передающий результат наружу) на оператор присваивания RETURN; и измените каждый вызов, чтобы возвращаемое значение использовалось, например, Result ← Unpack(Text) вместо CALL Unpack(Text, Result). Для вопроса «напишите заголовок» запишите всю строку целиком: FUNCTION Calculate(Expression : STRING) RETURNS INTEGER. Параметр массива передается по ссылке, поэтому процедура, записывающая данные в массив, изменяет массив вызывающей программы.

Когда программа получает новый модуль, интерфейс — это первое, о чем договариваются: имя, параметры (сколько, в каком порядке, какого типа) и тип возвращаемого значения, а также любые глобальные данные, которые модуль читает или записывает. Модулю, отправляющему напоминание до дедлайна, нужен запись (или его индекс) в качестве параметра и он ничего не возвращает, поэтому это процедура; основная программа вызывает её один раз для каждой записи.

Написание модуля для Билета 2

Половина Билета 2 — это «напишите псевдокод для модуля X». Экзаменационная схема начисляет балл за каждую деталь, поэтому даже незавершенный модуль получит баллы за каждую правильную часть. Части, на которые смотрит экзаменатор:

Аннотированная псевдокод-функция CountAbove с выноской на каждую часть, приносящую балл: заголовок с параметром и типом возвращаемого значения, локальные объявления, инициализация счетчика до цикла, цикл FOR по каждому элементу, условие IF с правильной границей, обновление внутри IF, закрытые конструкции и RETURN после цикла
За каждую часть ответа на модуль начисляется свой балл, поэтому пишите все части, даже если в одной из них уверены не полностью
  1. Заголовок, как описано в задании: PROCEDURE Name(Param : TYPE) или FUNCTION Name(Param : TYPE) RETURNS TYPE, с указанием BYREF там, гдеdirname должна изменить аргумент.
  2. Локальные объявления: для каждой локальной переменной укажите её тип DECLARE, а также инициализируйте счетчики и суммы (Count ← 0).
  3. Цикл, проходящий по каждому элементу: для массива, размер которого известен, используйте FOR Index ← 1 TO 50; для файла — WHILE NOT EOF(...).
  4. Условие, содержащее правильную операцию сравнения и границу, примененное к нужному элементу: IF Score[Index] > Limit THEN.
  5. Обновление внутри ветки: увеличение счетчика, сохранение значения или вывод сообщения.
  6. Завершение: запись RETURN один раз после цикла, в функции; операторы ENDFUNCTION или ENDPROCEDURE; а также закрытие каждого IF, FOR и WHILE.

Разобранное решение. Глобальный массив Score : ARRAY[1:50] OF INTEGER хранит оценки. Напишите функцию CountAbove(Limit : INTEGER), которая возвращает количество оценок, больших 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

Баллы: заголовок с его параметром и RETURNS INTEGER; объявление переменной Count и присвоение ей значения 0; цикл по всем элементам 50; сравнение > Limit (не >=); обновление счетчика внутри блока IF; вывод результата RETURN Count после цикла. Основная программа использует возвращаемое значение в выражении или выводе: например, OUTPUT "Above 70: ", CountAbove(70).

Разобранное решение. Напишите функцию IsValid(Code : STRING), которая возвращает TRUE, когда Code представляет собой две заглавные буквы, за которыми следуют четыре цифры — формат AB1234 — и FALSE в противном случае.

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

Проверка длины выполняется первой, поэтому запрос позиции MID никогда не будет сделан для несуществующего индекса. Валидация такого рода возвращает булево значение BOOLEAN, чтобы вызывающая программа могла вывести сообщение IF IsValid(Entry) THEN ... ELSE OUTPUT "Invalid code" ENDIF: сообщение пользователю выводит вызывающая программа, а не функция — функция вычисляет, процедура выполняет действия.

Разобранное решение. Напишите функцию IsPalindrome(Word : STRING), которая возвращает TRUE, когда Word читается одинаково в прямом и обратном направлении, например, "RACECAR".

Сравнивайте символы с двух концов, двигаясь внутрь: позиция Index сопоставляется с позицией Len - Index + 1, и достаточно проверять только первую половину.

Слово RACECAR в семи пронумерованных блоках; дуги соединяют позицию 1 с 7, 2 с 6 и 3 с 5, подписаны как позиция i и позиция Len минус i плюс 1; средний символ не имеет пары
При проверке палиндрома позиция i сопоставляется с позицией Len - i + 1, проверка прекращается в середине
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

Те же три инструмента — цикл FOR по позициям, чтение одного символа через MID(s, i, 1) и сборка новой строки через & — решают большинство модулей со строками в Бумаге 2: подсчет частоты встречаемости символа (IF MID(s, i, 1) = Ch THEN Count ← Count + 1), замена каждого вхождения символа (добавление либо NewChar, либо оригинального символа к NewString на каждой позиции), скрытие всех цифр номера карты, кроме последних четырех (добавление '*' для каждой позиции до ⟨⟩ Len - 4) или создание собственной функции MID() путем объединения символов из диапазона ⟨⟩ Start до ⟨⟩ Start + Length - 1. Запрос позиции за пределами строки с помощью MID вызывает ошибку времени выполнения, поэтому сначала проверяйте ⟨⟩ LENGTH.

Файлы. Значения в переменных исчезают при завершении программы, поэтому модуль, который должен сохранять данные для следующего запуска, записывает их в файл: открытие файла OPENFILE "scores.txt" FOR WRITE, одна запись ⟨⟩ WRITEFILE "scores.txt", NUM_TO_STR(Score[Index]) за строку внутри цикла и закрытие файла CLOSEFILE "scores.txt" один раз после цикла; чтение обратно использует FOR READ, READFILE и WHILE NOT EOF("scores.txt"). Тема 10 содержит полный раздел о файлах; здесь баллы начисляются за правильное открытие режима, чтение или запись внутри цикла и закрытие один раз после него.

Исследовать

Стек вызовов: push при вызове, pop при возврате

Вызов подпрограммы помещает новый кадр на вершину стека; возврат из неё удаляет этот кадр и возвращает значение вызывающему коду. Вызываемая функция всегда соответствует кадру на вершине стека.

English Русский
array/əˈreɪ/ массив (array)
operators/ˈɒpəreɪtəz/ операторы
precedence/ˈpresɪdəns/ приоритет
procedure/prəˈsiːdʒə/ процедура
structured programming/ˈstrʌktʃəd ˈprəʊɡræmɪŋ/ структурное программирование
subroutines/ˈsʌbruːtiːnz/ подпрограммы
return value/rɪˈtɜːn ˈvæljuː/ возвращаемого значения
arguments/ˈɑːɡjuːmənts/ аргументы
pass by value/pæs baɪ ˈvæljuː/ передача по значению
pass by reference/pæs baɪ ˈrefrəns/ передача по ссылке
global variable/ˈɡləʊbl ˈveərɪəbl/ глобальная переменная
local variable/ˈləʊkl ˈveərɪəbl/ локальная переменная
scope/skəʊp/ область применения
decomposition/ˌdiːkɒmpəˈzɪʃn/ разложение
signature/ˈsɪɡnɪtʃə/ подпись
format/ˈfɔːmæt/ формат
Validation/ˌvælɪˈdeɪʃn/ Валидация
run-time error/rʌn taɪm ˈerə/ ошибка во время выполнения
invariant/ɪnˈveərɪənt/ инвариантный
linear search/ˈlɪnɪə sɜːtʃ/ линейный поиск
syntax error/ˈsɪntæks ˈerə/ синтаксическая ошибка
11.3

Написание эффективного псевдокода

Три характеристики, которые делают псевдокод более понятным — ответ на вопрос «назовите три характеристики» — это осмысленные имена (Total, а не t), отступы операторов внутри каждого блока и комментарии (// ...), объясняющие назначение; также принимаются ключевые слова заглавными буквами, один оператор на строку и пустые строки между секциями. Эффективный псевдокод делает следующее:

  • вынести инварианты из циклов — если значение (инвариант) не изменяется при изменении счетчика цикла, вычислите его один раз перед циклом.
  • рано выйти из цикла, когда ответ найден (прекратить линейный поиск сразу после появления целевого элемента).
  • избегать избыточных вычислений — сохранить результат и использовать его повторно вместо повторного вычисления.
  • выбрать правильную структуру данных — массив предпочтительнее множества отдельных переменных, когда элементы относятся к одному набору.
  • заменить глубокие вложенные IF на CASE при проверке одного значения на соответствие множеству условий.
  • комментировать намерение, а не механику (// validate the postcode, а не // loop 6 times).
  • использовать осмысленные имена (numberOfPupils, а не n) и инициализировать переменные до их использования.
Переместите работу, которая никогда не меняется, за пределы цикла, чтобы она выполнялась один раз, а не на каждой итерации
Переместите неизменяемую работу за пределы цикла, чтобы она выполнялась один раз
11.3

Тестирование и ошибки

Три вида ошибок, каждый из которых обнаруживается особым образом:

Ошибка Суть Пример Как обнаруживается
синтаксическая ошибка нарушение правил языка пропущена запятая ENDIF; неправильная синтаксическая конструкция OUTPT "Hi" компилятор/переводчик, до запуска программы
ошибка времени выполнения программа работает, но оператор не может быть выполнен деление на ноль; индекс массива 0 или 51; вызов функции с некорректным параметром; цикл, который никогда не заканчивается, из-за чего программа «зависает» во время выполнения: программа останавливается или зависает
логическая ошибка программа выполняется до конца, но вывод неверен > там, где требовалось бы ⟨⟩ >=; сумма никогда не устанавливалась в ⟨⟩ 0 тестирование с использованием таблицы проследования и выбранных тестовых данных

IDE помогает найти последние два вида: точка останова останавливает программу на выбранной строке; пошаговое выполнение выполняет операторы по одному; а окно отчета (или наблюдения) показывает значение каждой переменной в этот момент, позволяя увидеть строку, где значение становится неверным. Методы тестирования и тестовые данные рассматриваются в теме 12.

English Русский
IDE/ˌaɪ diː ˈiː/ Среда разработки (IDE)
breakpoint/ˈbreɪkpɔɪnt/ точка останова
single stepping/ˈsɪŋɡl ˈstepɪŋ/ построчное выполнение
11.3

Определения, принимаемые экзаменатором

Вопросы с определениями оцениваются по фиксированной формулировке. Выучите их точно.

Термин Определение
процедура подпрограмма, выполняющая задачу (последовательность шагов) и не возвращающая значение; вызывается с помощью CALL
функция подпрограмма, возвращающая одно значение в точку вызова, поэтому её можно использовать в выражении
параметр идентификатор в заголовке подпрограммы, получающий значение или ссылку при вызове подпрограммы
аргумент значение (или переменная), передаваемое при вызове, соответствующее параметру
передача по значению копии значения аргумента передаются подпрограмме, поэтому изменения внутри неё не влияют на исходную переменную
передача по ссылке адрес переменной передается подпрограмме, поэтому изменения внутри неё изменяют исходную переменную
заголовок первая строка определения подпрограммы: её имя, параметры и, для функции, тип возвращаемого значения
интерфейс то, что должна знать вызывающая программа для использования подпрограммы: её имя, параметры (количество, порядок, тип) и тип возвращаемого значения
возвращаемое значение значение, которое функция возвращает обратно в выражение, которое её вызвало
локальная переменная объявленная внутри подпрограммы; существует только во время работы подпрограммы и может использоваться только внутри неё
глобальная переменная объявленная вне всех подпрограмм; может использоваться в любом месте программы
цикл с управляемым количеством итераций повторяется фиксированное число раз, управляется счетчиком (FOR ... NEXT)
цикл с предварительной проверкой условия проверяет условие перед каждой итерацией, поэтому тело может не выполниться ни разу (WHILE ... ENDWHILE)
цикл с последующей проверкой условия проверяет условие после каждой итерации, поэтому тело выполняется как минимум один раз (REPEAT ... UNTIL)
константа именованное значение, которое не может измениться во время выполнения программы
подпрограмма автономный блок кода, выполняющий задачу и вызываемый по имени: процедура или функция
библиотека процедур подпрограмма, уже написанная и протестированная, доступная для вызова из программы
11.3

Советы для экзамена

  • Различайте процедуру (без возвращаемого значения) и функцию (возвращающую значение); знайте передачу по значению против передачи по ссылке.
  • Выберите правильный цикл: управляемый количеством (FOR), когда количество повторений известно, управляемый условием (WHILE/REPEAT) в противном случае.
  • Различайте локальные и глобальные переменные и область видимости; предпочитайте локальные переменные в перенастраиваемых модулях.
  • Используйте точные названия процедур из вставки и порядок параметров. VAL и STR — названия IGCSE и не дают баллов; UCASE и LCASE — реальные процедуры 9618 из Pseudocode Guide, но они работают с одним символом, поэтому на Paper 2 для всей строки требуется TO_UPPER или TO_LOWER.
  • В ответе «напишите псевдокод» заголовок, объявления, цикл, условие, обновление и RETURN получают балл каждый: напишите все шесть частей, даже если одна вызывает сомнения.

Распространенные ошибки

  • Вызов функции без использования возвращаемого значения. Присвойте результат или используйте его в выражении или выводе: Sorted ← BubbleSort(MyArray, 7).
  • Передача длины равной единице: 6 для массива из семи элементов, или последний индекс, где требовалась длина. Решите, является ли параметр длиной или индексом, и убедитесь, что последний элемент посещен.
  • Закрытие файла внутри цикла, который его читает. Откройте один раз, закройте один раз, после цикла.
  • Использование входных данных напрямую как имени файла. Добавьте расширение, указанное в задании: FileName ← Choice & ".txt".
  • Оставленные открытыми конструкции. У каждой IF должна быть своя ENDIF, у каждого FOR — свой NEXT, у каждого WHILE — свой ENDWHILE, и у каждой функции — свой RETURN; схема оценивания предусматривает балл за это.
  • Неправильные границы: использование > для выражения «по крайней мере» (что соответствует ⟨⟩ >=) или использование индекса FOR, начинающегося с ⟨⟩ 0, для массива, объявленного размером ⟨⟩ [1:50].
  • Счетчик или сумма, которые никогда не устанавливаются в 0 перед циклом.
  • В таблице трассировки переписывание каждой переменной на каждой строке или изменение значения до выполнения оператора, который его изменяет.
  • Половина условия: использование IF x = 3 OR 4 — каждая сторона оператора OR и AND должна быть полным сравнением. И оператор + не соединяет строки; это делает оператор &.
  • Объявление как локального значения, которое должно сохраняться между вызовами. Накопительная сумма или строка, собираемая несколькими вызовами, являются глобальными или BYREF.

Интерактивные уроки по этой теме

Пройдите его шаг за шагом с упражнениями мгновенной проверки.

Архив экзаменационных работ

Больше тем в A-Level Информатика

Войти или создать аккаунт

IGCSE, A-Level & AP