Cで1123456789から1,123,456,789までの数値をフォーマットするにはどうすればよいですか?


83

C言語でから1123456789までの数値をフォーマットするにはどうすればよい1,123,456,789ですか?使ってみましprintf("%'10d\n", 1123456789);たがうまくいきません。

何かアドバイスはありますか?ソリューションは単純であるほど優れています。


1
参考までに:printf()フォーマットされたIO関数のファミリーの「千単位の区切り文字」フラグ(一重引用符: ')は、いくつかのライブラリ実装でのみサポートされる非標準のフラグです。それが標準ではないのは残念です。
Michael Burr

1
ロケールに依存します。Linuxのmanページによると、それはを調べLC_NUMERICます。ただし、どのロケールがこれをサポートしているかはわかりません。
ジョーイアダムス

1
@Joey、設定LC_NUMERIC電流にロケールは""作る'私のMac上で、私はちょうどチェックをLinuxマシン上で作業を。
Carl Norum 2012

printf()関数ファミリーのPOSIX2008(2013)バージョンは'、10進数のフォーマット変換仕様で(一重引用符またはアポストロフィ)文字の使用を標準化して、数値を千単位の区切り文字でフォーマットするように指定していることに注意してください。
ジョナサンレフラー2015

2
また、デフォルトの"C"ロケールでは、金銭以外の千単位の区切り文字が定義"%'d"されていないため、"C"ロケールでカンマが生成されないことにも注意してください。適切な非金銭的な千単位の区切り文字を使用してロケールを設定する必要があります。多くの場合、setlocale(LC_ALL, "");仕事をします—ロケール名の他の値(空の文字列以外)は実装で定義されています。
ジョナサンレフラー

回答:


83

printfが'フラグをサポートしている場合(POSIX 2008で要求されているようにprintf())、ロケールを適切に設定するだけでおそらくサポートできます。例:

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

int main(void)
{
    setlocale(LC_NUMERIC, "");
    printf("%'d\n", 1123456789);
    return 0;
}

そしてビルド&実行:

$ ./example 
1,123,456,789

Mac OS XおよびLinux(Ubuntu 10.10)でテスト済み。


1
私が上でこれをテストしてみたsprintf()組み込みシステムで、あなたが言うように、それは'フラグをサポートしていますので、それは、明らかに(仕事をしていない。
gbmhunter

それほど問題なくそれをサポートするCライブラリを見つけることができると確信しています。
Carl Norum 2013年

私はざっと見て、適切なものを見つけられず、上記のアイデアのいくつかを使用して自分で実装しました。実際のライブラリを見つけて、小数点以下の桁数のある浮動小数点数や文字列で使用できるようにすると便利です。
gbmhunter 2013年

1
FWIW AtmelStudioの組み込みシステムprintf()は、悲劇的なこと'修飾子をサポートしていないようです。ヘッダーから:Copyright ... 2007 Joerg Wunsch ... 1993 Regents of the University of CaliforniaすなわちBSD派生物。
ボブ・スタイン

2
これは便利ですが、この機能(setlocale)の状態を必ずしも変更する必要はありません。
ideasman42

46

次のように再帰的に実行できます(INT_MIN2の補数を使用している場合は、それを管理するために追加のコードが必要になることに注意してください)。

void printfcomma2 (int n) {
    if (n < 1000) {
        printf ("%d", n);
        return;
    }
    printfcomma2 (n/1000);
    printf (",%03d", n%1000);
}

void printfcomma (int n) {
    if (n < 0) {
        printf ("-");
        n = -n;
    }
    printfcomma2 (n);
}

要約:

  • ユーザーがprintfcomma整数で呼び出す場合、負の数の特殊なケースは、「-」を出力して数値を正にすることで処理されます(これはで機能しないビットです)INT_MIN)。
  • あなたが入るとき printfcomma2と、1,000未満の数値が出力されて返されます。
  • それ以外の場合、再帰は、1,000未満の数が見つかるまで、次のレベルで呼び出されます(したがって、1,234,567は1,234で呼び出され、次に1で呼び出されます)。
  • 次に、その番号が出力され、再帰ツリーに戻って、コンマと次の番号を出力します。

すべてのレベルで負の数をチェックする際に不要な処理を行いますが、より簡潔なバージョンもあります(再帰レベルの数が限られているため、これは問題になりません)。これはテスト用の完全なプログラムです。

#include <stdio.h>

void printfcomma (int n) {
    if (n < 0) {
        printf ("-");
        printfcomma (-n);
        return;
    }
    if (n < 1000) {
        printf ("%d", n);
        return;
    }
    printfcomma (n/1000);
    printf (",%03d", n%1000);
}

int main (void) {
    int x[] = {-1234567890, -123456, -12345, -1000, -999, -1,
               0, 1, 999, 1000, 12345, 123456, 1234567890};
    int *px = x;
    while (px != &(x[sizeof(x)/sizeof(*x)])) {
        printf ("%-15d: ", *px);
        printfcomma (*px);
        printf ("\n");
        px++;
    }
    return 0;
}

出力は次のとおりです。

-1234567890    : -1,234,567,890
-123456        : -123,456
-12345         : -12,345
-1000          : -1,000
-999           : -999
-1             : -1
0              : 0
1              : 1
999            : 999
1000           : 1,000
12345          : 12,345
123456         : 123,456
1234567890     : 1,234,567,890

再帰を信頼しない人のための反復ソリューション(再帰の唯一の問題はスタックスペースである傾向がありますが、64ビット整数の場合でも数レベルの深さしかないため、ここでは問題になりません):

void printfcomma (int n) {
    int n2 = 0;
    int scale = 1;
    if (n < 0) {
        printf ("-");
        n = -n;
    }
    while (n >= 1000) {
        n2 = n2 + scale * (n % 1000);
        n /= 1000;
        scale *= 1000;
    }
    printf ("%d", n);
    while (scale != 1) {
        scale /= 1000;
        n = n2 / scale;
        n2 = n2  % scale;
        printf (",%03d", n);
    }
}

これらは両方ともに対して生成さ2,147,483,647INT_MAXます。


問題は再帰的(「残りの3桁を分離し、残りでこれを繰り返す」)よりも自然に反復(「3桁ごとに分離」)であるため、これはむしろ反復的に解決する必要があると思います。
Joren 2009

MIN_INTの推奨される修正:printfcomma2を変更してunsignedintを取得します。それでおしまい。「余分なコード」はそれほど多くありません:
Steve Jessop

@Joren:反復ソリューションを追加しましたが、再帰ソリューションにメリットがある理由をある程度示しています。多くの場合、再帰の回避はコーディング標準の問題ですが。
クリフォード

@Steve:UBはできるだけ早くあなたが否定として呼び出されたためにだけは、引数の型を変更すると、それを修正しないnprintfcomma。否定する前に、unsignedへの変換を強制する必要があります。
R .. GitHub STOP HELPING ICE 2011

1
@Nehal、現在の進行状況がすべて失われるという意味で、再開することはありません。自分自身を再帰的に呼び出してから、次のステートメントであるprintf。に戻ります。
paxdiablo

11

これは非常に単純な実装です。この関数にエラーチェックが含まれていません。呼び出し元がバッファサイズを確認する必要があります。また、負の数では機能しません。このような改善は、読者の演習として残されています。

void format_commas(int n, char *out)
{
    int c;
    char buf[20];
    char *p;

    sprintf(buf, "%d", n);
    c = 2 - strlen(buf) % 3;
    for (p = buf; *p != 0; p++) {
       *out++ = *p;
       if (c == 1) {
           *out++ = ',';
       }
       c = (c + 1) % 3;
    }
    *--out = 0;
}

私はこれが好きです、それは組み込みシステムに役立つprintfの代わりにsprintfを使用します。
gbmhunter 2013年

1
非常に優れていますが、負の数を処理するには、いくつかの微調整が必​​要です。
ideasman42

(負の数をサポートするための修正版stackoverflow.com/a/24795133/432509
ideasman42

5

エガド!Linuxでgcc / g ++とglibcを使用して、これを常に行っています。そうです、 '演算子は非標準かもしれませんが、その単純さが気に入っています。

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

int main()
{
    int bignum=12345678;

    setlocale(LC_ALL,"");

    printf("Big number: %'d\n",bignum);

    return 0;
}

次の出力を提供します。

大きな数:12,345,678

そこにある「setlocale」呼び出しを覚えておく必要があります。そうしないと、何もフォーマットされません。


2
残念ながら、これはWindows / gcc4.9.2では機能しないようです。
rdtsc 2017年

まあドラト!どのプラットフォームのgccでも、OSに関係なく同様の結果が得られると思いました。知っておくといいのですが、なぜだろうと思います。Hmmmmm .....
lornix

使用中のCライブラリが'フラグをサポートしていない場合、目的の出力が得られないことに注意してください。これはコンパイラに依存しません。コンパイラは、のライブラリ関数printf()がフォーマット文字列で呼び出されるようにします。それを解釈するのはライブラリ関数次第です。Windowsでは、CRTライブラリが必要なサポートを提供しない可能性があります。使用するコンパイラは重要ではありません。
ジョナサンレフラー

3

おそらく、ロケール対応バージョンが興味深いでしょう。

#include <stdlib.h>
#include <locale.h>
#include <string.h>
#include <limits.h>

static int next_group(char const **grouping) {
    if ((*grouping)[1] == CHAR_MAX)
        return 0;
    if ((*grouping)[1] != '\0')
        ++*grouping;
    return **grouping;
}

size_t commafmt(char   *buf,            /* Buffer for formatted string  */
                int     bufsize,        /* Size of buffer               */
                long    N)              /* Number to convert            */
{
    int i;
    int len = 1;
    int posn = 1;
    int sign = 1;
    char *ptr = buf + bufsize - 1;

    struct lconv *fmt_info = localeconv();
    char const *tsep = fmt_info->thousands_sep;
    char const *group = fmt_info->grouping;
    char const *neg = fmt_info->negative_sign;
    size_t sep_len = strlen(tsep);
    size_t group_len = strlen(group);
    size_t neg_len = strlen(neg);
    int places = (int)*group;

    if (bufsize < 2)
    {
ABORT:
        *buf = '\0';
        return 0;
    }

    *ptr-- = '\0';
    --bufsize;
    if (N < 0L)
    {
        sign = -1;
        N = -N;
    }

    for ( ; len <= bufsize; ++len, ++posn)
    {
        *ptr-- = (char)((N % 10L) + '0');
        if (0L == (N /= 10L))
            break;
        if (places && (0 == (posn % places)))
        {
            places = next_group(&group);
            for (int i=sep_len; i>0; i--) {
                *ptr-- = tsep[i-1];
                if (++len >= bufsize)
                    goto ABORT;
            }
        }
        if (len >= bufsize)
            goto ABORT;
    }

    if (sign < 0)
    {
        if (len >= bufsize)
            goto ABORT;
        for (int i=neg_len; i>0; i--) {
            *ptr-- = neg[i-1];
            if (++len >= bufsize)
                goto ABORT;
        }
    }

    memmove(buf, ++ptr, len + 1);
    return (size_t)len;
}

#ifdef TEST
#include <stdio.h>

#define elements(x) (sizeof(x)/sizeof(x[0]))

void show(long i) {
    char buffer[32];

    commafmt(buffer, sizeof(buffer), i);
    printf("%s\n", buffer);
    commafmt(buffer, sizeof(buffer), -i);
    printf("%s\n", buffer);
}


int main() {

    long inputs[] = {1, 12, 123, 1234, 12345, 123456, 1234567, 12345678 };

    for (int i=0; i<elements(inputs); i++) {
        setlocale(LC_ALL, "");
        show(inputs[i]);
    }
    return 0;
}

#endif

これにはバグがあります(しかし、私はかなりマイナーだと思います)。2の補数ハードウェアでは、負の数を同等の正の数に変換しようとするため、最も負の数を正しく変換N = -N;しません。2の補数では、最大の負の数には、対応する正の数がありません。より大きなタイプに宣伝します。これを回避する1つの方法は、対応する符号なしタイプの番号をプロモートすることです(ただし、これは簡単ではありません)。


私は'ここでフォーマットフラグのクロスプラットフォーム実装に向けられた質問をしました:stackoverflow.com/q/44523855/2642059この答えはそれを完全に解決し、今より多くのテストを行っていると思います。もしそうなら、私はその質問を重複としてマークする必要があると思いますか?
ジョナサンミー2017年

OK、私が最初に認識したことは、ロケールが調整されても調整されないことです。なぜ、保守tsepplace_strおよびneg_strすべての?fmt_infoのメンバーを直接使用しないのはなぜですか?
ジョナサンミー2017年

OK、2番目の数字、このコードは負の数を処理できません...そして、それがどのようにできるのか正確にはわかりwhile (*ptr-- = *neg_str++)ませんが、私にはあまり意味がありません。負の文字列文字を逆の順序で挿入しています。
ジョナサンミー2017年

だから...私はメモリリークを排除し、負の数でバグを修正しました:ideone.com/gTv8Z4残念ながら、複数の文字区切り文字または複数の文字の負の記号が文字列に逆方向に書き込まれるという問題がまだあります。私はその次...解決しようとするつもりだ
ジョナサン・ミー

@JonathanMee:コードを更新しました(そして、負の数を含む、少なくともいくつかのテストケースを追加しました)。
ジェリーコフィン2017年

2

再帰や文字列処理なしで、数学的アプローチ:

#include <stdio.h>
#include <math.h>

void print_number( int n )
{
    int order_of_magnitude = (n == 0) ? 1 : (int)pow( 10, ((int)floor(log10(abs(n))) / 3) * 3 ) ;

    printf( "%d", n / order_of_magnitude ) ;

    for( n = abs( n ) % order_of_magnitude, order_of_magnitude /= 1000;
        order_of_magnitude > 0;
        n %= order_of_magnitude, order_of_magnitude /= 1000 )
    {
        printf( ",%03d", abs(n / order_of_magnitude) ) ;
    }
}

原理的にはPaxの再帰的ソリューションに似ていますが、事前に桁数を計算することにより、再帰が回避されます(おそらくかなりの費用がかかります)。

数千を区切るために使用される実際の文字はロケール固有であることにも注意してください。

編集:改善については、以下の@Chuxのコメントを参照してください。


1
を実行するときに2の補数エラーabs(n)fabs(n)防ぐために変更 しますprint_number(INT_MIN)
chux -復活モニカ

@chux:良い点ですが、%式では、LHSはintにキャストバックされ、それでも壊れます。それはちょうど許容入力のわずかに小さい範囲を受け入れるか、テストして出力を追加するために「-2147483647」に直接INT_MINのために、おそらく単純である(またはINT_MINが問題のプラットフォーム上にあるものは何でも-そこにワームの別の缶に位置しています。
クリフォード

提案する前に、テストに成功しました。うーん。私のアイデアは、log10(abs(n))他の場所ではなく、のためだけのものだったと思います。興味深いことに、あなたのソリューションは、単一の変更で動作log10(fabs(n))してprint_number(INT_MIN)いるためのprintf(..., abs(n / order_of_magnitude))手段はどのn = abs(INT_MIN) % order_of_magnitude負でOKです。INT_MINをあきらめると、printf(..., abs(n / order_of_magnitude))はになりprintf(..., n / order_of_magnitude)ます。しかし、「abs(INT_MIN)」と呼ばれるそのワームを扱うことは通常悪いことだと思います。
chux -復活モニカ

3つの変更を提案:新は思ったlog10(fabs(n))n = abs(n% order_of_magnitude)printf(",%03d", n/order_of_magnitude)。ところで:あなたの解決策が良いと思わない限り、私はこの努力を費やしません。INT_MINの場合でも、UBはありません。
chux -復活モニカ

2

@Greg Hewgillに基づいていますが、負の数を考慮して文字列サイズを返します。

size_t str_format_int_grouped(char dst[16], int num)
{
    char src[16];
    char *p_src = src;
    char *p_dst = dst;

    const char separator = ',';
    int num_len, commas;

    num_len = sprintf(src, "%d", num);

    if (*p_src == '-') {
        *p_dst++ = *p_src++;
        num_len--;
    }

    for (commas = 2 - num_len % 3;
         *p_src;
         commas = (commas + 1) % 3)
    {
        *p_dst++ = *p_src++;
        if (commas == 1) {
            *p_dst++ = separator;
        }
    }
    *--p_dst = '\0';

    return (size_t)(p_dst - dst);
}

1

私の答えは、質問の図のように結果を正確にフォーマットしていませんが、実際のニーズを満たす可能性があります、場合によっては、単純なワンライナーまたはマクロでをます。必要に応じて、それを拡張してさらに千のグループを生成することができます。

結果は、たとえば次のようになります。

Value: 0'000'012'345

コード:

printf("Value: %llu'%03lu'%03lu'%03lu\n", (value / 1000 / 1000 / 1000), (value / 1000 / 1000) % 1000, (value / 1000) % 1000, value % 1000);

ある'標準表記法と同等,の世界の一部では(数学的に、少なくとも)(複数可)?
ysap

1
@ysap世界の一部の地域では千単位の区切り文字です。
RolandPihlakas19年

0

Cでこれを行うための実際の簡単な方法はありません。int-to-string関数を変更して実行するだけです。

void format_number(int n, char * out) {
    int i;
    int digit;
    int out_index = 0;

    for (i = n; i != 0; i /= 10) {
        digit = i % 10;

        if ((out_index + 1) % 4 == 0) {
            out[out_index++] = ',';
        }
        out[out_index++] = digit + '0';
    }
    out[out_index] = '\0';

    // then you reverse the out string as it was converted backwards (it's easier that way).
    // I'll let you figure that one out.
    strrev(out);
}

0

別の反復関数

int p(int n) {
  if(n < 0) {
    printf("-");
    n = -n;
  }

  int a[sizeof(int) * CHAR_BIT / 3] = { 0 };
  int *pa = a;
  while(n > 0) {
    *++pa = n % 1000;
    n /= 1000;
  }
  printf("%d", *pa);
  while(pa > a + 1) {
    printf(",%03d", *--pa);
  }
}

配列の次元を決定するために使用される式に興味があります!?そのための数学的正当化はありますか?
クリフォード

10進数ごとにld(10)ビット。3に切り捨てます(一度に最大3桁を格納するという事実を考慮して)、3を再度除算できます。しかし、私はそれを上限に保ちたかったのです。
Johannes Schaub-litb 2009

0

この種の10進数フォーマットの最もスリムで、サイズと速度が効率的な実装は次のとおりです。

const char *formatNumber (
    int value,
    char *endOfbuffer,
    bool plus)
{
    int savedValue;
    int charCount;

    savedValue = value;
    if (unlikely (value < 0))
        value = - value;
    *--endOfbuffer = 0;
    charCount = -1;
    do
    {
        if (unlikely (++charCount == 3))
        {
            charCount = 0;
            *--endOfbuffer = ',';
        }

        *--endOfbuffer = (char) (value % 10 + '0');
    }
    while ((value /= 10) != 0);

    if (unlikely (savedValue < 0))
        *--endOfbuffer = '-';
    else if (unlikely (plus))
        *--endOfbuffer = '+';

    return endOfbuffer;
}

次のように使用します。

char buffer[16];
fprintf (stderr, "test : %s.", formatNumber (1234567890, buffer + 16, true));

出力:

test : +1,234,567,890.

いくつかの利点:

  • 逆順のフォーマットのため、文字列バッファの終わりをとる関数。最後に、生成された文字列(strrev)を崇拝する必要はありません。

  • この関数は、後の任意のアルゴリズムで使用できる1つの文字列を生成します。複数のprintf / sprintf呼び出しに依存したり、必要としたりすることはありません。これは非常に遅く、常にコンテキスト固有です。

  • 除算演算子の最小数(/、%)。

unlikelyですか?
ダンベチャード2017

1
@Dan:unlikely条件が真になる可能性が低いというオプティマイザーへのヒントである可能性があります。詳細については、Linuxカーネルのlikely()/unlikely()マクロを参照してください。
ジョナサンレフラー2017年

@JonathanLefflerああ、ハァッ。リンクをありがとう。
ダンベチャード2017年

0

負の数でformat_commasを保護します。

VS <2015はsnprintfを実装していないため、これを行う必要があります

#if defined(_WIN32)
    #define snprintf(buf,len, format,...) _snprintf_s(buf, len,len, format, __VA_ARGS__)
#endif

その後

char* format_commas(int n, char *out)
{
    int c;
    char buf[100];
    char *p;
    char* q = out; // Backup pointer for return...

    if (n < 0)
    {
        *out++ = '-';
        n = abs(n);
    }


    snprintf(buf, 100, "%d", n);
    c = 2 - strlen(buf) % 3;

    for (p = buf; *p != 0; p++) {
        *out++ = *p;
        if (c == 1) {
            *out++ = '\'';
        }
        c = (c + 1) % 3;
    }
    *--out = 0;

    return q;
}

使用例:

size_t currentSize = getCurrentRSS();
size_t peakSize = getPeakRSS();


printf("Current size: %d\n", currentSize);
printf("Peak size: %d\n\n\n", peakSize);

char* szcurrentSize = (char*)malloc(100 * sizeof(char));
char* szpeakSize = (char*)malloc(100 * sizeof(char));

printf("Current size (f): %s\n", format_commas((int)currentSize, szcurrentSize));
printf("Peak size (f): %s\n", format_commas((int)currentSize, szpeakSize));

free(szcurrentSize);
free(szpeakSize);

0

@paxdiabloソリューションの修正バージョンですが、とを使用WCHARしていwsprinfます:

static WCHAR buffer[10];
static int pos = 0;

void printfcomma(const int &n) {
    if (n < 0) {
        wsprintf(buffer + pos, TEXT("-"));
        pos = lstrlen(buffer);
        printfcomma(-n);
        return;
    }
    if (n < 1000) {
        wsprintf(buffer + pos, TEXT("%d"), n);
        pos = lstrlen(buffer);
        return;
    }
    printfcomma(n / 1000);
    wsprintf(buffer + pos, TEXT(",%03d"), n % 1000);
    pos = lstrlen(buffer);
}

void my_sprintf(const int &n)
{
    pos = 0;
    printfcomma(n);
}

0

私はCプログラミングの初心者です。これが私の簡単なコードです。

int main()
{
    //  1223 => 1,223
    int n;
    int a[10];
    printf(" n: ");
    scanf_s("%d", &n);
    int i = 0;
    while (n > 0)
    {
        int temp = n % 1000;
        a[i] = temp;
        n /= 1000;
        i++;
    }
    for (int j = i - 1; j >= 0; j--)
    {
        if (j == 0) 
        {
            printf("%d.", a[j]);
        }
        else printf("%d,",a[j]);
    }
    getch();
    return 0;
}

0
#include <stdio.h>

void punt(long long n){
    char s[28];
    int i = 27;
    if(n<0){n=-n; putchar('-');} 
    do{
        s[i--] = n%10 + '0';
        if(!(i%4) && n>9)s[i--]='.';
        n /= 10;
    }while(n);
    puts(&s[++i]);
}


int main(){
    punt(2134567890);
    punt(987);
    punt(9876);
    punt(-987);
    punt(-9876);
    punt(-654321);
    punt(0);
    punt(1000000000);
    punt(0x7FFFFFFFFFFFFFFF);
    punt(0x8000000000000001); // -max + 1 ...
}

私のソリューションはを使用しています。の代わりに、これを変更するのは読者に任されています。


0

これは古く、答えはたくさんありますが、質問は「コンマを追加するルーチンをどのように書くことができるか」ではなく、「Cでどのように行うことができるか」でした。コメントはこの方向を示していましたが、GCCを備えた私のLinuxシステムでは、これは私にとってはうまくいきます:

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
int main()
{
    unsetenv("LC_ALL");
    setlocale(LC_NUMERIC, "");
    printf("%'lld\n", 3141592653589);
}

これを実行すると、次のようになります。

$ cc -g comma.c -o comma && ./comma
3,141,592,653,589

LC_ALLプログラムを実行する前に変数の設定を解除した場合、それunsetenvは必要ありません。


0

自分と同じようなことをする必要がありましたが、直接印刷するのではなく、バッファに移動する必要がありました。これが私が思いついたものです。逆方向に動作します。

unsigned int IntegerToCommaString(char *String, unsigned long long Integer)
{
    unsigned int Digits = 0, Offset, Loop;
    unsigned long long Copy = Integer;

    do {
        Digits++;
        Copy /= 10;
    } while (Copy);

    Digits = Offset = ((Digits - 1) / 3) + Digits;
    String[Offset--] = '\0';

    Copy = Integer;
    Loop = 0;
    do {
        String[Offset] = '0' + (Copy % 10);
        if (!Offset--)
            break;
        if (Loop++ % 3 == 2)
            String[Offset--] = ',';
        Copy /= 10;
    } while (1);

    return Digits;
}

符号なし整数用にのみ設計されているため、バッファが十分に大きいことを確認する必要があることに注意してください。


0

別の解決策は、結果をint配列に保存することです。このlong long int型は9,223,372,036,854,775,807から-9,223,372,036,854,775,807の範囲の数値を処理できるため、最大サイズは7です。(符号なしの値ではないことに注意してください)。

非再帰印刷機能

static void printNumber (int numbers[8], int loc, int negative)
{
    if (negative)
    {
        printf("-");
    }
    if (numbers[1]==-1)//one number
    {
        printf("%d ", numbers[0]);
    }
    else
    {
        printf("%d,", numbers[loc]);
        while(loc--)
        {
            if(loc==0)
            {// last number
                printf("%03d ", numbers[loc]);
                break;
            }
            else
            { // number in between
                printf("%03d,", numbers[loc]);
            }
        }
    }
}

主な関数呼び出し

static void getNumWcommas (long long int n, int numbers[8])
{
    int i;
    int negative=0;
    if (n < 0)
    {
        negative = 1;
        n = -n;
    }
    for(i = 0; i < 7; i++)
    {
        if (n < 1000)
        {
            numbers[i] = n;
            numbers[i+1] = -1;
            break;
        }
        numbers[i] = n%1000;
        n/=1000;
    }

    printNumber(numbers, i, negative);// non recursive print
}

テスト出力

-9223372036854775807: -9,223,372,036,854,775,807
-1234567890         : -1,234,567,890
-123456             : -123,456
-12345              : -12,345
-1000               : -1,000
-999                : -999
-1                  : -1
0                   : 0
1                   : 1
999                 : 999
1000                : 1,000
12345               : 12,345
123456              : 123,456
1234567890          : 1,234,567,890
9223372036854775807 : 9,223,372,036,854,775,807

main()関数の場合:

int numberSeparated[8];
long long int number = 1234567890LL;
getNumWcommas(number, numberSeparated);

印刷だけが必要な場合はint numberSeparated[8];、関数内に移動しgetNumWcommasてこのように呼び出しますgetNumWcommas(number)


-1

かなり簡単にできます...

//Make sure output buffer is big enough and that input is a valid null terminated string
void pretty_number(const char* input, char * output)
{
    int iInputLen = strlen(input);
    int iOutputBufferPos = 0;
    for(int i = 0; i < iInputLen; i++)
    {
        if((iInputLen-i) % 3 == 0 && i != 0)
        {
            output[iOutputBufferPos++] = ',';
        }

        output[iOutputBufferPos++] = input[i];
    }

    output[iOutputBufferPos] = '\0';
}

呼び出し例:

char szBuffer[512];
pretty_number("1234567", szBuffer);
//strcmp(szBuffer, "1,234,567") == 0

-1
void printfcomma ( long long unsigned int n) 
{

    char nstring[100];
     int m;
      int ptr;
       int i,j;


    sprintf(nstring,"%llu",n);
      m=strlen(nstring);

     ptr=m%3;
       if (ptr)
        {   for (i=0;i<ptr;i++)       // print first digits before comma
              printf("%c", nstring[i]); 
           printf(",");
         }
     j=0; 
     for (i=ptr;i<m;i++)      // print the rest inserting commas
          {
            printf("%c",nstring[i]);
            j++;
            if (j%3==0)
              if(i<(m-1)) printf(",");
           }

}

1
コードを投稿するときは、少なくとも適切なインデントを使用してください。また、既存の回答ではまだ行われていない、これが何をするのかについての説明を追加するかもしれません。
EWit 2014

これは単純であるという利点があり、一目で簡単に理解できます。
スティーブニューマン2014

1
偽のソリューションは、余分に印刷し,、以下の番号については100、用途に飛んでいくのだ、名前、混沌インデントとあまりにも多くのコードを誤解用途。printf()putchar()
chqrlie 2015

-1
        // separate thousands
        int digit;
        int idx = 0;
        static char buffer[32];
        char* p = &buffer[32];

        *--p = '\0';
        for (int i = fCounter; i != 0; i /= 10)
        {
            digit = i % 10;

            if ((p - buffer) % 4 == 0)
                *--p = ' ';

            *--p = digit + '0';
        }

1
このコードにはさまざまな問題があります。未使用の変数idxが移動する可能性があります。このコードは0に対して何も生成しません。負の数は処理しません。変数を作成bufferする明確な理由はありませんstatic(コードの再入可能性を制限します)。それが何をするのかについての説明はなく、コードが完了した後、が指す文字列pにはフォーマットされた文字列が含まれていると述べられていません。最も深刻でない問題は、千単位の区切り文字としてコンマの代わりに空白を使用することです。ただし、ゼロを処理しないという事実は致命的な問題です。
ジョナサンレフラー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.