Stack Overflowでは、この質問に対して他の多くの言語で回答していますが、Cでは回答していません。
Cで2つの整数を連結する方法
例:
x = 11;
y = 11;
次のようにzをお願いします。
z = 1111;
他の例では、文字列を使用してこれを試みます。文字列なしでこれを行う方法は何ですか?
私の特定の使用法では、これがコードのタイムクリティカルな部分になるため、Cでこれを行う効率的な方法を探しています。
前もって感謝します!
unsigned concatenate(unsigned x, unsigned y) {
unsigned pow = 10;
while(y >= pow)
pow *= 10;
return x * pow + y;
}
コンパイル/正確さ/速度 の証明
log10
関数とpow
関数は使用しないでください。浮動小数点を使用し、速度が遅いと確信しているため、このmightお使いのマシンでより高速になります。多分。プロフィール。
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;
これは最適または高速な解決策ではないかもしれませんが、誰もそれを言及しておらず、簡単な解決策であり、役に立つかもしれません。
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_MIN
とINT_MAX
の間(を含む)ではない場合)、エラーが発生しました。 INT_MIN
およびINT_MAX
はlimits.h
からのものです。
文字列内のの値が大きすぎてlong
で表現できない場合、errno
はERANGE
に設定されます(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()
が完了しました。
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 からコピーしました
ここに別の方法があります:
int concat(int x, int y) {
int temp = y;
while (y != 0) {
x *= 10;
y /= 10;
}
return x + temp;
}
どんなパフォーマンスが得られるかを知っている人。試してみてください。
マクロを使用して文字列を連結することもできます(簡単な方法)
#include<stdio.h>
#define change(a,b) a##b
int main()
{
int y;
y=change(12,34);
printf("%d",y);
return 0;
}
欠点が1つあります。このメソッドで引数を渡すことはできません
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;
}
たぶんこれは動作します:
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;
}
コードは長いですが、簡単です。間違いがある場合は私を修正してください。