web-dev-qa-db-ja.com

Cで2つの整数を連結する方法

Stack Overflowでは、この質問に対して他の多くの言語で回答していますが、Cでは回答していません。

Cで2つの整数を連結する方法

例:

x = 11;
y = 11;

次のようにzをお願いします。

z = 1111;

他の例では、文字列を使用してこれを試みます。文字列なしでこれを行う方法は何ですか?

私の特定の使用法では、これがコードのタイムクリティカルな部分になるため、Cでこれを行う効率的な方法を探しています。

前もって感謝します!

17
010110110101
unsigned concatenate(unsigned x, unsigned y) {
    unsigned pow = 10;
    while(y >= pow)
        pow *= 10;
    return x * pow + y;        
}

コンパイル/正確さ/速度 の証明

log10関数とpow関数は使用しないでください。浮動小数点を使用し、速度が遅いと確信しているため、このmightお使いのマシンでより高速になります。多分。プロフィール。

37
Mooing Duck
z = x * pow(10, log10(y)+1) + y;

説明:

最初に、2番目に来る変数の桁数を取得します。

int digits = log10(y)+1;  // will be 2 in your example

次に、他の変数に10 ^ digitsを掛けて「シフト」します。

int shifted = x * pow(10, digits);   // will be 1100 in your example

最後に、2番目の変数を追加します。

z = shifted + y;   // 1111

または1行で:

z = x * pow(10, (int)log10(y)+1) + y;
9
DrummerB

これは最適または高速な解決策ではないかもしれませんが、誰もそれを言及しておらず、簡単な解決策であり、役に立つかもしれません。

sprintf()strtol()を使用できます。

char str[100];
int i=32, j=45;
sprintf(str, "%d%d", i, j);
int result=strtol(str, NULL, 10);

sprintf()を使用して文字列に数字を書き込み、次にprintf()を使用して標準出力に出力する場合と同様に、結果の文字列をstrtol()

strtol()longに格納できる値よりも大きい値になる可能性があるintを返すため、最初に結果の値を確認することをお勧めします。

int result;
long rv=strtol(str, NULL, 10);
if(rv>INT_MAX || rv<INT_MIN || errno==ERANGE)
{
    perror("Something went wrong.");
}
else
{
    result=rv;
}

strtol()によって返される値がintの範囲内にない場合(つまり、INT_MININT_MAXの間(を含む)ではない場合)、エラーが発生しました。 INT_MINおよびINT_MAXlimits.hからのものです。

文字列内のの値が大きすぎてlongで表現できない場合、errnoERANGEに設定されます(errno.hから)オーバーフローのため。

strtol()here について読んでください。

編集:

chqrlie による啓発的なコメントが指摘したように、負の数はこのアプローチで問題を引き起こすでしょう。

これまたはこれの修正を使用して、それを回避することができます

char str[100], temp[50];
int i=-32, j=45, result;
sprintf(temp, "%+d", j);
sprintf(str, "%d%s", i, temp+1);
long rv=strtol(str, NULL, 10);

最初に、2番目の数値をその記号とともに文字配列tempに出力します。

+%+dにより、数字の符号が出力されます。

ここで、最初の数値と2番目の数値をstrに出力しますが、2番目の数値の符号部分はありません。 tempの最初の文字を無視することにより、2番目の数値の符号部分をスキップします。

最後に、strtol()が完了しました。

2
J...S
int myPow(int x, int p)
{
     if (p == 0) return 1;
     if (p == 1) return x;

     int tmp = myPow(x, p/2);
     if (p%2 == 0) return tmp * tmp;
     else return x * tmp * tmp;
}
int power = log10(y);
z = x*myPow(10,power+1)+y;

ここで、私は恥知らずにmyPowを https://stackoverflow.com/a/1505791/119487 からコピーしました

2
Tae-Sung Shin

ここに別の方法があります:

int concat(int x, int y) {
    int temp = y;
    while (y != 0) {
        x *= 10;
        y /= 10;
    }
    return x + temp;
}

どんなパフォーマンスが得られるかを知っている人。試してみてください。

1
none

マクロを使用して文字列を連結することもできます(簡単な方法)

#include<stdio.h>
#define change(a,b) a##b
int main()
 {
    int y;
    y=change(12,34);
    printf("%d",y);
    return 0;
 }

欠点が1つあります。このメソッドで引数を渡すことはできません

1
Jot Singh

10の倍数のルックアップテーブルを使用する@Mooing Duckの回答のバリエーションは次のとおりです(遅い整数の乗算を使用するプラットフォームの場合)。無限ループに関するchqrlieのコメント。結合された入力が符号なしを超えないことが保証できる場合、それらは変更される可能性があります。

static const unsigned long long pow10s[] = {
   10,100,1000,10000,100000,1000000,10000000,100000000,1000000000,10000000000
};
unsigned long long concat(unsigned x, unsigned y) {
    const unsigned long long *p = pow10s;
    while (y >= *p) ++p;
    return *p * x +y;        
}
0
technosaurus

たぶんこれは動作します:

int x=11,y=11,temp=0;
int z=x;
while(y>0)
{
    // take reciprocal of y into temp
    temp=(temp*10)+(y%10);       
    y=y/10;
}
while(temp>0)
{
    // take each number from last of temp and add to last of z
    z=(z*10)+(temp%10);      
    temp=temp/10;
}

コードは長いですが、簡単です。間違いがある場合は私を修正してください。

0
Shabeer V P K