c#中更快的控制台I/O方式

本文关键字:方式 控制台 | 更新日期: 2023-09-27 18:11:45

我最近开始在像sphere online judge这样的编程竞赛网站上使用c#。我注意到的一件事是,控制台I/O确实会减慢c#程序的速度。

我主要使用控制台。ReadLine和Console。WriteLine方法。对于整数解析,我编写了自己的解析器,因为内置的解析器相当慢

我知道,写入控制台是缓慢的,所以当有很多东西要写的时候,我使用StringBuilder来构建所有的输出,并使用一个单独的console . writeline (sb.ToString())调用一次写入所有的输出。

是否有更多的优化我可以加快I/O?除了我上面提到的,还有其他的I/O方式吗?

(请不要使用you-should-check your-algorithm-first之类的回答,这个问题是专门关于快速I/O的。)

c#中更快的控制台I/O方式

我正在以这种方式加速控制台I/O:

解析长数组

static IEnumerable<T> ReadArray<T>(string arrayLine, Func<string, T> parseFunction, char separator = ' ')
{
    int from = 0;
    for (int i = 0; i < arrayLine.Length; i++)
    {
        if (arrayLine[i] == separator)
        {
            yield return parseFunction(arrayLine.Substring(from, i - from));
            from = i + 1;
        }
    }
    yield return parseFunction(arrayLine.Substring(from));
}

,你可以这样使用这个方法

var array = ReadArray(Console.ReadLine(), s => int.Parse(s)).ToArray();

您可以获得额外的毫秒避免ToArray()调用和直接返回数组,因为大多数时间数组长度是输入的一部分。

高效打印(有时还不够)

class Program
{
    static StreamWriter output = new StreamWriter(Console.OpenStandardOutput());
    internal static void Run()
    {
        int testCount = int.Parse(Console.ReadLine());
        for (int t = 0; t < testCount; t++)
        {
            // Do your logic here. For example
            var result = FooBarSolution(...);
            output.WriteLine(result);               
        }
        output.Flush();
    }
}

GIST。

读取字符串并将其转换回整数或长等,有不必要的开销。

需要考虑的事情:

  1. 你能一次读取多个测试用例吗?
  2. 您能否以一种支持的格式读取输入,并且更容易转换为其他数据类型?[字符串对开发者来说很简单;)]
  3. 你能以缓冲的方式读取吗?
  4. 不安全代码是由SPOJ c#编译器支持吗?这样你就能救更多的虱子了?等等…

这是我对INOUT测试的看法

你应该使用一个巨大的缓冲区(byte[])并读取所有控制台输入字节-然后使用ReadByte()循环,直到你看到一个空白字符,并根据你的输入格式将该段转换为整数或长或字符串。

这是非常有效的,节省了很多时间严格限制的问题。

下面是我的示例代码

public int ReadInt()
    {
        byte readByte;
        while ((readByte = GetByte()) < '-') ;
        var neg = false;
        if (readByte == '-')
        {
            neg = true;
            readByte = GetByte();
        }
        var m = readByte - '0';
        while (true)
        {
            readByte = GetByte();
            if (readByte < '0') break;
            m = m * 10 + (readByte - '0');
        }
        return neg ? -m : m;
    }

这是我在SPOJ中使用的代码https://github.com/davidsekar/C-sharp-Programming-IO/blob/master/ConsoleInOut/InputOutput.cs

谢谢,

davidsekar