2012-07-26 170 views
2

好日子,我正在做哈希algorthm,所以我正在从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++导致了字例: “嗨!” :053c81be 和PHP结果这个词:324C 053c81be

有谁知道,这里是错误,如何解决这个问题,无论是在PHP或CPP代码? 顺便说一句,当我在php结果中剪掉那些第一个字母时,我得到了C++结果,但它不会帮助,因为C++结果不是8个字符长,在某些情况下可能只有6个字符长。

+1

C++中的“long hash”很可能仅限于您平台上的32位。 PHP的号码不是。在'$ hash'的每次修改之后,尝试执行'$ hash =($ hash&0xFFFFFFFF);'。 – DCoder 2012-07-26 12:41:10

+0

@DCOder,nope,我在64位平台上得到了相同的结果。 – SingerOfTheFall 2012-07-26 12:43:18

+0

它的工作原理,但以防万一,当C + +哈希是8个字符长。 当它散列为“asdf”时,C++:20205e中的结果长度为6个字符,但在PHP中它的长度为9个字符:10020205e – jakubinf 2012-07-26 12:46:32

回答

1
  1. long hash是最有可能仅限于你的平台上32位。 PHP的号码不是。

  2. sprintf(final, "%x", hash)产生可能不正确的结果。 %x将参数解释为unsigned int,在Windows和Linux x64上均为32位。所以它会将long解释为unsigned int,如果您的long超过32位,您的结果将被截断。

  3. 查看由aib引发的所有问题。特别是结果的提前终止。

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

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

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

+0

谢谢,现在它工作:) – jakubinf 2012-07-26 14:27:37

2

从哪里开始?

数据类型不具有C或C++固定保证大小。因此,hash可能会在每次迭代时溢出,或者它可能永远不会。

char s可以是signedunsigned,因此,对于同一个字符,将one转换为整数可能导致不同实现上的负值和正值。

hash的值打印到final的末尾时,您可能会写入结尾。你也可能是第9个字符设置为0

strcat会写过去的final如果str结束的时候切串关过早地至少7个字符长。

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

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

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

在处理C++中的字符串时,考虑使用std::string而不是char数组。

+0

将char转换为int结果为负值,仅当char包含“非英文字符”时,我的意思是“ô”,“ň”,“ä”,“ö”,“č”等。 char * final =新char [(atleast 9)];是9个字符长,因为最大散列大小可以是8个字符+ \ 0字符 – jakubinf 2012-07-26 13:04:42

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将在分配的内存之外。

不知道如果这是你的错误或没有,但它不;吨C++看的权利

+0

是的,我已经修复它: int size =(strlen(str)+3),s = 0; \t if(size <= 6) \t \t size = 9; 但结果仍然相同。 – jakubinf 2012-07-26 13:06:42

相关问题