从1到10写入数字,将光标位置设置为开头并重新开始写入

Write numbers from 1 to 10, set cursor position to the beginning and restart the writing

我刚遇到一个我无法解释的奇怪行为。我有一个控制台应用程序,它写入从 1 到 9 的数字,然后再次将光标设置到控制台 window 的开头。之后,循环继续并重新开始写入从1到10的数字。问题是之前写入的数字被覆盖而不是向前移动。

为了更好理解我的代码:

int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
for (int counter = 0; counter < 10; counter++)
{
    foreach (int number in numbers)
    {
        Console.Write(number + " ");
        Thread.Sleep(5);
    }
    Console.SetCursorPosition(0, 0);
}

当我在 Console.SetCursorPosition(0, 0); 下面添加行 Console.Write("Test"); 时,我得到以下输出:

Test1 2 3 4 5 6 7 8 9

我没想到的是:在下面添加Console.Write(1);时,我得到

1 2 3 4 5 6 7 8 9

我想用我的代码实现以下目标:

1 2 3 4 5 6 7 8 9 [now setting cursor position to the beginning and moving the consisting numbers forward] 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 [and so on]

为什么程序的行为不是这样的?

显然,当您将控制台的光标设置为 0,0 时,您将开始覆盖以前的值,因此会发生这种情况。您可以使用字符串连接轻松做到这一点,但我建议您使用 StringBuilder 因为它是可变的。

    public static void Main(string[] args)
    {
        StringBuilder sb = new StringBuilder();

        int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        for (int counter = 0; counter < 10; counter++)
        {
            StringBuilder numberBuilder = new StringBuilder();
            foreach (int number in numbers)
            {
                numberBuilder.Append(number + " ");
            }

            sb.Insert(0, numberBuilder.ToString());
        }

        Console.WriteLine(sb.ToString());
    }

此处dotnet fiddle示例

控制台就像一个 canvas,一旦向其中写入内容,文本就是 "painted on",直到有内容覆盖或擦除它。

当您将光标移动到开头时,您开始一个字母一个字母地覆盖旧文本。看这个例子

Console.Write("This is some long text");
Console.SetCursorPosition(0, 0);
for(int i = 0; i < 30; i++)
{
    Console.Write("z");
    Thread.Sleep(1000);
}

可以看到文字写的很慢,每秒一个字母。

要获得您正在寻找的效果,您需要在整个字符串的内存中保留一个缓冲区并编辑该字符串缓冲区,更新缓冲区后您必须再次写出整行。一种简单的方法是使用 StringBuilder 作为缓冲区(更新:请参阅 了解示例用法)