【问题标题】:Catch user input error in real-time实时捕捉用户输入错误
【发布时间】:2018-06-29 12:40:42
【问题描述】:

我制作了这个简单的控制台应用程序,它要求用户输入用户名和密码。 然后将数据保存在 Db 中。对于 Db 中的每一列,我为数据类型分配了有限数量的值。例如,密码 (varchar(5)) 最多只能包含 5 个字符。

using System;

namespace MyConto
{
    public class NewUser
    {
        public static void NewUserRegistration()
        {
            Console.Write("Username: ");
            string user = Console.ReadLine();

            Console.Write("Password: ");
            string pass = Console.ReadLine();     
        }
    }
}

现在,我如何实时 (??) 检查用户在控制台中写入的内容?甚至有可能吗? 例如,如果用户输入"password" 作为密码,则警告用户字符串太长的消息。

谢谢

【问题讨论】:

  • if (pass?.Length > 5)
  • @mjwills 好的,但这会给用户他做错了的消息?我已经考虑过这一点,也考虑过尝试/捕获,但在控制台中看到很难看......
  • try/catch 总是丑陋的,如果可能的话你应该避免它。在您的情况下,它 可能的。只需检查是否提供了超过五个字符,如果是,则打印一条消息,例如使用Console.WriteLine("Too long")
  • but this will give the user the message that he is doing wrong ? 考虑使用Console.WriteLine 将消息写入最终用户。
  • 这个问题让我有点困惑。 OP 一直使用“实时”一词,对我来说,这表明他想在他们输入错误时进行检查。如果是这样,答案就变得很简单,不,这是不可能的。在按下回车键之前,Windows 命令 shell 不会评估命令行。

标签: c# .net error-handling user-input


【解决方案1】:

添加一个验证方法,如:

private bool isValid(string input)
{
   //my validation logic
}

并像这样使用:

  ...
string user = Console.ReadLine();
if (!isValid(user))
{
    ///my logic for warning the user that input is invalid
}
...

【讨论】:

    【解决方案2】:

    我假设“实时”是指您希望用户在看到消息之前按 ENTER - 所以只要他们输入第 6 个字符,它就会告诉他们这是太长。你不能用 Console.ReadLine() 来做这个你可以用 Console.ReadKey() 来做这个,虽然这很费力......但只是为了好玩:

    class Program
    {
        static void Main(string[] args)
        {
            //First clear the screen.  We need to have absolute knowledge of what's on 
            //the screen for this to work.
            Console.Clear();
            //hide the cursor as it has no real bearing on much....
            Console.CursorVisible = false;
            var user = GetLimitedInput("UserName?", 0, 10, true);
            var password = GetLimitedInput("Password?", 4, 5, false);
    
            Console.Clear();
            Console.WriteLine($"User is {user} and password is {password}");
        }
    
    
        private static string GetLimitedInput(string prompt, 
            int lineToShowPromptOn, int maxChars, bool showChars)
        {
            //set cursor to the suggested position
            Console.SetCursorPosition(0, lineToShowPromptOn);
            //output the prompt.
            Console.WriteLine(prompt);
            Console.SetCursorPosition(0, lineToShowPromptOn + 1);
    
            var finished = false;
            var inputText = string.Empty;
    
            while (!finished)
            {
                if (Console.KeyAvailable)
                {
                    //remembr old input so we can re-display if required.
                    var oldInput = inputText;
                    var key = Console.ReadKey();
                    //check for CTRL+C to quit
                    if (key.Modifiers.HasFlag(ConsoleModifiers.Control) && key.KeyChar=='c')
                    {
                        inputText = string.Empty;
                        finished = true;
                    }
                    //allow backspace
                    else if (key.KeyChar == '\b')
                    {
                        if (inputText.Length > 0)
                        {
                            inputText = inputText.Substring(0, inputText.Length - 1);
                        }
                    }
                    //check for return & finish if legal input.
                    else if (key.KeyChar == '\r')
                    {
                        if (inputText.Length<=maxChars)
                        {
                            finished = true;
                        }
                    }
                    else
                    {
                        //really we should check for other modifier keys (CTRL, 
                        //ALT, etc) but this is just example.
                        //Add text onto the input Text
                        inputText += key.KeyChar;
                    }
    
                    if (inputText.Length > maxChars)
                    {
                        //Display error on line under current input.
                        Console.SetCursorPosition(0, lineToShowPromptOn + 2);
                        Console.WriteLine("Too many characters!");
                    }
                    else
                    {
                        //if not currently in an 'error' state, make sure we
                        //clear any previous error.
                        Console.SetCursorPosition(0, lineToShowPromptOn + 2);
                        Console.WriteLine("                     ");
                    }
                    //if input has changed, then refresh display of input.
                    if (inputText != oldInput)
                    {
                        Console.SetCursorPosition(0, lineToShowPromptOn + 1);
                        //do we show the input?
                        if (showChars)
                        {
                            //We write it out to look like we're typing, and add 
                            //a bunch of spaces as otherwise old input may be        
                            //left there.
                            Console.WriteLine(inputText+"            ");
                        }
                        else
                        {
                            //show asterisks up to length of input.
                            Console.WriteLine(new String('*', inputText.Length)+"            ");
                        }
    
                    }
    
                }
            }
    
            return inputText;
        }       
    }
    

    注意:这有很多缺陷,但这只是为了说明目的:)

    【讨论】:

    • 这里和那里都有 cmets,非常适合教育目的。我不能只是复制粘贴它,但我肯定会在将来考虑它。干得好。
    • @Link - 我总是尝试在我放在任何地方的任何示例中评论为什么......否则它也无助于人们在附近的任何地方学习。我只是想我会把它放在一起来应对一个快速的小挑战......我不一定会推荐这种方法(非常重新发明轮子!),但如果你想在通过控制台应用程序输入时屏蔽密码,你'可能不得不做这样的事情。也就是说,如果某个地方没有一个库比我的破解示例更优雅地处理这个问题,我会感到惊讶!
    【解决方案3】:

    如果您想一直询问用户,直到他提供有效密码,您可以执行以下操作:

    string ObtainPassword()
    {
        string password;
        string passwordErrorMessage;
        while(true)
        {
            Console.Write("Password: ");
            password = Console.ReadLine();
            passwordErrorMessage = ValidatePassword(password);
            if (passwordErrorMessage == null)
                return password;
    
            Console.WriteLine($"\r\n*** {passwordErrorMessage}");
        }
    }
    

    密码验证方法如下:

    string ValidatePassword(string password)
    {
        if(password.Length > 5) return "Password is too long";
    
        //Add other validations here as needed
    
        return null;
    }
    

    【讨论】:

    • 如果密码为null,请考虑使用password?.Length
    • 其实 OP 想要验证密码是最大的。 5 个字符长,因为 db 中的列有 varchar(5)
    • @HimBromBeere 好的,这只是一个示例,但已修复,谢谢。
    • @HimBromBeere 我还对另一件事感到好奇:在 db 中我设置了 varchar(5)。但奇怪的是,即使用户输入了一个 pass long 10 chars 它也不会显示任何错误......也许我错过了一些东西......
    • 你还是要把error-message改成"Password is too long",哈哈。
    【解决方案4】:

    我最终得到了这个:

    using System;
    
    namespace MyConto
    {
        public class NewUser
        {
            public static void NewUserRegistration()
            {
                Console.Write("Username: ");
                string user = Console.ReadLine();
    
                Console.Write("Password: ");
                string pass = Console.ReadLine();
                while (pass.Length > 5)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("Insert a valid password (max 5 chars)\n");
                    Console.ForegroundColor = ConsoleColor.White;
                    Console.Write("Password: ");
                    pass= Console.ReadLine();
                }     
            }
        }
    }
    

    【讨论】:

    • 使用do { ... } while(),为pass调用一次ReadLine()
    • 另外,这将允许一个空密码 - 当然这可能是可取的,只是一个想法
    • 在密码为空的情况下考虑使用pass?.Length
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-31
    • 2010-12-05
    • 1970-01-01
    • 2010-10-15
    • 2013-10-12
    • 1970-01-01
    • 2020-04-02
    相关资源
    最近更新 更多