C# 在C控制台应用程序中,如何允许用户从行的开头输入?

C# 在C控制台应用程序中,如何允许用户从行的开头输入?,c#,input,user-input,C#,Input,User Input,我知道我可以使用Console.ReadLine来允许用户输入,但它只允许用户从光标所在的位置输入,我希望有一种方法能够允许用户从整行的开始输入,而不仅仅是从光标所在的位置输入。例如: for (int i = 1;i <= 5;i++) Console.Write(i+" "); string x = Console.ReadLine(); 其中‘‘’指的是光标,这样,用户将只能从光标位置进行书写-他不能使用backspace删除前面的字符。那么,当光标不在行的开头时,如何允许用户在整

我知道我可以使用Console.ReadLine来允许用户输入,但它只允许用户从光标所在的位置输入,我希望有一种方法能够允许用户从整行的开始输入,而不仅仅是从光标所在的位置输入。例如:

for (int i = 1;i <= 5;i++) Console.Write(i+" ");
string x = Console.ReadLine();
其中‘‘’指的是光标,这样,用户将只能从光标位置进行书写-他不能使用backspace删除前面的字符。那么,当光标不在行的开头时,如何允许用户在整行上输入?

您可以使用Console.CursorLeft=0;为了这个。与Console.SetCursorPosition相比的优点是,您不必计算y坐标,因此光标将保持在当前行中

我想举一个例子,在这两种情况下,我们都希望光标指向行的开头:

Console.SetCursorPosition(0, Console.CursorTop); //With SetCursorPosition
Console.CursorLeft = 0; //With CursorLeft

但是,我认为没有一种优雅的方式可以让用户删除程序编写的字符。您仍然可以不断检查用户是否按下Backshift,然后删除最后一个字符并将光标移回,同时您必须异步检查这一点,这将不会产生一个好的解决方案。

这是一个具有自定义输入处理的现成示例。 当然,这需要对性能进行一些调整,但它应该让您知道从哪里开始

    static void Main(string[] args)
    {
        List<char> outputString = new List<char>();
        outputString = "test".ToCharArray().ToList();
        //If there is something in outputString write it to buffer and set cursor position
        if (outputString.Count > 0)
        {
            Console.Write(outputString.Select(x => x.ToString()).Aggregate((x, y) => x + y));
        }

        while (true)
        {
            //This will read user input but it will not print it to the console window 
            var key = Console.ReadKey(true);
            //Allow user maniputate cursor to the right
            //Here you can add another condition to prevent line overflow or some constrains
            //if(Console.CursorLeft < 30)
            if (key.Key == ConsoleKey.RightArrow && Console.CursorLeft < outputString.Count)
            {
                Console.SetCursorPosition(Console.CursorLeft + 1, Console.CursorTop);
            }
            else if (key.Key == ConsoleKey.LeftArrow && Console.CursorLeft > 0)
            {
                Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
            }
            //Here you should add all keys that your input should take, special characters are ok above ASCII number 32 which is space
            else if (key.KeyChar >= 48 && key.KeyChar <= 57 || //Read numbers
                key.KeyChar >= 64 && key.KeyChar <= 90 || //Read capital letters
                key.KeyChar >= 97 && key.KeyChar <= 122 || //Read lower letters
                key.Key == ConsoleKey.Spacebar)
            {
                Console.Write(key.KeyChar);
                if(Console.CursorLeft > outputString.Count)
                {
                    outputString.Add(' ');
                }
                outputString[Console.CursorLeft - 1] = key.KeyChar;
            }
            //This will remove character
            else if (key.Key == ConsoleKey.Backspace && Console.CursorLeft > 1)
            {
                ClearCurrentConsoleLine();
                outputString.RemoveAt(Console.CursorLeft - 1);
                var currentLeft = Console.CursorLeft;
                Console.CursorLeft = 0;
                Console.Write(outputString.Select(x => x.ToString()).Aggregate((x,y) => x + y));
                Console.CursorLeft = currentLeft - 1;
            }
            //This ends input loop
            //You can add more keys to break current loop with OR condition
            else if (key.Key == ConsoleKey.Enter)
            {
                break;
            }
        }
        //Display result and wait for any key
        Console.WriteLine(outputString.Select(x => x.ToString()).Aggregate((x, y) => x + y));
        Console.ReadKey();
    }

    //Clears current console line and sets cursor at where it was before
    public static void ClearCurrentConsoleLine()
    {
        int currentLineCursorTop = Console.CursorTop;
        int currentLineCursorLeft = Console.CursorLeft;
        Console.SetCursorPosition(0, Console.CursorTop);
        Console.Write(new string(' ', Console.WindowWidth));
        Console.SetCursorPosition(currentLineCursorLeft, currentLineCursorTop);
    }

但是OP不想移动光标。他们希望光标保持在正确的位置,但只允许用户自己将光标移动到开始位置的左侧。@Servy保持冷静,我正在编辑此答案。如果您还没有写完答案,则不应发布它。只有当你觉得你的答案已经准备好接受评估时,才发布你的答案。也就是说,你的编辑没有解决它的问题;答案根本无法回答问题。事实上,在对问题进行编辑之前,我很确定我的答案与问题相符。@MetaColon感谢您的回答,但正如Servy所说,我不想移动光标,我想让它保持原样,但允许用户从那一点开始输入,在它之前。C shell并不是真正设计成开箱即用的。非常确定的是,您只需在控制台中读取输入,每次输入一个键,并在用户按下箭头键、退格键等时自行处理移动光标。你最好简单地调整你的用户界面;要么使用更适合控制台应用程序的UI,要么使用真正为更复杂的用户交互而设计的非控制台UI。@一次读取一个键当然是最接近的解决方案,但处理将这些值存储在数组或列表中会更加复杂,因为这不像简单的“一刀切”控制台。ReadLine,它在用户输入完值后开始处理这些值,因此它可以看到整行内容,而不是距离当前光标位置的一个字符您希望编写自己的方法来完成所有需要的工作,并在完成时返回字符串,以便调用方可以调用该方法并获取字符串。不过,编写这样一种方法确实需要很多工作。这就是为什么我说你应该避免解决这个问题。太好了!在这种情况下,它完美地处理了用户输入,但是在按下Enter键之后,有没有一种方法可以读取整行内容来开始处理用户输入的内容,甚至是在输入过程的开始?就像Console.ReadLine所做的一样,将整行数据存储在字符串中后,读取整行数据以在下一个操作中开始处理它。整个数据位于outputString变量中,该变量是字符列表。要将其转换为纯字符串,您需要像我在每个writeline方法之前所做的那样聚合一个数组。这不支持的一些事情:其他语言中的字符是代理项对、home/end、从剪贴板粘贴、标点符号和点击控制台水平缓冲区的末尾。我相信还有更多,但这只是我的想法。这只是一个开始,一个想法,需要进一步改进,你应该添加所有这些功能,但它们很容易添加。如果我没有弄错的话,C控制台无论如何只支持ASCII@Servy欢迎使用StackOverflow,在这里我们不为其他人编写代码,但为他们指出正确的方向:@TomaszJuszczak事实上,这些特性中的许多都很难添加。至于什么是网站,它是一个我们为质量问题提供高质量答案的网站。这不是一个人们提供半个答案却不能真正解决问题的地方。该网站的设计是,问题的范围仅限于那些可以快速、简洁地回答的问题,而不需要从头开始编写相关功能的答案。
    static void Main(string[] args)
    {
        List<char> outputString = new List<char>();
        outputString = "test".ToCharArray().ToList();
        //If there is something in outputString write it to buffer and set cursor position
        if (outputString.Count > 0)
        {
            Console.Write(outputString.Select(x => x.ToString()).Aggregate((x, y) => x + y));
        }

        while (true)
        {
            //This will read user input but it will not print it to the console window 
            var key = Console.ReadKey(true);
            //Allow user maniputate cursor to the right
            //Here you can add another condition to prevent line overflow or some constrains
            //if(Console.CursorLeft < 30)
            if (key.Key == ConsoleKey.RightArrow && Console.CursorLeft < outputString.Count)
            {
                Console.SetCursorPosition(Console.CursorLeft + 1, Console.CursorTop);
            }
            else if (key.Key == ConsoleKey.LeftArrow && Console.CursorLeft > 0)
            {
                Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
            }
            //Here you should add all keys that your input should take, special characters are ok above ASCII number 32 which is space
            else if (key.KeyChar >= 48 && key.KeyChar <= 57 || //Read numbers
                key.KeyChar >= 64 && key.KeyChar <= 90 || //Read capital letters
                key.KeyChar >= 97 && key.KeyChar <= 122 || //Read lower letters
                key.Key == ConsoleKey.Spacebar)
            {
                Console.Write(key.KeyChar);
                if(Console.CursorLeft > outputString.Count)
                {
                    outputString.Add(' ');
                }
                outputString[Console.CursorLeft - 1] = key.KeyChar;
            }
            //This will remove character
            else if (key.Key == ConsoleKey.Backspace && Console.CursorLeft > 1)
            {
                ClearCurrentConsoleLine();
                outputString.RemoveAt(Console.CursorLeft - 1);
                var currentLeft = Console.CursorLeft;
                Console.CursorLeft = 0;
                Console.Write(outputString.Select(x => x.ToString()).Aggregate((x,y) => x + y));
                Console.CursorLeft = currentLeft - 1;
            }
            //This ends input loop
            //You can add more keys to break current loop with OR condition
            else if (key.Key == ConsoleKey.Enter)
            {
                break;
            }
        }
        //Display result and wait for any key
        Console.WriteLine(outputString.Select(x => x.ToString()).Aggregate((x, y) => x + y));
        Console.ReadKey();
    }

    //Clears current console line and sets cursor at where it was before
    public static void ClearCurrentConsoleLine()
    {
        int currentLineCursorTop = Console.CursorTop;
        int currentLineCursorLeft = Console.CursorLeft;
        Console.SetCursorPosition(0, Console.CursorTop);
        Console.Write(new string(' ', Console.WindowWidth));
        Console.SetCursorPosition(currentLineCursorLeft, currentLineCursorTop);
    }