Форматирование и столбцы
Вы знаете string.format по уроку «Переменные и типы»: она подставляет значения в строку по спецификаторам формата: %d для целого числа, %.2f для дробного числа с двумя знаками после запятой и %s для строки. format — такая же строковая функция, как остальные, поэтому её можно вызывать и как метод строки со спецификаторами:
local name = "Белла"
local liters = 18.5
print(string.format("%s дала %.1f л молока", name, liters))
print(("%s дала %.1f л молока"):format(name, liters))Он выводит:
Белла дала 18.5 л молока
Белла дала 18.5 л молокаОбе строки делают одно и то же; для метода нужны скобки вокруг строки, как вы уже знаете. %s принимает любое значение, а не только строку: ("%s"):format(true) даёт "true". А поскольку % начинает спецификатор, знак процента пишется как %%: ("%d%%"):format(75) даёт "75%".
Число между % и буквой задаёт ширину: сколько символов значение занимает как минимум. Более короткое значение дополняется слева пробелами, то есть выравнивается по правому краю. С минусом пробелы добавляются справа, и значение выравнивается по левому краю. Скобки в этом примере показывают, где каждое значение начинается и заканчивается:
print(("[%5d]"):format(42))
print(("[%-5d]"):format(42))
print(("[%8s]"):format("hen"))
print(("[%-8s]"):format("hen"))
print(("[%7.2f]"):format(3.14159))Он выводит:
[ 42]
[42 ]
[ hen]
[hen ]
[ 3.14]В %7.2f число 7 — это вся ширина вместе с десятичной точкой, а 2 — число знаков после запятой. Ширина нужна для ровной таблицы. Без неё каждая строка получается ровно такой длины, как её значения, и числа разъезжаются:
print(("%s %d"):format("eggs", 14))
print(("%s %d"):format("milk", 9))
print(("%s %d"):format("strawberries", 120))Он выводит:
eggs 14
milk 9
strawberries 120Если задать ширину, столбцы выровняются:
print(("%-12s %4d"):format("eggs", 14))
print(("%-12s %4d"):format("milk", 9))
print(("%-12s %4d"):format("strawberries", 120))Он выводит:
eggs 14
milk 9
strawberries 120Названия идут влево, поэтому %-12s; числа идут вправо, чтобы единицы и десятки стояли друг под другом: %4d. Ширину выбирают по самому длинному значению в столбце: более длинное значение не обрезается, а лишь нарушает выравнивание.
Типичная ошибка — спецификатор без значения:
print(("%s and %s"):format("eggs"))main.lua:1: bad argument #2 to 'format' (no value)Сообщение говорит, что одному из спецификаторов не хватило значения. Посчитайте спецификаторы и значения: значений должно быть столько же, сколько спецификаторов (%% не считается, значения ему не нужно). При вызове с двоеточием Lua не считает строку перед ним аргументом, поэтому в сообщении стоит #2; string.format("%s and %s", "eggs") выдаст #3, как в уроке «Переменные и типы».
И ещё об одном: ширина считается в байтах, а русская буква занимает два. Столбец со словом пюре сдвинулся бы на четыре места: по одному на каждую русскую букву. Поэтому названия в этом упражнении написаны по-английски; как быть с русскими буквами, показывает следующее упражнение.
Задание
- 1
Измените
printв цикле так, чтобы он использовалformat: название выровнено по левому краю в столбце шириной 12 символов, затем пробел, вес выровнен по правому краю в столбце шириной 6 символов с 2 знаками после запятой, затем пробел иkg. Вывод будет таким:carrots 12.50 kg potatoes 30.00 kg strawberries 4.25 kg - 2
Под циклом выведите итоговую строку: слово
Totalв столбце названий и сумму весов в столбце весов. Складывайте веса в цикле. Строка будет такой:Total 46.75 kg