0

How to format a thousand separator in C with FreeBSD? I obtain the code from one of the answers here How can I format currency with commas in C? and it is working in my Ubuntu Linux system but not in my FreeBSD 11.4 and 14-CURRENT systems.

#include <stdio.h>
#include <locale.h>

int main(void)
{
    setlocale(LC_NUMERIC, "");
    printf("$%'.2Lf\n", 123456789.00L);
    printf("$%'.2Lf\n", 1234.56L);
    printf("$%'.2Lf\n", 123.45L);
    return 0;
}
  • `'` is [a GNU extension](https://www.man7.org/linux/man-pages/man3/printf.3.html), so you need to check the documentation of BSD `printf`. Run `man 3 printf` on your BSD and read. Looks like [there's none](https://man.bsd.lv/printf.1) so you'll have to format it yourself – phuclv Oct 03 '22 at 04:10
  • @phuclv: FreeBSD [printf](https://www.freebsd.org/cgi/man.cgi?printf(3)) does have `'`. – sj95126 Oct 03 '22 at 04:26

2 Answers2

2

The printf manpage(3) says:

`'' (apostrophe) Decimal conversions (d, u, or i) or the integral portion of a floating point conversion (f or F) should be grouped and separated by thousands using the non-monetary separator returned by localeconv(3).

so, it uses the locale separator.

You can do something like that:

#include <stdio.h>
#include <locale.h>

int main(void)
{
    const char sep = '\'';

    setlocale(LC_NUMERIC, ""); 
    localeconv()->thousands_sep[0] = sep;

    printf("$%'04.2Lf\n", 123456789.00L);
    printf("$%'04.2Lf\n", 1234.56L);
    printf("$%'04.2Lf\n", 123.45L);

    return 0;
}

then compile like this:

cc -o myprog myprog.c

which will output:

./myprog
$123'456'789.00
$1'234.56
$123.45
Valery S.
  • 596
  • 1
  • 4
  • 10
  • `$ cc thousand-separator.c -o thousand-separator thousand-separator.c:11:17: warning: invalid conversion specifier ''' [-Wformat-invalid-specifier] printf("$%04'.2Lf\n", 123456789.00L); ~~~^ thousand-separator.c:12:17: warning: invalid conversion specifier ''' [-Wformat-invalid-specifier] printf("$%04'.2Lf\n", 1234.56L); ~~~^ thousand-separator.c:13:17: warning: invalid conversion specifier ''' [-Wformat-invalid-specifier] printf("$%04'.2Lf\n", 123.45L); ~~~^ 3 warnings generated.` – ordinary_guy Oct 03 '22 at 09:19
  • Above errors are encountered while compiling your code @ValeryS. – ordinary_guy Oct 03 '22 at 09:20
  • Sorry, I used `gcc` and it didn't complain, `cc` just spit some warning but still compile. I just edit my answer with the right format, and it will not complain again. My bad – Valery S. Oct 03 '22 at 10:54
  • It's alright and yes I'm using the default compiler of FreeBSD 11.4 and 14.0-CURRENT which is `clang`. With the current revision you have, compilation got no more warnings, however I encountered segmentation fault (core dumped). Anyway, let me check what's going on. – ordinary_guy Oct 03 '22 at 11:31
  • answer edited with the compiler usage ; check your environment, editor. Everything was done under FreeBSD-13.1-p1 amd64, clang-13.0.0 and gcc-11.3.0, no warnings, no error, no nothing. – Valery S. Oct 03 '22 at 12:45
0

Just found this, by specifying this argument en_US.UTF-8 in the setlocale() will also provide thousand separator in C with FreeBSD.

#include <stdio.h>
#include <locale.h>

int main(void)
{
    setlocale(LC_NUMERIC, "en_US.UTF-8");
    printf("$%'.2Lf\n", 123456789.00L);
    printf("$%'.2Lf\n", 1234.56L);
    printf("$%'.2Lf\n", 123.45L);
    return 0;
}
  • Yep, of course, this is what I said in my answer : **"so, it uses the locale separator."** ; my code has been done from your own code in order to provide a solution from your requirements or constraints I don't know ; you wrote in your question `setlocale(LC_NUMERIC, "");`, I assumed this as a constraint and write the code accordingly. – Valery S. Oct 04 '22 at 09:09
  • There's no problem with your shared solution @ValeryS. I really appreciate it, however when your code is compiled and run, it keeps crashing (segmentation fault) in my FreeBSD systems (11.4-RELEASE(x86_64) and 14.0-CURRENT(aarch64)) and it's the reason why I keep looking and found the one I shared which works without any problem. – ordinary_guy Oct 05 '22 at 07:37