How to use compound literals to `fprintf()` multiple formatted numbers with arbitrary bases?

跟風遠走 提交于 2019-11-27 05:20:56
chux

C99 C11 introduced compound literals which allow not only a complicated initialized structure, but also an "in-line" variable.

Code can call a conversion function and pass in a new buffer (char [UTOA_BASE_N]){0} per each function call allowing the function to return that same buffer, now written as needed that is still within its lifetime. The returned string is then printed using various flags, width and precision available to the "%s" specifier.

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

// Maximum buffer size needed
#define UTOA_BASE_N (sizeof(unsigned)*CHAR_BIT + 1)

char *utoa_base(char *s, unsigned x, unsigned base) {
  s += UTOA_BASE_N - 1;
  *s = '\0';
  if (base >= 2 && base <= 36) {
    do {
      *(--s) = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[x % base];
      x /= base;
    } while (x);
  }
  return s;
}

#define TO_BASE(x,b) utoa_base((char [UTOA_BASE_N]){0} , (x), (b))

void test(unsigned x) {
  printf("base10:%10u base2:%5s  base36:%s ", x, TO_BASE(x, 2), TO_BASE(x, 36));
  printf("%lu\n", strtoul(TO_BASE(x, 36), NULL, 36));
}

int main(void) {
  test(0);
  test(25);
  test(UINT_MAX);
}

Output

base10:         0 base2:    0  base36:0 0
base10:        25 base2:11001  base36:P 25
base10:4294967295 base2:11111111111111111111111111111111  base36:1Z141Z3 4294967295

Ref: Is there a printf converter to print in binary format? has a number of answers but none of them allow the simple memory management (no static) of the above with access to fprintf() flags width, precision and use the full range of the number.

This is an Answer your own question answer.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!