Как установить значение ввода по умолчанию в .Net Console App? - PullRequest
12 голосов
/ 31 октября 2009

Как установить значение ввода по умолчанию в консольном приложении .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);

Конечно, я не ожидаю, что это будет так просто. Я держу пари на том, что мне нужно делать что-то низкоуровневое, неуправляемое; Я просто не знаю как.

EDIT

Я знаю, что не могу заменить ввод по умолчанию. Это не то, о чем я спрашиваю. Я пытаюсь узнать, что связано с достижением описанного мной поведения: предоставление пользователю редактируемого значения по умолчанию. Я также не беспокоюсь о проверке входных данных; мой вопрос не имеет к этому никакого отношения.

Ответы [ 8 ]

8 голосов
/ 25 февраля 2011

Вот простое решение:

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 для полного описания.

7 голосов
/ 31 октября 2009

Я считаю, что вам придется управлять этим вручную, прослушивая каждое нажатие клавиши:

Пример быстрого объединения:

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

Это довольно сложно - вам нужно следить за тем, чтобы курсор не выходил за пределы диапазона, и вручную обновлять буфер.

4 голосов
/ 31 октября 2009

Или ... Просто проверьте введенное значение, если оно пустое, введите значение по умолчанию для ввода.

3 голосов
/ 07 мая 2018

Я пошел дальше и завершил подход к реализации Мэтта:

    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. ;)
1 голос
/ 12 июня 2014
  1. Добавить ссылку на библиотеку сборок "System.Windows.Forms" в ваш проект
  2. Добавьте SendKeys.SendWait ("DefaultText") сразу после команды Console.WriteLine и перед командой Console.ReadLine

string _weeklycost = "";
Console.WriteLine("Enter weekly cost: ");
System.Windows.Forms.SendKeys.SendWait("135");
_weeklycost = Console.ReadLine();
1 голос
/ 31 октября 2009

Простое решение, если пользователь ничего не вводит, назначьте значение по умолчанию:

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 coalescing :

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;
0 голосов
/ 06 февраля 2019

Есть гораздо лучший способ сделать это сейчас, посмотрите Readline на nuget: https://www.nuget.org/packages/ReadLine

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

Мне нравится использовать консоль для написания интерактивных тестов, и наличие значений по умолчанию действительно может помочь.

0 голосов
/ 31 октября 2009

Вы можете использовать вспомогательный метод следующим образом:

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