2013-06-12 107 views
0

我對這個模塊有很大的困難。 C版本輸出我想要的,但不是正確的值。我的C#輸出我不想要的,但是正確的值。我如何獲得C#版本以輸出C版本?Modulous錯誤幫助C C#

Ç

typedef unsigned long long u64; 
typedef unsigned char u8; 
static u64 pfd_calculate_hash_table_entry_index(const char *file_name) { 
    u64 hash, len, i; 

    if (!file_name) 
     return -1; 

    len = strlen(file_name); 
    hash = 0; 

    for (i = 0; i < len; ++i) 
     hash = (hash << 5) - hash + (u8)file_name[i]; 
    printf("%X ", hash); 
    printf("mod "); 
    printf("%X ", 0x39); 
    printf("= %X\n", hash % 0x39); 
    return hash % 0x39; 
} 

C#

public ulong pfd_calculate_hash_table_entry_index(char[] file_name) 
{ 
    uint hash, len, i; 
    hash = 0; 
    len = (uint)Array.IndexOf(file_name, '\0'); 
    for (i = 0; i < len; ++i) 
     hash = (hash << 5) - hash + (byte)file_name[i]; 
    MessageBox.Show(hash.ToString("X") + " mod 0x39 = " + (hash % 0x39).ToString("X")); 
    return ((ulong)hash % 0x39); 
} 

C#

#1: char[] file_name = "PARAM.SFO"; 
#2: char[] file_name = "RAGE.SAV" 

Ç

#1: char* file_name = "RAGE.SAV"; 
#2: char* file_name = "PARAM.SFO" 

Ç哈希ES

#1: 0x319FFDA7 
#2: 0x1A8C4B5B 

C#混編

#2: 0x319FFDA7 
#1: 0x1A8C4B5B 

C輸出

#1: 0x319FFDA7 % 0x39 = 0x21; 
#2: 0x1A8C4B5B % 0x39 = 0x8; 

C#輸出

#1: 0x319FFDA7 % 0x39 = 0xA; 
#2: 0x1A8C4B5B % 0x39 = 0xE; 

圖片...

Ç

http://puu.sh/3dT5L/52ababeccf.png

C#

http://puu.sh/3dT6P/62b911c102.png

+0

你應該能夠用一個簡短而完整的程序來重現這個問題,每個語言只是*使用一個硬編碼的值。在每種情況下,代碼的主體應該是大約5行。這將會更容易診斷。另外,我們不知道你實際上想要達到什麼 - *爲什麼*是你想要的結果?這意味着什麼? –

+1

這就是我的觀點:擺脫成千上萬行代碼,直到您可以在每種語言的*非常小的*程序中重現問題。你正在顯示的代碼*暗示着*這種模數算法在兩種語言中的工作方式不同。這應該是可以證明的,不需要參考其他代碼。試圖證明它可能會大量幫助你。有一點需要注意:您可能需要在C#代碼中使用'ulong',以匹配C代碼中的'u64'。 (我還指出,C#代碼在命名,變量聲明位置等方面是非慣用的) –

+0

我不明白爲什麼這應該是最好的,你可以簡化它。你應該能夠自己包含哈希。 *至少說*文件名是什麼,所以我們可以嘗試重現它。我強烈懷疑這裏唯一的問題是使用'uint'而不是'ulong',但是我不能複製它,因爲你沒有給我們足夠的信息。 –

回答

2

好。正如我想的那樣,這是C中的u64與C#中的uint之間不匹配的問題,然後C代碼中的錯誤診斷代碼會使其混淆。

這是很容易在很短,但完整的C#程序來演示:

using System; 

public class Test 
{ 
    static void Main() 
    { 
     ShowHash("PARAM.SFO"); 
     ShowHash("RAGE.SAV"); 
    } 

    static void ShowHash(string name) 
    { 
     uint hash = 0; 
     foreach (char c in name) 
     { 
      hash = (hash << 5) - hash + (byte) c; 
     } 
     Console.WriteLine("0x{0:X} mod 0x39 = {1:X}", hash, hash % 0x39); 
    } 
} 

輸出:

0x1A8C4B5B mod 0x39 = E 
0x319FFDA7 mod 0x39 = A 

變化hashuintulong類型,我們得到:

0x3FC01A8C4B5B mod 0x39 = 8 
0x21B319FFDA7 mod 0x39 = 21 

所以要得到合適的模數,你需要不要想要值0x1A8C4B5B - 你想要0x3FC01A8C4B5B。如果你已經寫了一個簡短但完整的C程序,它實際上是從0x1A8C4B5B開始的,你會發現它的結果與C#代碼相同。

另一點,這個代碼幾乎假設ASCII文件名......這絕對會對你有效嗎?

+0

這是ANSI,但是!謝啦!我猜%X只有32位而不是64位。解釋我的困難! + 1'd – user1594121

+0

@ user1594121:它可能是C代碼中的ANSI,但是在C#代碼中,您正在投射UTF-16代碼單元,因此您最終可能會獲得對於非ASCII字符的不同結果。 –