0

I have a project where I have to create my own linear hash, bucket hash and quadratic hash algorithms, so I choose to hash some strings, but I've run into a little problem where I have 2 ListBoxes:

  • A ListBox full of strings
  • A ListBox full of the hashes of those strings

I can print the strings without any problems, but I can't figure out how to print their corresponding hashes into the other ListBox when I click on a button.

Here's my code:

Form.cs

private void btnLinearHash_Click(object sender, EventArgs e)
{
    // Initialize Hash.cs (see below for code)
    Hash.LinearHash linearHash = new Hash.LinearHash();
    RandomArrayGen randGen = new RandomArrayGen();

    // Clear both ListBoxes
    lbHashStrings.Items.Clear();
    lbHashesOfStrings.Items.Clear();

    for (int i = 0; i < 12; i++)
    {
        // Generate 12 random upper and lowercase strings using RandomArrayGen.cs (see https://pastebin.com/jRsG5r1E)
        lbHashStrings.Items.Add(randGen.GenRandomStrings(12, true, true));
    }

    for (int i = 0; i < lbHashStrings.Items.Count; i++)
    {
    // Generate a hash of a string and store it into a Dictionary (see Hash.cs)
    linearHash.GenerateHashOfString(lbHashStrings.Items[i].ToString());
    lbHashesOfStrings.Items.Add(linearHash.FindHashCodeInDictionary(lbHashStrings.Items[i].ToString()));
    }
}

Hash.cs

    public class LinearHash
    {
        private Dictionary<byte[], string> linearHashArray = new Dictionary<byte[], string>();
        private byte[] hashCode;

        public void GenerateHashOfString(string stringToHash)
        {
            hashCode = Encoding.ASCII.GetBytes(stringToHash);

            linearHashArray.Add(hashCode, stringToHash);
        }

        public string FindHashCodeInDictionary(string StringToFind)
        {
            byte[] HashOfStringToFind = Encoding.ASCII.GetBytes(StringToFind);

            //For some reason, this keeps returning false
            foreach (var keyPairValue in linearHashArray)
            {
                if ((linearHashArray.ContainsKey(HashOfStringToFind) && linearHashArray.ContainsValue(StringToFind))
                {
                    return Encoding.UTF8.GetString(HashOfStringToFind);
                }
            }
            return "Hash not found";
        }
    }

So, my question is: What am I doing wrong? Why is the foreach in Hash.cs returning false?

Rutger
  • 1
  • 3
  • You're looking in a dictionary for a match, have you checked that its actually there by breaking your code at the "findhashcodeindictonary" portion? – BugFinder Apr 05 '17 at 12:15
  • If you try to use `Equals` to compare two byte arrays, it will do a reference comparison, not a contents comparison. Since the two arrays are separate in memory, they have different references. – Matthew Watson Apr 05 '17 at 12:17
  • @BugFinder: Yes. Both the string and the hash I look for can be found in the dictionary. – Rutger Apr 05 '17 at 12:18
  • @MatthewWatson: I see. How can I solve this? I tried this: `if ((linearHashArray.ContainsKey(HashOfStringToFind) && linearHashArray.ContainsValue(StringToFind)))` – Rutger Apr 05 '17 at 12:25
  • Why would you rehash and compare, not just look up the hashed string? it would make your code way simpler – BugFinder Apr 05 '17 at 12:36
  • Yes, the "hash code" isn't a hash code at all. Hash codes imply the possibility of two items generating the same hash code. You are effectively just storing the string in a different format - so why not just store the string? What are you trying to achieve here? – Matthew Watson Apr 05 '17 at 12:38
  • @BugFinder: I'm hashing a string to see if the generated hash is a key in the dictionary, if it is, I want to retrieve the string (i.e. the value) of it. – Rutger Apr 05 '17 at 12:44
  • @MatthewWatson: I have a project where I have to create my own linearhash, bucket hash and quadratic hash algorithms, so I need to hash something to test it out. – Rutger Apr 05 '17 at 12:44
  • Well just use `string.GetHashCode()` to test it - but you will need to change your code to account for collisions! – Matthew Watson Apr 05 '17 at 12:47
  • @MatthewWatson: The main reason why I didn't use `string.GetHashCode()` is to prevent collisions. I read that hashing a string into `byte[]` would solve this issue, but comparing a string to a value in a dictionary is more challenging that I though, but my C# knowledge is sort off limited, so I'm sure I'm doing something wrong here. – Rutger Apr 05 '17 at 12:51
  • What happens when the click function is called? Does lbHashStrings get updated correctly? Does lbHashesOfStrings remain empty? Or do you get exceptions? If lbHashesOfStrings is still empty, does the code in the second loop get executed at all? – steeveeet Apr 05 '17 at 17:51
  • @steeveeet: lbHashStrings works perfectly, but lbHashesOfStrings returns "Hash not found", even though it should return true and enter the foreach loop, mainly because the key and value match. I'm lost as to why the foreach loop won't return true... – Rutger Apr 05 '17 at 19:42

1 Answers1

0

I solved my issue by converting the Byte[] using BitConverter.ToString(hashToConvert).Replace("-", string.Empty);.

Hash.cs

    public void GenerateHashOfString(string stringToHash)
    {
        hashCode = Encoding.ASCII.GetBytes(stringToHash);
    ==> hashCodeInStringForm = BitConverter.ToString(hashCode).Replace("-", string.Empty);

        linearHashArray.Add(hashCode, stringToHash);
    }

    public string FindHashCodeInDictionary(string StringToFind)
    {
    byte[] HashOfStringToFind = Encoding.ASCII.GetBytes(StringToFind);

    foreach (var hashCode in linearHashArray)
    {
        if (!linearHashArray.ContainsKey(HashOfStringToFind) && !linearHashArray.ContainsValue(StringToFind))
        {
        return "String and hash not found in array";
        }
    }
    return hashCodeInStringForm;
    }
Rutger
  • 1
  • 3