如何在.Net Console App中设置默认输入值?

发布于 2024-08-09 02:32:28 字数 416 浏览 2 评论 0原文

如何在 .net 控制台应用程序中设置默认输入值?

这是一些虚构的代码:

Console.Write("Enter weekly cost: ");
string input = Console.ReadLine("135"); // 135 is the default. The user can change or press enter to accept
decimal weeklyCost = decimal.Parse(input);

当然,我不希望它这么简单。我打赌必须做一些低级的、不受管理的事情;我只是不知道怎么办。

编辑

我知道我可以用默认值替换没有输入。我要问的不是这个。我正在尝试了解实现我所描述的行为所涉及的内容:为用户提供可编辑的默认值。我也不担心输入验证;我的问题与此无关。

How can you set a default input value in a .net console app?

Here is some make-believe code:

Console.Write("Enter weekly cost: ");
string input = Console.ReadLine("135"); // 135 is the default. The user can change or press enter to accept
decimal weeklyCost = decimal.Parse(input);

Of course, I don't expect it to be this simple. I am betting on having to do some low-level, unmanaged stuff; I just don't know how.

EDIT

I know I can replace no input with the default. That's not what I am asking about. I am trying to LEARN what's involved in achieving the behavior I described: giving the user an editable default. I'm also not worried about input validation; my question has nothing to do with that.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

萌逼全场 2024-08-16 02:32:28

我找到了一个完全符合您想要的解决方案。感谢 LagDaemon.ReadLine,它是Lunster 的回答中使用的包,我们可以这样做:

ReadLine.Send("default value");
var input = ReadLine.Read("Enter something: ");

Console.WriteLine("Received: " + input);
Thread.Sleep(-1);

展示:
GIF 显示如何使用此答案

此解决方案还支持 快捷方式,例如左右箭头,用于移动光标并在到达时处理文本溢出终端的右边框。

警告:此解决方案不会替换/扩展官方 Console.ReadLine 方法,仍应被视为“hacky”。

I have found a solution that does exactly what you want. Thanks to LagDaemon.ReadLine, which is a fork of package used in Lunster's answer, we can do this:

ReadLine.Send("default value");
var input = ReadLine.Read("Enter something: ");

Console.WriteLine("Received: " + input);
Thread.Sleep(-1);

Showcase:
GIF showing how you can use this answer

This solution also supports shortcuts like left and right arrow to move the cursor and handles text overflow when you reach the terminal's right border.

Warning: this solution does not replace/extend the official Console.ReadLine method and should still be considered as "hacky".

短暂陪伴 2024-08-16 02:32:28

我相信您将通过监听每个按键来手动管理此操作:

快速组合示例:

   // write the initial buffer
   char[] buffer = "Initial text".ToCharArray();
   Console.WriteLine(buffer);

   // ensure the cursor starts off on the line of the text by moving it up one line
   Console.SetCursorPosition(Console.CursorLeft + buffer.Length, Console.CursorTop - 1);

   // process the key presses in a loop until the user presses enter
   // (this might need to be a bit more sophisticated - what about escape?)
   ConsoleKeyInfo keyInfo = Console.ReadKey(true);
   while (keyInfo.Key != ConsoleKey.Enter)
   {

       switch (keyInfo.Key)
       {
            case ConsoleKey.LeftArrow:
                    ...
              // process the left key by moving the cursor position
              // need to keep track of the position in the buffer

         // if the user presses another key then update the text in our buffer
         // and draw the character on the screen

         // there are lots of cases that would need to be processed (backspace, delete etc)
       }
       keyInfo = Console.ReadKey(true);
   }

这非常复杂 - 您必须确保光标不会超出范围并手动更新缓冲区。

I believe that you will have manage this manually by listening to each key press:

Quickly thown together example:

   // write the initial buffer
   char[] buffer = "Initial text".ToCharArray();
   Console.WriteLine(buffer);

   // ensure the cursor starts off on the line of the text by moving it up one line
   Console.SetCursorPosition(Console.CursorLeft + buffer.Length, Console.CursorTop - 1);

   // process the key presses in a loop until the user presses enter
   // (this might need to be a bit more sophisticated - what about escape?)
   ConsoleKeyInfo keyInfo = Console.ReadKey(true);
   while (keyInfo.Key != ConsoleKey.Enter)
   {

       switch (keyInfo.Key)
       {
            case ConsoleKey.LeftArrow:
                    ...
              // process the left key by moving the cursor position
              // need to keep track of the position in the buffer

         // if the user presses another key then update the text in our buffer
         // and draw the character on the screen

         // there are lots of cases that would need to be processed (backspace, delete etc)
       }
       keyInfo = Console.ReadKey(true);
   }

This is quite involved - you'll have to keep ensure the cursor doesn't go out of range and manually update your buffer.

梦毁影碎の 2024-08-16 02:32:28

这是一个简单的解决方案:

public static string ConsoleReadLineWithDefault(string defaultValue)
{
    System.Windows.Forms.SendKeys.SendWait(defaultValue);
    return Console.ReadLine();
}

但是它并不完整。 SendWait 输入字符串中的某些字符具有特殊含义,因此您必须对它们进行转义(例如 +、(、) 等)
请参阅:http://msdn.microsoft.com/en -us/library/system.windows.forms.sendkeys.aspx 获取完整说明。

Here's a simple solution:

public static string ConsoleReadLineWithDefault(string defaultValue)
{
    System.Windows.Forms.SendKeys.SendWait(defaultValue);
    return Console.ReadLine();
}

It's not complete however. Some characters in the SendWait input string have special meaning so you have to escape them (eg. +, (, ), etc.)
See: http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.aspx for a complete description.

执笏见 2024-08-16 02:32:28

我继续完成了 Matt 的实现方法:

    public static string ReadInputWithDefault(string defaultValue, string caret = "> ")
    {
        Console.WriteLine(); // make sure we're on a fresh line

        List<char> buffer = defaultValue.ToCharArray().Take(Console.WindowWidth - caret.Length - 1).ToList();
        Console.Write(caret); 
        Console.Write(buffer.ToArray());
        Console.SetCursorPosition(Console.CursorLeft, Console.CursorTop);

        ConsoleKeyInfo keyInfo = Console.ReadKey(true);
        while (keyInfo.Key != ConsoleKey.Enter)
        {
            switch (keyInfo.Key)
            {
                case ConsoleKey.LeftArrow:
                    Console.SetCursorPosition(Math.Max(Console.CursorLeft - 1, caret.Length), Console.CursorTop);
                    break;
                case ConsoleKey.RightArrow:
                    Console.SetCursorPosition(Math.Min(Console.CursorLeft + 1, caret.Length + buffer.Count), Console.CursorTop);
                    break;
                case ConsoleKey.Home:
                    Console.SetCursorPosition(caret.Length, Console.CursorTop);
                    break;
                case ConsoleKey.End:
                    Console.SetCursorPosition(caret.Length + buffer.Count, Console.CursorTop);
                    break;
                case ConsoleKey.Backspace:
                    if (Console.CursorLeft <= caret.Length)
                    {
                        break;
                    }
                    var cursorColumnAfterBackspace = Math.Max(Console.CursorLeft - 1, caret.Length);
                    buffer.RemoveAt(Console.CursorLeft - caret.Length - 1);
                    RewriteLine(caret, buffer);
                    Console.SetCursorPosition(cursorColumnAfterBackspace, Console.CursorTop);
                    break;
                case ConsoleKey.Delete:
                    if (Console.CursorLeft >= caret.Length + buffer.Count)
                    {
                        break;
                    }
                    var cursorColumnAfterDelete = Console.CursorLeft;
                    buffer.RemoveAt(Console.CursorLeft - caret.Length);
                    RewriteLine(caret, buffer);
                    Console.SetCursorPosition(cursorColumnAfterDelete, Console.CursorTop);
                    break;
                default:
                    var character = keyInfo.KeyChar;
                    if (character < 32) // not a printable chars
                        break;
                    var cursorAfterNewChar = Console.CursorLeft + 1;
                    if (cursorAfterNewChar > Console.WindowWidth || caret.Length + buffer.Count >= Console.WindowWidth - 1)
                    {
                        break; // currently only one line of input is supported
                    }
                    buffer.Insert(Console.CursorLeft - caret.Length, character);
                    RewriteLine(caret, buffer);
                    Console.SetCursorPosition(cursorAfterNewChar, Console.CursorTop);
                    break;
            }
            keyInfo = Console.ReadKey(true);
        }
        Console.Write(Environment.NewLine);

        return new string(buffer.ToArray());
    }

    private static void RewriteLine(string caret, List<char> buffer)
    {
        Console.SetCursorPosition(0, Console.CursorTop);
        Console.Write(new string(' ', Console.WindowWidth - 1));
        Console.SetCursorPosition(0, Console.CursorTop);
        Console.Write(caret);
        Console.Write(buffer.ToArray());
    }

注意:

  • 仅适用于一行输入
  • 您可以定义可编辑文本区域之前的内容(caret 参数),
  • 使用风险自负,可能仍然存在一些问题IndexOutOfBound-问题。 ;)

I went ahead and completed Matt's implementation approach:

    public static string ReadInputWithDefault(string defaultValue, string caret = "> ")
    {
        Console.WriteLine(); // make sure we're on a fresh line

        List<char> buffer = defaultValue.ToCharArray().Take(Console.WindowWidth - caret.Length - 1).ToList();
        Console.Write(caret); 
        Console.Write(buffer.ToArray());
        Console.SetCursorPosition(Console.CursorLeft, Console.CursorTop);

        ConsoleKeyInfo keyInfo = Console.ReadKey(true);
        while (keyInfo.Key != ConsoleKey.Enter)
        {
            switch (keyInfo.Key)
            {
                case ConsoleKey.LeftArrow:
                    Console.SetCursorPosition(Math.Max(Console.CursorLeft - 1, caret.Length), Console.CursorTop);
                    break;
                case ConsoleKey.RightArrow:
                    Console.SetCursorPosition(Math.Min(Console.CursorLeft + 1, caret.Length + buffer.Count), Console.CursorTop);
                    break;
                case ConsoleKey.Home:
                    Console.SetCursorPosition(caret.Length, Console.CursorTop);
                    break;
                case ConsoleKey.End:
                    Console.SetCursorPosition(caret.Length + buffer.Count, Console.CursorTop);
                    break;
                case ConsoleKey.Backspace:
                    if (Console.CursorLeft <= caret.Length)
                    {
                        break;
                    }
                    var cursorColumnAfterBackspace = Math.Max(Console.CursorLeft - 1, caret.Length);
                    buffer.RemoveAt(Console.CursorLeft - caret.Length - 1);
                    RewriteLine(caret, buffer);
                    Console.SetCursorPosition(cursorColumnAfterBackspace, Console.CursorTop);
                    break;
                case ConsoleKey.Delete:
                    if (Console.CursorLeft >= caret.Length + buffer.Count)
                    {
                        break;
                    }
                    var cursorColumnAfterDelete = Console.CursorLeft;
                    buffer.RemoveAt(Console.CursorLeft - caret.Length);
                    RewriteLine(caret, buffer);
                    Console.SetCursorPosition(cursorColumnAfterDelete, Console.CursorTop);
                    break;
                default:
                    var character = keyInfo.KeyChar;
                    if (character < 32) // not a printable chars
                        break;
                    var cursorAfterNewChar = Console.CursorLeft + 1;
                    if (cursorAfterNewChar > Console.WindowWidth || caret.Length + buffer.Count >= Console.WindowWidth - 1)
                    {
                        break; // currently only one line of input is supported
                    }
                    buffer.Insert(Console.CursorLeft - caret.Length, character);
                    RewriteLine(caret, buffer);
                    Console.SetCursorPosition(cursorAfterNewChar, Console.CursorTop);
                    break;
            }
            keyInfo = Console.ReadKey(true);
        }
        Console.Write(Environment.NewLine);

        return new string(buffer.ToArray());
    }

    private static void RewriteLine(string caret, List<char> buffer)
    {
        Console.SetCursorPosition(0, Console.CursorTop);
        Console.Write(new string(' ', Console.WindowWidth - 1));
        Console.SetCursorPosition(0, Console.CursorTop);
        Console.Write(caret);
        Console.Write(buffer.ToArray());
    }

Notes:

  • Works for only one line of input
  • You can define what stands before the editable text area (caret parameter)
  • Use at your own risk, there may still be some IndexOutOfBound-problems. ;)
若水微香 2024-08-16 02:32:28

或者...只需测试输入的值,如果为空,则将默认值放入输入中。

Or... Just test the value entered, if it's empty put the default value in input.

合久必婚 2024-08-16 02:32:28

现在有更好的方法可以做到这一点,请查看 nuget 上的 Readlinehttps ://www.nuget.org/packages/ReadLine

  1. install-package Readline
  2. var input = ReadLine.Read("输入每周费用:", "135");< /code>

我喜欢使用控制台来编写交互式测试,并且使用默认值确实很有帮助。

There's a much better way to do this now, check out Readline on nuget: https://www.nuget.org/packages/ReadLine

  1. install-package Readline
  2. var input = ReadLine.Read("Enter weekly cost: ", "135");

I like to use the console to write interactive tests, and having default values can really help things.

猫腻 2024-08-16 02:32:28
  1. 将对程序集库“System.Windows.Forms”的引用添加到项目中 在
  2. Console.WriteLine 命令之后和 Console.ReadLine 命令之前添加 SendKeys.SendWait("DefaultText"

)

string _weeklycost = "";
Console.WriteLine("Enter weekly cost: ");
System.Windows.Forms.SendKeys.SendWait("135");
_weeklycost = Console.ReadLine();
  1. Add Reference to Assembly Library "System.Windows.Forms" to your Project
  2. Add SendKeys.SendWait("DefaultText") immediately after your Console.WriteLine command and before your Console.ReadLine command

 

string _weeklycost = "";
Console.WriteLine("Enter weekly cost: ");
System.Windows.Forms.SendKeys.SendWait("135");
_weeklycost = Console.ReadLine();
西瓜 2024-08-16 02:32:28

您可以使用这样的辅助方法:

public static string ReadWithDefaults(string defaultValue)
{
    string str = Console.ReadLine();
    return String.IsNullOrEmpty(str) ? defaultValue : str;
}

You can use helper method like this:

public static string ReadWithDefaults(string defaultValue)
{
    string str = Console.ReadLine();
    return String.IsNullOrEmpty(str) ? defaultValue : str;
}
傾旎 2024-08-16 02:32:28

简单的解决方案,如果用户没有输入任何内容,则分配默认值:

Console.Write("Enter weekly cost: ");
string input = Console.ReadLine();
decimal weeklyCost = String.IsNullOrEmpty(input) ? 135 : decimal.Parse(input);

在处理用户输入时,您应该预料到它可能包含错误。因此,如果用户未输入数字,您可以使用 TryParse 以避免异常:

Console.Write("Enter weekly cost: ");
string input = Console.ReadLine(); 
decimal weeklyCost;
if ( !Decimal.TryParse(input, out weeklyCost) ) 
    weeklyCost = 135;

这将被认为是处理用户输入的最佳实践。如果您需要解析许多用户输入,请使用辅助函数。一种方法是使用可空值的方法,如果解析失败则返回 null。然后使用 空合并运算符

public static class SafeConvert
{
    public static decimal? ToDecimal(string value)
    {
        decimal d;
        if (!Decimal.TryParse(value, out d))
            return null;
        return d;
    }
}

然后,读取输入并分配默认值就很简单:

decimal d = SafeConvert.ToDecimal(Console.ReadLine()) ?? 135;

Simple solution, if user inputs nothing, assign the default:

Console.Write("Enter weekly cost: ");
string input = Console.ReadLine();
decimal weeklyCost = String.IsNullOrEmpty(input) ? 135 : decimal.Parse(input);

When dealing with user inputs, you should expect that it might contain errors. So you could use TryParse in order to avoid an exception, if the user has not input a number:

Console.Write("Enter weekly cost: ");
string input = Console.ReadLine(); 
decimal weeklyCost;
if ( !Decimal.TryParse(input, out weeklyCost) ) 
    weeklyCost = 135;

This would be considered best-practice for handling user input. If you need to parse many user inputs, use a helper function for that. One way of doing it is to use a method with a nullable and return null if parsing failed. Then it is very easy to assign a default value using the null coalescing operator:

public static class SafeConvert
{
    public static decimal? ToDecimal(string value)
    {
        decimal d;
        if (!Decimal.TryParse(value, out d))
            return null;
        return d;
    }
}

Then, to read an input and assign a default value is as easy as:

decimal d = SafeConvert.ToDecimal(Console.ReadLine()) ?? 135;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文