2

こんにちは、私はハッシュアルゴリズムを作成しているので、PHP から C++ に書き直しています。しかし、C++ の結果は php の結果とは異なります。PHP の結果には 10 文字を超える文字が含まれていますが、C++ の結果には 6 ~ 8 文字しか含まれていません。しかし、PHP の結果の最後の 8 文字は C++ の結果と同じです。だからここにPHPコードがあります:

<?php function JL1($text) { 
$text.="XQ";
$length=strlen($text);
$hash=0;        
for($j=0;$j<$length;$j++) {
    $p=$text[$j];
    $s=ord($p);
    if($s%2==0) $s+=9999;
    $hash+=$s*($j+1)*0x40ACEF*0xFF;                         
}       
$hash+=33*0x40ACEF*0xFF;
$hash=sprintf("%x",$hash);
return $hash; } ?>

そしてここに C++ コード:

char * JL1(char * str){
int size=(strlen(str)+3),s=0; //Edit here (+2 replaced with +3)
if(size<=6) //Edit here (<9 replaced with <=6)
    size=9;
char *final=new char[size],temp;
strcpy(final,str);
strcat(final,"XQ");
long length=strlen(final),hash=0L;
for(int i=0;i<length;i++){
    temp=final[i];
    s=(int)temp;    
    if(s%2==0)s+=9999;
    hash+=((s)*(i+1)*(0x40ACEF)*(0xFF));
}
hash+=33*(0x40ACEF)*(0xFF);
sprintf(final,"%x",hash); //to hex string
final[8]='\0';
return final; }

単語に対する C++ の結果の例: "Hi!" : 053c81be この単語に対する PHP の結果: 324c 053c81be

その間違いはどこにあり、それを修正する方法は、phpであろうとcppコードであろうと、誰にも分かりますか? ちなみに、PHP の結果の最初の文字を切り取ると、C++ の結果が得られますが、C++ の結果は 8 文字である必要はなく、場合によっては 6 文字になることがあるため、役に立ちません。

4

3 に答える 3

2

どこから始めれば...

C または C++ では、データ型の固定サイズが保証されていません。そのため、hash反復ごとにオーバーフローするか、まったくオーバーフローしない可能性があります。

chars は または のいずれsignedunsignedになります。したがって、1 を整数に変換すると、同じ文字に対して、異なる実装では負の値と正の値になる場合があります。

finalの値を出力するときに、 の末尾を超えて書き込んでいる可能性がありますhash。また、9 番目の文字を 0 に設定すると、文字列が途中で切断される可能性があります。

strcat長さが 7 文字以上のfinal場合は、末尾を超えて書き込みます。str

sは比較的短命の一時変数であり、あまりにも早く宣言されます。と同じtemp

あなたのコードは空白がほとんどなく非常に混み合っており、非常に読みにくいです。

式 " 33*(0x40ACEF)*(0xFF)" がオーバーフローします。ということ0x4DF48431Lですか?

std::stringC++ で文字列を処理する場合は、char 配列の代わりに使用することを検討してください。

于 2012-07-26T12:53:10.857 に答える
1

ここにバグがあるようです...

int size=(strlen(str)+2),s=0; 
if(size<9)     
    size=9; 
char *final=new char[size],temp; 
strcpy(final,str); 
strcat(final,"XQ");

strlen が 10 の場合、サイズは 12 になり、12 文字が割り当てられます。次に、元の 10 文字をコピーして XQ を追加しますが、最後の終端の \0 は割り当てられたメモリの範囲外になります。

それがあなたのバグかどうかはわかりませんが、正しく見えません

于 2012-07-26T12:54:04.450 に答える
1
  1. long hashC++ では、プラットフォーム上で 32 ビットに制限されている可能性があります。PHPの番号はそうではありません。

  2. sprintf(final, "%x", hash)誤った結果になる可能性があります。これは、Windows と Linux x64 の両方で 32 ビットです%xunsigned intしたがって、 alongを として解釈していunsigned intますlong。32 ビットを超える場合、結果は切り捨てられます。

  3. aib によって提起されたすべての問題を参照してください。特に結果の早期終了。

3 点目はご自身で対応していただく必要がありますが、最初の 2 点についてはお答えできます。結果を 32 ビットにクランプする必要があります$hash &= 0xFFFFFFFF;

最終値をクランプすると、php コードは、x64 Linux での C++ コードと同じ結果を生成します (つまり、中間結果の 64 ビット整数を意味します)。

すべての計算の後にクランプすると、32 ビット プラットフォームまたは Windows x64 で C++ コードと同じ結果が得られるはずです (中間結果の 32 ビット整数)。

于 2012-07-26T14:19:23.113 に答える