Трассировка ветвлений
В дне 02 трассировка отвечала на вопрос «что лежит в ячейках после каждой строки». С ветвлениями появляется второй вопрос: какие строки вообще выполнятся. На ревью чужого кода и на контрольной точке запустить программу нельзя — путь по веткам нужно пройти в голове.
Правила для ветвлений
Правила 1–6 дня 02 действуют: одна строка таблицы — одна выполненная строка внутри main, печать тоже; значения — после шага; прочерк - — переменной ещё нет; номера строк — по исходному файлу. Нумерация правил сквозная на весь курс, поэтому новые правила продолжают её — 7–10:
- Строка с
ifили} else if— шаг. На ней вычисляется условие. Условие только читает ячейки, поэтому значения в этой строке таблицы те же, что строкой выше. - Строки
} else {и}— не шаги. На них ничего не вычисляется. - Строки невыполненных веток в таблицу не попадают. Номера строк идут с пропусками.
- После первой сработавшей ветки остальная цепочка — не шаги. Следующее
} else ifниже не проверяется, его в таблице нет.
Ситуация. На складе 7 штук, в заказе 10. Программа решает, отгрузить заказ полностью, частично или никак.
1 package main
2
3 import "fmt"
4
5 func main() {
6 stock := 7
7 ordered := 10
8 status := "полностью"
9 if stock == 0 {
10 status = "нет"
11 } else if stock < ordered {
12 status = "частично"
13 ordered = stock
14 }
15 fmt.Println(status, ordered)
16 }| шаг | строка | что происходит | stock | ordered | status |
|---|---|---|---|---|---|
| 1 | 6 | создать stock |
7 | - | - |
| 2 | 7 | создать ordered |
7 | 10 | - |
| 3 | 8 | создать status |
7 | 10 | полностью |
| 4 | 9 | 7 == 0 — false, строка 10 пропущена |
7 | 10 | полностью |
| 5 | 11 | 7 < 10 — true, заходим в блок |
7 | 10 | полностью |
| 6 | 12 | status получает «частично» |
7 | 10 | частично |
| 7 | 13 | ordered = stock → 7 |
7 | 7 | частично |
| 8 | 15 | напечатать | 7 | 7 | частично |
stagiaire@lab:~/gocourse/day06/scratch$ go run .
частично 7Строки 10 нет: её ветка не выполнилась. Строки 14 нет: это }.
Та же программа с stock := 20 идёт другим путём:
# шаг | строка | stock | ordered | status
1 | 6 | 20 | - | -
2 | 7 | 20 | 10 | -
3 | 8 | 20 | 10 | полностью
4 | 9 | 20 | 10 | полностью
5 | 11 | 20 | 10 | полностью
6 | 15 | 20 | 10 | полностьюполностью 10Оба условия проверялись и оба оказались false — поэтому шаги 4 и 5 есть, а строк 10, 12 и 13 нет. Таблица стала на две строки короче: по числу строк видно, какой путь прошла программа.
Какая ветка сработала: отладочная печать
Проверить путь запуском можно так же, как в дне 02, — отладочной печатью в копии программы в scratch. Первой строкой каждой ветки вставьте печать с номером строки из исходного файла:
stock := 7
ordered := 10
status := "полностью"
if stock == 0 {
fmt.Println("строка 10")
status = "нет"
} else if stock < ordered {
fmt.Println("строка 12")
status = "частично"
ordered = stock
}
fmt.Println(status, ordered)строка 12
частично 7Напечаталась только «строка 12» — программа прошла через вторую ветку. В подписях — номера строк исходной программы: в копии они сдвинулись.
Попробуйте сейчас: трассировка trace.
Цель: заполнить
trace/table.txtбез запуска — скидка и бесплатная доставка, сумма у каждого своя.1. Посмотрите, что в папке задания:
▶ Выполнитеcd ~/gocourse/day06/trace ls2. Шаги и номера строк в
table.txtуже вписаны, и по ним виден путь. Поэтому сначала не открывайтеtable.txt: откройте толькоprogram.go, пройдите его в голове и выпишите на бумаге номера строк, которые выполнятся. Потом откройтеtable.txtи сверьте номера. Разошлось — найдите, в каком условии ошиблись.3. Заполните все
?без запуска. Потом запустите — три числа в выводе совпадут с последней строкой таблицы:pct,delivery,pay:▶ Выполнитеgo run .4. Этот шаг — сверка уже заполненной таблицы, а не способ получить числа: смысл упражнения в том, чтобы ваши числа совпали, а не в том, чтобы их напечатала машина. Разошлось что-то в середине — вот копия, в которой можно дописать отладочную печать и найти, где именно (
program.goпри этом не меняйте):▶ Выполнитеcp program.go ~/gocourse/day06/scratch/main.go cd ~/gocourse/day06/scratch go run .Готово, когда: в
table.txtне осталось?, три числа из выводаgo run .совпали с последней строкой таблицы, и вcourse check 06пункт «Таблица trace заполнена верно» (trace) отмечен ✔.
Задача с порогами: как её решать
В задании discount скидка зависит от суммы заказа: четыре ступени, пороги и проценты у каждого свои. Решаем по методу дня 05: условие → примеры → подцели → маленькие шаги → сверка.
Условие. cat TASK.txt. Выпишите пороги в копейках и проценты. Что печатать — три строки, их вид дан в условии.
Примеры. Одной своей суммы мало: она проверяет одну ступень из четырёх. Нужны примеры на каждую ступень и на каждый порог — сам порог и на копейку меньше. Посчитайте их на бумаге до кода. Для порогов 1000, 5000 и 10 000 руб. с процентами 2, 5 и 10 таблица примеров начиналась бы так:
| sum, коп. | Ступень | Скидка, коп. | К оплате, коп. |
|---|---|---|---|
| 99999 | меньше 1000 руб. | 0 | 99999 |
| 100000 | от 1000 руб. | 2000 | 98000 |
| 499999 | от 1000 руб. | 9999 | 490000 |
| 500000 | от 5000 руб. | 25000 | 475000 |
В третьей строке 499999 × 2 / 100 = 9999,98, а целое деление отбрасывает дробь — 9999.
Подцели.
- Процент по сумме — цепочка
else if. С какого порога начинать, решает правило порядка с третьей страницы. - Скидка в копейках — по формуле из условия.
- К оплате — сумма минус скидка.
- Печать рублей и копеек: рубли —
/ 100, копейки —% 100, вPrintf—%d.%02d(день 03). Знак процента вPrintf—%%.
Маленькие шаги. Сначала только подцель 1: цепочка и печать процента. Прогоните её со всеми суммами из таблицы примеров, меняя число в строке sum :=. Когда процент верный на всех границах — добавляйте скидку, потом печать.
Сверка. Своя сумма из условия даёт ровно три строки из TASK.txt, граничные суммы — ваши примеры с бумаги. gofmt -l . ничего не печатает.
Что может пойти не так
| Что видите | Что это значит | Что делать |
|---|---|---|
Строк с шагами в таблице 9, а нужно 10 |
строку удалили или добавили | переименовать table.txt, выполнить course lab 06, перенести значения в новую заготовку |
Все ? заполнены, но где-то значение не совпало |
ошибка в каком-то шаге | пройти заново по правилам; на строке с if значения те же, что строкой выше |
discount: на сумме ровно на пороге — процент меньшей ступени |
> вместо >= |
сверить знак с условием |
discount: у самой большой суммы процент средней ступени |
пороги в цепочке идут от меньшего к большему | начать с большего порога |
discount: копейки напечатаны одной цифрой — 312.5 вместо 312.05 |
в Printf %d вместо %02d |
%02d |
discount: личная сумма прошла, запуск с другой суммой — нет |
в программе готовые числа вместо вычислений | всё считать из sum |
не нашёл в main.go строк с начальными значениями: sum |
первая строка main не такая, как в условии |
sum := число — первой строкой main |
Попробуйте сейчас: задание discount.
Цель:
discount/main.goсчитает скидку на всех порогах из своегоTASK.txtи печатает три строки по образцу.1. Прочитайте условие:
▶ Выполнитеcd ~/gocourse/day06/discount cat TASK.txt2. Таблица примеров на бумаге, потом код по подцелям. Прогоните каждую границу из своей таблицы.
3. Верните свою сумму и выполните:
▶ Выполнитеgo run . gofmt -l .Готово, когда: каждая граница из таблицы дала на экране расчёт с бумаги, со своей суммой программа печатает три строки из
TASK.txt,gofmt -l .ничего не печатает (пункты проверкиdiscount,code_fmt).
Дальше: условия из нескольких частей — «и», «или», «не» — course next