How to add thousands separator to double in C on Windows?

I use the MPFR library to perform calculations on large numbers, but also return double with 8 digits after the decimal point.

I mpfr_sprintf is the number before the char array, so the accuracy or something is not lost. Everything is in order, except that I did not find any thousands separator options in the documentation (or I missed it).

Given a number like 20043.95381376, I would like to introduce it as 20,043.95381376 for better readability.

Or number 164992818.48075795 as 164 992 818.48075795

I read about the apostrophe that should be added to printf / sprintf, but it looks like UNIX / POSIX and I am a Windows user.

Since I print the number as a string, I thought that I could write a special implementation that will automatically add a comma depending on the number (> 1000> 10000> 100000, etc.), but then I realized that functions like strncpy or strcpy will essentially replace, rather than add a comma to, the desired position. And here's how I get back to how to do it.

How can i do this?

+3
source share
3 answers

You need your implementation to convert a double value to a string and examine each character of that string, and then copy it to the output string along with the delimiters.

Something like that:

#include <stdio.h>
#include <string.h>

int thousandsep(double in, char* out_str, size_t out_len, unsigned int precision) {
    char in_str[128], int_str[128], format[32];
    size_t dlen, mod, i, j;
    int c;

    snprintf(format, sizeof format, "%%.%df", precision);
    snprintf(in_str, sizeof in_str, format, in);
    snprintf(int_str, sizeof int_str, "%d", (int)in);

    dlen = strlen(in_str);
    mod = strlen(int_str) % 3;
    c = (mod == 0) ? 3 : mod;

    for (i=0, j=0; i<dlen; i++, j++, c--) {
        if (j >= out_len - 1) {
            /* out_str is too small */
            return -1;
        }

        if (in_str[i] == '.') {
            c = -1;
        } else if (c == 0) {
            out_str[j++] = ',';
            c = 3;
        }

        out_str[j] = in_str[i];
    }
    out_str[j] = '\0';

    return 0;
}

Then use it like this:

char out_str[64];

if (thousandsep(20043.95381376, out_str, sizeof out_str, 8) == 0)
    printf("%s\n", out_str);       /* 20,043.95381376 */

if (thousandsep(164992818.48075795, out_str, sizeof out_str, 8) == 0)
    printf("%s\n", out_str);       /* 164,992,818.48075795 */

if (thousandsep(1234567.0, out_str, sizeof out_str, 0) == 0)
    printf("%s\n", out_str);       /* 1,234,567 */

. , Windows, MSVC, C89.

+2

GetNumberFormatEx , .. Pass LOCALE_NAME_USER_DEFAULT , , .

(, ), NUMBERFMT , , .

+2

, , .

, , .

. , . .

, .

, , .

{
    double dFloat = 123456789012.567890;
    char xBuff[128];
    sprintf (xBuff, "%f", dFloat);

    char xBuff2[128];
    int iLen = strlen(xBuff);
    int iPoint = iLen;
    for (iLen--; iLen >= 0; iLen--) {
        if (xBuff[iLen] == '.' || xBuff[iLen] == ',') {
            // found the decimal point.  depends on locale.
            iPoint = iLen;
            break;
        }
    }
    strcpy (xBuff2, xBuff + iPoint);   // save the decimal portion

    char xBuff3[128], xBuff4[128];
    xBuff3[127] = 0;    // set an end of string
    int  iCount, jLen;
    for (iCount = 1, jLen = 126, iLen--; iLen >= 0; jLen--, iLen--) {
        if ((iCount % 4) == 0) {
            xBuff3[jLen] = ',';
            jLen--;
            iCount = 1;
        }
        xBuff3[jLen] = xBuff[iLen];
        iCount++;
    }
    strcpy (xBuff4, xBuff3 + jLen + 1);
    strcat (xBuff4, xBuff2);
}
0

Source: https://habr.com/ru/post/1531177/


All Articles