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

Posted

技术标签:

【中文标题】字符串数组中字符串(多个实例)的递归二进制搜索 - C#【英文标题】:Recursive binary search of string (multiple instances) in string array - C# 【发布时间】:2021-12-17 02:27:36 【问题描述】:

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

代码:

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 → *** 3, 3
fourth set → *** 4, 4
fifth set → NoN-Existent, 69, 69

预期的 IO:如果我要搜索“***”,我应该得到输入 '*** 3, 3' 和 '*** 4, 4',反之亦然,但如前所述,它遇到了溢出 smh。

【问题讨论】:

【参考方案1】:

考虑first = 0last = 1 的情况。 (first + last) / 2) 变成 1 / 2,因为是整数除法,所以结果是 0,如果你不想整数除法,用 2.0 代替。零上限为零,假设array[0] &lt; item 我们再次使用last = middle + 1 调用该方法,即1。所以该方法会以相同的参数再次运行,最终导致堆栈溢出。

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

简单的解决方法是改用Array.BinarySearch,但我认为这是某种分配。如果是这种情况,我建议学习如何使用调试器,请参阅how to debug small programs。这应该允许您逐步通过程序获取一些示例输入,并检查每个步骤是否产生了您期望的结果。作为新程序员,这是一项非常宝贵的技能。

【讨论】:

以上是关于字符串数组中字符串(多个实例)的递归二进制搜索 - C#的主要内容,如果未能解决你的问题,请参考以下文章

错误 - 在反应搜索组件中呈现多个实例

使用递归搜索整数数组中元素的所有组合

如何创建一个实现递归二进制搜索的循环来搜索数组中的n个数字? JAVA

具有多个列表的递归排列

如何在字符串数组上使用二进制搜索

array_merge_recursive — 递归地合并一个或多个数组