Home > Software engineering >  Recursive binary search of string (multiple instances) in string array - C#
Recursive binary search of string (multiple instances) in string array - C#

Time:11-03

Im trying to search for multiple indexes of strings using the recursive binary search from a string array. However, my application hit stackoverflowexception, and reached break point. What am I doing incorrectly; I did played out the flow of the recursiveness in my mind, it did seemed to be fine, but I have no idea why it was not working. Was there too much code? Any alternative/solution/help would be appreciated.

code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Security.Cryptography;
using System.Text.RegularExpressions;

namespace ProjectNumeroUno
{
    internal class Program
    {
        public static int BinSearch(int[] array, int first, int last, int item)
        {

            if (first <= last)
            {
                int middle = (int)Math.Ceiling((decimal)((first   last) / 2));
                if (array[middle] == item)
                    return middle;
                if (array[middle] > item)
                {
                    first = middle - 1;
                    return BinSearch(array, first, last, item);
                }
                if (array[middle] < item)
                {
                    last = middle   1;
                    return BinSearch(array, first, last, item);
                }
            }
            return -1;
        }
        static void Main(string[] args)
        {
            string path = @"D:\ytraddijyhcnuap.txt";
            string[] vs = { }, site = { }, usrnme = { }, pass = { };
            int[] num = { }, m = { };
            List<int> mList = new List<int>();
            List<int> numhList= new List<int>();
            List<string> list = new List<string>(vs.ToList());
            Console.Write("Welcome to your personal password database.\nData will be protected, and cannot be accessed directly.\nVery personalized and secure!\n\n1. New Data entry\n2. Display (latest → oldest) and search\n3. Clear password list\n4. Exit\nEnter your option: ");
            string option = Console.ReadLine();
            while (option != "4")
            {
                if (option == "1")
                {
                    Console.Write("Enter website: ");
                    string url = Console.ReadLine();
                    Console.Write("Enter username: ");
                    string usr = Console.ReadLine();
                    Console.Write("Enter password: ");
                    string pwd = Console.ReadLine();
                    string mmm = url   "Ψ"   usr   "Ψ"   pwd;
                    using (Aes Entry = Aes.Create())
                    {
                        Entry.Key = Encoding.Default.GetBytes(new string('j', 16));
                        Entry.IV = Encoding.Default.GetBytes(new string('j', 16));
                        byte[] encrypted = EncryptionOfContent(mmm, Entry.Key, Entry.IV);
                        using (StreamWriter sw = File.AppendText(path))
                        {
                            sw.WriteLine(Convert.ToBase64String(encrypted));
                        }
                    }
                }
                else if (option == "2")
                {
                    vs = new string[0];
                    Console.Write("\n");
                    try
                    {
                        var lineData = File.ReadAllLines(path);
                        foreach (var data in lineData)
                        {
                            using (Aes entry = Aes.Create())
                            {
                                entry.Key = Encoding.Default.GetBytes(new string('j', 16));
                                entry.IV = Encoding.Default.GetBytes(new string('j', 16));
                                string decrypted = DecryptionOfContent(Convert.FromBase64String(data), entry.Key, entry.IV);
                                list.Add(decrypted);
                            }
                        }
                        vs = list.ToArray();
                    }
                    catch (IOException e)
                    {
                        Console.WriteLine("The file could not be read due to:");
                        Console.WriteLine(e.Message);
                    }
                    num = new int[vs.Length];
                    site = new string[vs.Length];
                    usrnme = new string[vs.Length];
                    pass = new string[vs.Length];
                    m = new int[] { };
                    for (int i = 0; i < vs.Length; i  )
                    {
                        vs[i] = ((i   1)   "Ψ"   vs[i]);
                    }
                    for (int i = 0;i < vs.Length; i  )
                    {
                        string[] split = vs[i].Split('Ψ');
                        num[i] = int.Parse(split[0]);
                    }
                    for (int i = 0; i < num.Length - 1; i  )
                    {
                        int max = i;
                        for (int j = i   1; j < num.Length; j  )
                        {
                            if (num[j] > num[max])
                            {
                                max = j;
                            }
                        }
                        if (max != i)
                        {
                            int tempi = num[i];
                            var tempv = vs[i];
                            num[i] = num[max];
                            vs[i] = vs[max];
                            num[max] = tempi;
                            vs[max] = tempv;
                        }
                    }
                    for (int i = 0; i < vs.Length; i  )
                    {
                        string[] split = vs[i].Split('Ψ');
                        site[i] = split[1];
                        usrnme[i] = split[2];
                        pass[i] = split[3];
                    }
                    string A = "No.";
                    string B = "Site";
                    string C = "Username";
                    string D = "Password";
                    Console.WriteLine("{0,-10} {1,-20} {2,-20} {3,-0}", A, B, C, D);
                    for (int i = 0;i < vs.Length; i  )
                    {
                        Console.WriteLine("{0,-10} {1,-20} {2,-20} {3,-0}", num[i], site[i], usrnme[i], pass[i]);
                    }
                    Console.Write("\n");
                    Console.Write("Enter the website that you want to search: ");
                    string site2search = Console.ReadLine();
                    foreach (string s in site)
                    {
                        if (s == site2search)
                        {
                            mList.Add(Array.IndexOf(site, s));
                        }
                    }
                    m = mList.ToArray();
                    foreach (int s in m)
                    {
                        numhList.Add(BinSearch(num, 0, num.Length - 1, s   1));
                    }
                    int[] numh = numhList.ToArray();
                    Console.WriteLine("{0,-10} {1,-20} {2,-20} {3,-0}", A, B, C, D);
                    for (int i = 0; i < numh.Length; i  )
                    {
                        Console.WriteLine("{0,-10} {1,-20} {2,-20} {3,-0}", num[i], site[i], usrnme[i], pass[i]);
                    }
                    Console.Write("\n");
                }
                Console.Write("\n1. New Data entry\n2. Display (latest → oldest) and search\n3. Clear password list\n4. Exit\nEnter your option: ");
                option = Console.ReadLine();
            }
        }

        static byte[] EncryptionOfContent(string plainText, byte[] Key, byte[] IV)
        {
            // Check arguments.
            if (plainText == null || plainText.Length <= 0)
                throw new ArgumentNullException("plainText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("IV");
            byte[] encrypted;

            // Create an Aes object
            // with the specified key and IV.
            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                // Create an encryptor to perform the stream transform.
                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

                // Create the streams used for encryption.
                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {
                            //Write all data to the stream.
                            swEncrypt.Write(plainText);
                        }
                        encrypted = msEncrypt.ToArray();
                    }
                }
            }

            // Return the encrypted bytes from the memory stream.
            return encrypted;
        }

        static string DecryptionOfContent(byte[] cipherText, byte[] Key, byte[] IV)
        {
            // Check arguments.
            if (cipherText == null || cipherText.Length <= 0)
                throw new ArgumentNullException("cipherText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("IV");

            // Declare the string used to hold
            // the decrypted text.
            string plaintext = null;

            // Create an Aes object
            // with the specified key and IV.
            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                // Create a decryptor to perform the stream transform.
                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

                // Create the streams used for decryption.
                using (MemoryStream msDecrypt = new MemoryStream(cipherText))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {

                            // Read the decrypted bytes from the decrypting stream
                            // and place them in a string.
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }
            }
            return plaintext;
        }
    }
}

input:

first set → google, 1, 1
second set → google 2, 2
third set → stackoverflow 3, 3
fourth set → stackoverflow 4, 4
fifth set → NoN-Existent, 69, 69

Expected IO: if I were to search "stackoverflow", I should get both the inputs 'stackoverflow 3, 3' and 'stackoverflow 4, 4', and vice versa, but as said, it hit overflow smh.

CodePudding user response:

Consider the case where first = 0 and last = 1. (first last) / 2) becomes 1 / 2, and since it is integer division the result is 0, if you do not want integer division, divide by 2.0 instead. Ceiling of zero is zero, and assuming array[0] < item we call the method again with last = middle 1, i.e. 1. So the method will run again with identical parameters, eventually causing a stack overflow.

I'm not sure this is exactly the issue you are having, It is perfectly possible that there are other issues with the code. This was just the most obvious issue I spotted.

The easy fix would be to use Array.BinarySearch instead, but I would assume this is some kind of assignment. If that is the case I would suggest learning how to use the debugger, see how to debug small programs. This should allow you to step thru the program for some example input, and check that each step produces the result you expect it to. This is an invaluable skill to learn as a new programmer.

  • Related