Щодо [s[n]]printf
Koala, воно загалом (відносно) жруче до пам'яті, навіть мінімальний варіант без підтримки floating point форматів
та моїх улюблених можливостей на зразок «точності» для рядків ( "%.8s", або "%.*s" і взагалі * у форматах) може зжерти два кілобайти флеша. Також просить трохи більше стеку під буфер перетворення чисел у текст, деякі інші проблеми. Тому після звички вбирати програму у 8 кілобайт (наприклад, UV EPROM 27C64) жаба давить лінкувати у проект компанію printf.
Але.
MCS-51, я теж раніше старався обійтися без нього. На початку роботи на 8-бітниках. Але десь після ATmega64 (та це ж слон з можливостями як у комп'ютерів, на яких мова С зі стандартною бібліотекою і з'являлася!) /ATmega328 перестав про це турбуватися.
Яещо робота більш-менш складна, то купа рядків коду зі strcpy, ctrcat, strlen, *buf++ = і так далі зрештою і важко супроводжувати, і все одно їсть багато пам'яті.
Розглядайте printf-функції як інтерпретатор DSL по форматуванню тексту :-)
І я припинив робити вручну всякі такі речі
int addBitNumberLlistTag(char *dst, int len, const char *tag_name, uint8_t bits)
{
// Xоча краще б визначити константу десь поруч з оголошенням getBitNumberList
char buf[2 * CHAR_BITS + 1];
if (bits == 0)
return snprintf(dst, len, "<%s/>", tag_name);
getBitNumberList(buf, bits);
return snprintf(dst, len, "<%s>%s</%s>", tag_name, buf, tag_name);
}
Повернуте значення можна використовувати для контролю переповнення буфера
Перед початком створення даних
pr_buf.cursor = printed_data.buf; // якось отриманий вказівник на буфер
pr_buf.size_left = printed_data.buf_size;
Кожна порція додається якось так
int size = addBitNumberLlistTag(pr_buf.cursor, pr_buf.size_left, "outs_on", 0x55);
// У реальному коді наступні рядки об'єднати у функцію і замінити одним рядком
// return buf_forward(&pr_buf, size);
if (size >= pr_buf.size_left)
return ERR_BUF_TOO_SMALL;
pr_buf.size_left -= size;
pr_buf.cursor += size;
return OK;
Загалом прямо в addBitNumberLlistTag можна передавати вказівник на pr_buf, а він відразу може повертати buf_forward(&pr_buf, size);
У самопальному принтері даних у форматі json я приблизно так і зробив. Всі функції отрмують вказівник на json_buffer і додають своє туди.