День 20 · Контрольная точка 4: срезы, map, строки и файлы · страница 2 из 3

Правила трассировки: 1–32

Все правила таблиц трассировки за курс — одним списком, как их вводили дни. Номера сквозные: на них ссылаются подсказки и сообщения проверки. Читать подряд не нужно — держите страницу открытой рядом с table.txt. Новых правил контрольная не вводит: таблица в kt6 сверяется по этому списку.


Формат таблицы

Образец · набирать не нужно
# шаг | строка | boxes | len(boxes) | cap(boxes) | first | len(first) | cap(first)
1 | 8 | [] | 0 | 4 | - | - | -
2 | 9 | ? | ? | ? | ? | ? | ?

Строки и значения — день 02

  1. Одна строка таблицы — одна выполненная строка кода внутри main, включая строки с печатью. С дня 11 — строка на каждую выполненную строку кода и внутри вызванных функций (правила 16–18).
  2. Значения записываются после выполнения шага.
  3. Переменной ещё нет — прочерк -. Это не ноль.
  4. То, что шаг не трогал, переписывается из строки выше: пустых клеток не бывает.
  5. Правая часть считается по предыдущей строке таблицы.
  6. Номера строк — по исходному файлу программы, без ваших вставок с отладочной печатью.

Ветвления — день 06

  1. Строка с if или } else if — шаг; значения в ней те же, что строкой выше: условие только читает.
  2. Строки } else { и одинокая } — не шаги.
  3. Строки невыполненных веток в таблицу не попадают: номера идут с пропусками.
  4. После первой сработавшей ветки остальная цепочка — не шаги.

Циклы — день 08

  1. Строка for — шаг каждый раз, когда программа к ней приходит. В первый раз выполняются начальное значение и проверка, в следующие — третья часть (i++) и проверка; в таблицу идут значения после всего этого.
  2. Последний шаг со строкой for — тот, где условие ложно; он есть всегда, и переменная цикла на нём уже «за границей».
  3. После цикла переменной цикла нет — прочерк.
  4. Строки break и continue — шаги. Значения в них переписываются из строки выше. После continue следующий шаг — строка for, после break — первая строка после цикла.
  5. Шаги нумеруются подряд, номера строк повторяются. Самопроверка: строка for встречается на один раз больше, чем выполнилось тело.

Вызов функции — день 11

  1. Колонка «где мы» — имя функции, чью строку сейчас выполняем: main, boxes.
  2. Строка с вызовом — шаг, и она встречается в таблице дважды: уход в функцию (результата ещё нет) и возврат (присваивание доделано).
  3. Первый шаг внутри функции — строка её заголовка: на нём параметры получают копии аргументов. Самое забываемое правило.
  4. Строка return — шаг; значения на нём те же, что строкой выше.
  5. Переменные другой функции — прочерк; переменные main, пока мы внутри функции, показываются как есть и не меняются.

Одноимённые переменные и сокращённый вызов — день 12

  1. Одноимённые переменные — разные колонки: trips и trips в if. До объявления внутренней и после закрывающей } её блока — прочерк.
  2. Строка с вызовом функции — один шаг, если шаги внутри функции не расписываются: в таблицу идут значения вызвавшего, уже с присвоенным результатом.

Несколько функций — день 13

  1. Одноимённые переменные разных функций — разные колонки, и в заголовке написано, чья: total (main), total (loadPlan).
  2. Вложенный вызов раскрывают отдельной таблицей, а в первую подставляют её результат.

Самопроверки для функций: строк с именем функции столько, сколько строк её тела выполнилось, плюс одна на заголовок; строка вызова встречается парами — уход и возврат (правило 17), кроме случая правила 22.


Срез в клетке и цикл range — день 16

  1. Срез в клетке таблицы пишется так, как его печатает fmt.Println: элементы через пробел в квадратных скобках — [12 40 5]. Пустой срез — [], а не прочерк: срез уже есть, элементов в нём нет. Изменился один элемент или добавился новый — в клетку идёт весь срез целиком, уже с изменением.
  2. Строка for i, v := range s — шаг в начале каждого прохода: на нём i уже получила индекс, а v — копию элемента. После последнего прохода программа ещё раз приходит на эту строку и узнаёт, что элементов больше нет, — это тоже шаг, и на нём i и v уже прочерк.

Правила 11–13 дня 08 для range: у него нет значения «за границей», поэтому на последнем шаге сразу прочерк.

len, cap и общий массив — день 17

  1. У каждого среза в таблице три колонки: сам срез, len и cap. В клетку среза по правилу 25 идут элементы с нулевого по len - 1; ячейки за длиной не пишутся. У подсреза s[a:b] длина b - a, ёмкость cap(s) - a.
  2. Срезы, взятые один из другого, делят массив. Запись через любой из них на том же шаге меняет все срезы, чьё окно видит эту ячейку; len и cap от записи не меняются.
  3. append при len меньше cap пишет в тот же массив, при len, равном cap, — в новый. В первом случае элемент на том же шаге появляется во всех срезах, чьё окно видит ячейку, а cap прежний. Во втором срез с этого шага ни с кем ячеек не делит, а новый cap не вычисляют: он вписан в заготовку или взят из вывода.

Самопроверка: если клетка среза изменилась на шаге, где его имени в строке кода нет, в строке должен стоять его сосед по массиву — правило 28 или 29.

Колонка map — день 18

  1. Колонка map записывается так, как её печатает fmt.Println: map[ключ:значение ключ:значение] — пары через пробел, ключ и значение через двоеточие, ключи по возрастанию, строки без кавычек. Пустая map — map[]; map, которая ещё не объявлена, — прочерк -. Порядок в клетке — порядок ключей, а не порядок записи.
  2. Новый ключ появляется в колонке только при записи: m[k] = …, m[k]++, m[k] += … — даже если прибавили ноль. Чтение x := m[k] и x, ok := m[k] колонку map не меняет, даже когда ключа нет. delete(m, k) убирает пару; delete ключа, которого нет, ничего не меняет.
  3. Map, переданная в функцию, — та же самая map: запись внутри функции меняет колонку map вызывающего. Если вызов — один шаг (правило 22), изменение видно уже в строке вызова. Если шаги функции расписаны, колонка вызывающего меняется в той строке функции, где сделана запись. Это исключение из правила 20: у переменных int и string вызывающего так не бывает.

Обход for k, v := range m по самой map по шагам не расписывают: порядок меняется от запуска к запуску. Обход slices.Sorted(maps.Keys(m)) — обычный обход среза, для него действуют правила дня 16.

День 19 новых правил не вводил: список заканчивается на 32.


Как свериться с таблицей

Отладочная печать — в копии программы в scratch, не в файле задания (правило 6). После каждой строки — все колонки таблицы:

Код для чтения · разбираем, набирать не нужно
fmt.Println(boxes, len(boxes), cap(boxes), first, len(first), cap(first))

До объявления переменной её в печать не включают — в таблице у неё прочерк. Последняя строка таблицы обязана совпасть с тем, что печатает сама программа.

На контрольной точке так не делают: таблица заполняется до запуска, по картинке памяти, а запуск нужен только для сверки последней строки.


Дальше: правила контрольной точки 4 и задачи — course next