字符串数组中字符串(多个实例)的递归二进制搜索 - C#

Recursive binary search of string (multiple instances) in string array - C#

我正在尝试使用递归二进制搜索从字符串数组中搜索字符串的多个索引。但是,我的应用程序遇到了 Whosebugexception,并达到了断点。我做错了什么;我确实在脑海中播放了递归的流程,看起来确实不错,但我不知道为什么它不起作用。代码太多了吗?任何 alternative/solution/help 将不胜感激。

代码:

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;
        }
    }
}

输入:

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

预期 IO:如果我要搜索“Whosebug”,我应该同时获得输入 'Whosebug 3, 3' 和 'Whosebug 4, 4',反之亦然,但如前所述,它会溢出 smh。

考虑 first = 0last = 1 的情况。 (first + last) / 2) 变为 1 / 2,由于它是整数除法,结果是 0,如果您不想整数除法,请除以 2.0。零上限为零,假设 array[0] < item 我们用 last = middle + 1 再次调用该方法,即 1。因此该方法将再次使用相同的参数运行,最终导致堆栈溢出。

我不确定这是否正是您遇到的问题,代码很可能还有其他问题。这只是我发现的最明显的问题。

简单的解决方法是使用 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。这应该允许您逐步执行程序以获取一些示例输入,并检查每个步骤是否产生您期望的结果。作为新程序员,这是一项非常宝贵的技能。