【问题标题】:'Advanced' Console Application“高级”控制台应用程序
【发布时间】:2011-01-05 14:36:37
【问题描述】:

我不确定这个问题是否已在其他地方得到解答,我似乎无法通过谷歌找到任何不是“Hello World”示例的内容......我正在使用 C# .NET 4.0 进行编码。

我正在尝试开发一个控制台应用程序,它将打开、显示文本,然后等待用户输入命令,这些命令将运行特定的业务逻辑。

例如:如果用户打开应用程序并键入“帮助”,我想显示一些语句等。但我不确定如何为用户输入编写“事件处理程序”。

希望这是有道理的。任何帮助将非常感激! 干杯。

【问题讨论】:

  • 编写一个简单的应用程序,无论用户输入什么,它都会显示“Bad command”。然后发布您的代码,让您的问题更具体。
  • 我肯定会,但我真的没有任何代码,因为我不知道从哪里开始......

标签: c# event-handling console user-input


【解决方案1】:

您需要几个步骤来实现这一点,但这应该不难。首先,您需要某种解析器来解析您编写的内容。要读取每个命令,只需使用var command = Console.ReadLine(),然后解析该行。并执行命令......主要逻辑应该有一个看起来像这样(有点)的基础:

public static void Main(string[] args)
{
    var exit = false;
    while(exit == false)
    {
         Console.WriteLine();
         Console.WriteLine("Enter command (help to display help): "); 
         var command = Parser.Parse(Console.ReadLine());
         exit = command.Execute();
    }
}

有点,你可以把它改得更复杂。

Parser 和命令的代码有点简单:

public interface ICommand
{
    bool Execute();
}

public class ExitCommand : ICommand
{
    public bool Execute()
    {
         return true;
    }
}

public static Class Parser
{
    public static ICommand Parse(string commandString) { 
         // Parse your string and create Command object
         var commandParts = commandString.Split(' ').ToList();
         var commandName = commandParts[0];
         var args = commandParts.Skip(1).ToList(); // the arguments is after the command
         switch(commandName)
         {
             // Create command based on CommandName (and maybe arguments)
             case "exit": return new ExitCommand();
               .
               .
               .
               .
         }
    }
}

【讨论】:

  • 太好了,谢谢。这绝对是我正在寻找的东西
  • 对不起,这种情况下界面是如何工作的?我没有太多使用接口,所以这可能是我的问题......
  • 该接口只是指定一个ceratin对象应该有的方法。有了它,您可以定义几个从接口继承的不同对象,并让您的解析器为您创建这些对象。您可以将界面更改为您喜欢的任何方式,我只是用一个简单的Execute 来完成它,如果程序应该退出,它会返回true。我可以使用简单的命令和示例进行更新。
  • 谢谢...这个解决方案的一个好处是每个Command“生活”在他们自己的上下文中。因此,没有什么能阻止命令向用户提示更多问题。
  • 通过 Tomas 使用您的代码时,当我尝试构建它时,我收到一条错误消息,说我无法在静态类中声明类的实例 (ExitCommand)……有什么想法吗?
【解决方案2】:

我知道这是一个老问题,但我也在寻找答案。但是我找不到一个简单的,所以我构建了 InteractivePrompt。它以NuGet Package 的形式提供,您可以轻松扩展GitHub 上的代码。它还具有当前会话的历史记录。

问题中的功能可以通过 InteractivePrompt 以这种方式实现:

static string Help(string strCmd)
{
    // ... logic
    return "Help text";
}
static string OtherMethod(string strCmd)
{
    // ... more logic
    return "Other method";
}
static void Main(string[] args)
{
    var prompt = "> ";
    var startupMsg = "BizLogic Interpreter";
    InteractivePrompt.Run(
        ((strCmd, listCmd) =>
        {
            string result;
            switch (strCmd.ToLower())
            {
                case "help":
                    result = Help(strCmd);
                    break;
                case "othermethod":
                    result = OtherMethod(strCmd);
                    break;
                default:
                    result = "I'm sorry, I don't recognize that command.";
                    break;
            }

            return result + Environment.NewLine;
        }), prompt, startupMsg);
}

【讨论】:

    【解决方案3】:

    这很简单,只需使用Console.WriteLineConsole.ReadLine() 方法。从 ReadLine 你得到一个字符串。您可能有一个可怕的 if 语句来根据已知/预期的输入验证这一点。最好有一个查找表。最复杂的是编写一个解析器。这实际上取决于输入的复杂程度。

    【讨论】:

    • 但是使用 Console.ReadLine() 方法,然后我如何编码答案等的不同排列?例如 Console.ReadLine()、if(Console.ReadLine() == "help) { } 等
    【解决方案4】:

    Console.WriteLine Console.ReadLineConsole.ReadKey 是你的朋友。 ReadLine 和 ReadKey 等待用户输入。 string[] args 将包含您的所有参数,例如“帮助”。该数组是通过用空格分隔命令行参数来创建的。

    【讨论】:

      【解决方案5】:
      switch (Console.ReadLine())
      {
          case "Help":
              // print help
              break;
      
          case "Other Command":
              // do other command
              break;
      
          // etc.
      
          default:
              Console.WriteLine("Bad Command");
              break;
      }
      

      如果您要解析其中包含其他内容(例如参数)的命令,例如“manipulate file.txt”,那么仅此一项是行不通的。但是您可以例如使用String.Split 将输入分成命令和参数。

      【讨论】:

        【解决方案6】:

        一个样本:

            static void Main(string[] args)
            {
                Console.WriteLine("Welcome to test console app, type help to get some help!");
        
                while (true)
                {
                    string input = Console.ReadLine();
        
                    int commandEndIndex = input.IndexOf(' ');
        
                    string command = string.Empty;
                    string commandParameters = string.Empty;
        
                    if (commandEndIndex > -1)
                    {
                        command = input.Substring(0, commandEndIndex);
                        commandParameters = input.Substring(commandEndIndex + 1, input.Length - commandEndIndex - 1);
                    }
                    else
                    {
                        command = input;
                    }
        
                    command = command.ToUpper();
        
                    switch (command)
                    {
                        case "EXIT":
                            {
                                return;
                            }
                        case "HELP":
                            {
                                Console.WriteLine("- enter EXIT to exit this application");
                                Console.WriteLine("- enter CLS to clear the screen");
                                Console.WriteLine("- enter FORECOLOR value to change text fore color (sample: FORECOLOR Red) ");
                                Console.WriteLine("- enter BACKCOLOR value to change text back color (sample: FORECOLOR Green) ");
                                break;
                            }
                        case "CLS":
                            {
                                Console.Clear();
                                break;
                            }
        
                        case "FORECOLOR":
                            {
                                try
                                {
                                    Console.ForegroundColor = (ConsoleColor)Enum.Parse(typeof(ConsoleColor), commandParameters);
                                }
                                catch
                                {
                                    Console.WriteLine("!!! Parameter not valid");
                                }
        
                                break;
                            }
                        case "BACKCOLOR":
                            {
                                try
                                {
                                    Console.BackgroundColor = (ConsoleColor)Enum.Parse(typeof(ConsoleColor), commandParameters);
                                }
                                catch
                                {
                                    Console.WriteLine("!!! Parameter not valid"); 
                                }
        
                                break;
                            }
                        default:
                            {
                                Console.WriteLine("!!! Bad command");
                                break;
                            }
                    }
                }
            }
        

        【讨论】:

        • 这不是一个好的设计,因为你的函数正在做所有的工作。你应该分工,所以每个部分都有一个责任。
        • 我同意这一点,但我发现他正在寻找可以从中学习的代码,而且这并不太复杂。你是对的,逻辑应该分开。最后你和我的样本都给出了相同的结果。
        • 它最终肯定有相同的结果,但我不认为我的解决方案更复杂,重要的是你要学会如何以正确的方式做事......即使我的可能并不适合所有人,但设计是您应该考虑的事情。我什至认为我的解决方案更容易,因为当你阅读它时它更加“流畅”,如果你不需要它们,你可以跳过所有细节。在高层次上,它只是读取命令、解析命令并最后执行命令。也就是说,你可以跳过命令的解析方式和执行方式的细节。
        【解决方案7】:

        这非常简单,但可能满足您的需求。

        // somewhere to store the input
        string userInput="";
        
        // loop until the exit command comes in.
        while (userInput != "exit")
        {
            // display a prompt
            Console.Write("> ");
            // get the input
            userInput = Console.ReadLine().ToLower();
        
            // Branch based on the input
            switch (userInput)
            {
                case "exit": 
                  break;
        
                case "help": 
                {
                  DisplayHelp(); 
                  break;
                }
        
                case "option1": 
                {
                  DoOption1(); 
                  break;
                }
        
                // Give the user every opportunity to invoke your help system :)
                default: 
                {
                  Console.WriteLine ("\"{0}\" is not a recognized command.  Type \"help\" for options.", userInput);
                  break;
                }
            }
        }
        

        【讨论】:

          【解决方案8】:

          “tornerdo”有一个名为“ReadLine”的 C# nuget 包。语句ReadLine.Read(" prompt > ");CustomAutoCompletionHandler.PossibleAutoCompleteValues 提供的选项中提示用户。

          此外,您可以更改每个提示的CustomAutoCompletionHandler.PossibleAutoCompleteValues。这确保用户可以从可用\支持的选项列表中选择一个选项。不易出错。

          static void Main(string[] args)
          {
              Console.ForegroundColor = ConsoleColor.Cyan;
              Console.WriteLine(" Note! When it prompts, press <tab> to get the choices. Additionally, you can use type ahead search.");
              Console.ForegroundColor = ConsoleColor.White;
          
              // Register auto completion handler..
              ReadLine.AutoCompletionHandler = new CustomAutoCompletionHandler();
          
              CustomAutoCompletionHandler.PossibleAutoCompleteValues = new List<string> { "dev", "qa", "stg", "prd" };
              var env = CoverReadLine(ReadLine.Read("  Environment > "));
              Console.WriteLine($"Environment: {env}");
          }
          
          private static string CoverReadLine(string lineRead) => CustomAutoCompletionHandler.PossibleAutoCompleteValues.Any(x => x == lineRead) ? lineRead : throw new Exception($"InvalidChoice. Reason: No such option, '{lineRead}'");
                  
          public class CustomAutoCompletionHandler : IAutoCompleteHandler
          {
              public static List<string> PossibleAutoCompleteValues = new List<string> { };
          
              // characters to start completion from
              public char[] Separators { get; set; } = new char[] { ' ', '.', '/' };
          
              // text - The current text entered in the console
              // index - The index of the terminal cursor within {text}
              public string[] GetSuggestions(string userText, int index)
              {
                  var possibleValues = PossibleAutoCompleteValues.Where(x => x.StartsWith(userText, StringComparison.InvariantCultureIgnoreCase)).ToList();
                  if (!possibleValues.Any()) possibleValues.Add("InvalidChoice");
                  return possibleValues.ToArray();
              }
          }
          

          【讨论】:

            猜你喜欢
            • 2010-11-04
            • 1970-01-01
            • 1970-01-01
            • 2011-01-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-01-24
            • 2012-06-15
            相关资源
            最近更新 更多