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 时,您也可能会过早地切断字符串。

strcatfinal如果str至少有 7 个字符长,则会写到末尾。

s,一个相对短暂的临时变量,被声明得太早了。与 相同temp

您的代码看起来非常拥挤,几乎没有空格,而且很难阅读。

表达式“ 33*(0x40ACEF)*(0xFF)”溢出;你的意思是0x4DF48431L

std::string在 C++ 中处理字符串时,请考虑使用而不是 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,那么 size 将为 12 并且将分配 12 个字符。然后复制原始的 10 个字符,并添加 XQ,但最终终止的 \0 将在分配的内存之外。

不确定这是否是您的错误,但看起来不正确

于 2012-07-26T12:54:04.450 回答
1
  1. long hash在 C++ 中最有可能在您的平台上限制为 32 位。PHP 的数字不是。

  2. sprintf(final, "%x", hash)产生一个可能不正确的结果。%x将参数解释为unsigned int,在 Windows 和 Linux x64 上都是 32 位。因此,它将 a 解释longunsigned int,如果您long的长度超过 32 位,您的结果将被截断。

  3. 查看 aib 提出的所有问题。尤其是结果的提前终止。

你需要自己处理第三点,但我可以回答前两点。您需要将结果限制为 32 位:$hash &= 0xFFFFFFFF;.

如果您限制最终值,则 php 代码将产生与 x64 Linux 上的 C++ 代码相同的结果(这意味着中间结果为 64 位整数)。

如果在每次计算后对其进行钳制,您应该得到与 C++ 代码在 32 位平台或 Windows x64 上相同的结果(中间结果为 32 位整数)。

于 2012-07-26T14:19:23.113 回答