How can you set a default input value in a .net console app?
如何在.net控制台应用程序中设置默认输入值?
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.
我知道我可以用默认值替换没有输入。这不是我要问的问题。我试图了解实现我所描述的行为所涉及的内容:为用户提供可编辑的默认值。我也不担心输入验证;我的问题与此无关。
7 个解决方案
#1
6
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.
这非常复杂 - 您必须确保光标不会超出范围并手动更新缓冲区。
#2
6
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.
但它并不完整。 SendWait输入字符串中的某些字符具有特殊含义,因此您必须转义它们(例如。+,(,)等)请参阅:http://msdn.microsoft.com/en-us/library/system.windows。 forms.sendkeys.aspx获取完整说明。
#3
4
Or... Just test the value entered, if it's empty put the default value in input.
或者......只测试输入的值,如果它为空则将默认值输入输入。
#4
2
- Add Reference to Assembly Library "System.Windows.Forms" to your Project
- Add SendKeys.SendWait("DefaultText") immediately after your Console.WriteLine command and before your Console.ReadLine command
将程序集库“System.Windows.Forms”的引用添加到项目中
在Console.WriteLine命令之后和Console.ReadLine命令之前立即添加SendKeys.SendWait(“DefaultText”)
string _weeklycost = "";
Console.WriteLine("Enter weekly cost: ");
System.Windows.Forms.SendKeys.SendWait("135");
_weeklycost = Console.ReadLine();
#5
1
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:
处理用户输入时,您应该预期它可能包含错误。因此,如果用户没有输入数字,您可以使用TryParse来避免异常:
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:
这将被视为处理用户输入的最佳实践。如果需要解析许多用户输入,请使用辅助函数。一种方法是使用一个可以为null的方法,如果解析失败则返回null。然后使用空合并运算符分配默认值非常容易:
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;
#6
0
You can use helper method like this:
您可以使用这样的帮助方法:
public static string ReadWithDefaults(string defaultValue)
{
string str = Console.ReadLine();
return String.IsNullOrEmpty(str) ? defaultValue : str;
}
#7
0
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. ;)
仅适用于一行输入
您可以定义可编辑文本区域之前的内容(插入符号参数)
使用风险自负,可能仍存在一些IndexOutOfBound问题。 ;)
#1
6
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.
这非常复杂 - 您必须确保光标不会超出范围并手动更新缓冲区。
#2
6
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.
但它并不完整。 SendWait输入字符串中的某些字符具有特殊含义,因此您必须转义它们(例如。+,(,)等)请参阅:http://msdn.microsoft.com/en-us/library/system.windows。 forms.sendkeys.aspx获取完整说明。
#3
4
Or... Just test the value entered, if it's empty put the default value in input.
或者......只测试输入的值,如果它为空则将默认值输入输入。
#4
2
- Add Reference to Assembly Library "System.Windows.Forms" to your Project
- Add SendKeys.SendWait("DefaultText") immediately after your Console.WriteLine command and before your Console.ReadLine command
将程序集库“System.Windows.Forms”的引用添加到项目中
在Console.WriteLine命令之后和Console.ReadLine命令之前立即添加SendKeys.SendWait(“DefaultText”)
string _weeklycost = "";
Console.WriteLine("Enter weekly cost: ");
System.Windows.Forms.SendKeys.SendWait("135");
_weeklycost = Console.ReadLine();
#5
1
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:
处理用户输入时,您应该预期它可能包含错误。因此,如果用户没有输入数字,您可以使用TryParse来避免异常:
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:
这将被视为处理用户输入的最佳实践。如果需要解析许多用户输入,请使用辅助函数。一种方法是使用一个可以为null的方法,如果解析失败则返回null。然后使用空合并运算符分配默认值非常容易:
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;
#6
0
You can use helper method like this:
您可以使用这样的帮助方法:
public static string ReadWithDefaults(string defaultValue)
{
string str = Console.ReadLine();
return String.IsNullOrEmpty(str) ? defaultValue : str;
}
#7
0
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. ;)
仅适用于一行输入
您可以定义可编辑文本区域之前的内容(插入符号参数)
使用风险自负,可能仍存在一些IndexOutOfBound问题。 ;)