awesome-everything EN
↑ Обратно к восхождению

Базовый CS с нуля

Трассировка программы

Суть Пройди шаг за шагом TypeScript-программу, объединяющую условие и цикл. Следи за счётчиком команд и состоянием переменных на каждой итерации, чтобы увидеть точно, как if и while работают вместе на уровне инструкций.
◷ 25 min

Ты теперь знаешь, что if — это условный переход, а while — обратный переход. Но читать о них по отдельности — совсем не то же самое, что наблюдать, как они работают вместе в реальной программе, шаг за шагом, с меняющимся прямо перед тобой состоянием переменных.

Именно это и делает этот урок. Ты прочитаешь короткую TypeScript-функцию, которая обходит небольшой массив и суммирует только положительные числа. Затем проследишь её кадр за кадром — следя за счётчиком команд и значением каждой переменной на каждой строке — пока функция не вернёт результат.

После этой трассировки ты будешь знать не только то, что код говорит; ты будешь знать, что CPU делает, по одной инструкции за раз.

Цель

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

Идея

Программа для трассировки — функция суммирования положительных чисел по фиксированному массиву. В ней три момента управления потоком:

  1. Тест while — вычислить i < nums.length в начале каждой итерации. Счётчик команд либо проваливается в тело цикла (условие истинно), либо прыгает вперёд за цикл (условие ложно, выход).
  2. Тест if — вычислить nums[i] > 0 внутри тела. Счётчик команд либо выполняет sum += nums[i] (условие истинно, fall-through), либо пропускает его (условие ложно, прыжок вперёд).
  3. Инкремент и обратный переходi++ выполняется на каждой итерации (положительное или нет), затем безусловный обратный переход возвращается к тесту while.

Массив: [3, -1, 4]. Начальное состояние: sum = 0, i = 0. Ожидаемый результат: 3 + 4 = 7 (значение -1 пропускается внутренним if).

Каждый кадр в трассировке показывает:

  • Строку кода, которая вот-вот выполнится.
  • Текущие значения i, sum и nums[i].

Настоятельно рекомендуется сначала самостоятельно пройти трассировку вручную, а потом смотреть кадры — это закрепляет ментальную модель движения счётчика команд по коду.

Код
1 function sumPositives(nums: number[]): number {
2 let sum = 0; // аккумулятор начинается с нуля
3 let i = 0; // счётчик цикла начинается с нуля
4
5 while (i < nums.length) { // цикл с обратным переходом
6 if (nums[i] > 0) { // условие: пропустить отрицательные
7 sum += nums[i];
8 }
9 i++; // всегда инкремент, положительное или нет
10 }
11
12 return sum;
13 }
  • L2 sum: аккумулятор — собирает текущую сумму
  • L3 i: индекс в nums — продвигается на каждой итерации
  • L5 тест while: CMP i, nums.length → условный переход выходит при i >= length
  • L6 тест if: CMP nums[i], 0 → условный переход пропускает sum+= когда nums[i] <= 0
  • L7 sum += nums[i]: добавляет текущий элемент только когда условие if истинно
  • L9 i++: безусловный; выполняется даже когда if был пропущен
  • L10 закрывающая скобка: безусловный обратный переход к тесту while на строке 5
sumPositives: цикл while с внутренним условием. Вход: [3, -1, 4]. Ожидаемый результат: 7.
Пошаговый разбор

Пройди sumPositives([3, -1, 4]) кадр за кадром. Каждая ячейка показывает текущее значение одной переменной. Активная строка подсвечена в панели кода выше.

1 function sumPositives(nums: number[]): number {
2 let sum = 0;
3 let i = 0;
4
5 while (i < nums.length) {
6 if (nums[i] > 0) {
7 sum += nums[i];
8 }
9 i++;
10 }
11
12 return sum;
13 }

Граничные случаи

Что если массив пустой? Если nums = [], то nums.length = 0, и тест while при самой первой проверке вычисляет i=0 < 0 → false. Тело цикла не выполняется ни разу. Функция сразу возвращает sum = 0. Это корректный результат для пустых входных данных и является естественным следствием проверки условия перед телом — тот же аппаратный механизм, который делает тест while в начале.

Практика 0 / 5

После первой итерации sumPositives([3,-1,4]) переменная i была проинкрементирована с 0. Какое значение имеет i в начале второго теста while?

Во время итерации 2 (nums[1] = -1) условие if nums[1] > 0 ложно. Какое значение имеет sum после выполнения i++ в конце этой итерации?

Сколько раз выполняется строка 'sum += nums[i]' при вызове с [3,-1,4]?

При каком значении i цикл while выходит (т. е. когда условие while становится ложным)?

sumPositives([2, -5, -3, 6]) возвращает какое значение?

Проверь себя
Викторина

В sumPositives: что происходит когда nums[i] отрицательный или нулевой?

Итог

Трассировка программы шаг за шагом раскрывает конкретный механизм за высокоуровневым синтаксисом. В sumPositives цикл while — это структура с тестом в начале и обратным переходом: на каждой итерации условие i < nums.length вычисляется (сравнение обновляет флаг Z или N), условный переход либо выходит из цикла, либо проваливается в тело, а безусловный обратный переход в конце сбрасывает счётчик команд обратно к тесту. Внутренний if — это второй CMP + условный переход: когда nums[i] > 0 ложно, тело sum += nums[i] пропускается условным прямым переходом; когда истинно — fall-through. Инкремент i++ безусловен — он стоит за пределами блока if и выполняется в любом случае. Цикл выходит, когда i достигает nums.length: в этот момент условие while ложно, условный переход в начале срабатывает (прямой переход за цикл), и счётчик команд перемещается к return sum. Итоговое значение sum — сумма всех положительных элементов, встреченных в ходе итерации.

Продолжить восхождение ↑Control flow: тест с множественным выбором
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.