美好的一天,我正在进行哈希算法,所以我用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个字符。
答案 0 :(得分:2)
从哪里开始...
数据类型在C或C ++中没有固定的保证大小。因此,hash
可能会在每次迭代时溢出,或者它可能永远不会溢出。
char
可以是signed
或unsigned
,因此对于同一个字符,将一个转换为整数可能会在不同的实现上产生负值和正值。
在将final
的值打印到hash
时,您可能正在写strcat
。将第9个字符设置为0时,您可能也会过早地剪掉字符串。
final
长度至少为7个字符, str
将在s
的末尾写入。
temp
,一个相对短暂的临时变量,太快宣布了。与33*(0x40ACEF)*(0xFF)
相同。
您的代码看起来非常拥挤,几乎没有空白,并且很难阅读。
表达式“0x4DF48431L
”溢出;你的意思是std::string
吗?
在处理C ++中的字符串时,请考虑使用{{1}}而不是char数组。
答案 1 :(得分: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将在分配的内存之外。
不确定这是不是你的错,但它没有;看起来不错
答案 2 :(得分:1)
long hash
很可能仅限于您平台上的32位。 PHP的数字不是。
sprintf(final, "%x", hash)
会产生可能不正确的结果。 %x
将参数解释为unsigned int
,在Windows和Linux x64上均为32位。所以它将long
解释为unsigned int
,如果long
超过32位,则结果将被截断。
查看aib提出的所有问题。特别是结果提前终止。
你需要自己处理第3点,但我可以回答前两点。您需要将结果钳位到32位:$hash &= 0xFFFFFFFF;
。
如果你输入 final 值,php代码将产生与x64 Linux上的C ++代码相同的结果(这意味着64位整数用于中间结果)。
如果在每次计算后将其钳制,您应该得到与32位平台或Windows x64(中间结果的32位整数)上的C ++代码相同的结果。