On Sunday, 11 June 2017 at 05:36:08 UTC, helxi wrote:
I was writing a program that reads and prints the first nth lines to the stdout:

import std.stdio;

void main(string[] args)
{
    import std.algorithm, std.range;
    import std.conv;
    stdin.byLine.take(args[1].to!ulong).each!writeln;
}

As far as I understand the stdin.byLine.take(args[1].to!ulong) part reads all the lines written in stdin.
What if I want to make byLine read only and only first nth line?

stdin.byLine(args[1].to!ulong).each!writeln;

Obviously the code above won't work. Is there any efficient workaround?

Ok, if I read you right you are writing to stdin and want first to print the first args[1] lines, then to do other things with the other lines of stdin.

If you use byLine you will not read all the lines of stdin, but you will lose a line. From there I see three possibilities:

1) If you control the input, add a limit line (if you want to take 2 then the third line will be lost):

import std.conv;
import std.stdio;
import std.range;
import std.algorithm;

void main(string[] args) {
    auto limit = args.length > 1 ? args[1].to!ulong : 2;

    writefln("First %d lines", limit);
    stdin.byLineCopy.take(limit).each!writeln;
    writeln("Next lines");
    stdin.byLineCopy.each!writeln;
}



2) Read all stdin and separate those you want to print from the others later:

import std.conv;
import std.stdio;
import std.range;
import std.algorithm;

void main(string[] args) {
    // I used byLineCopy because of the buffer reuse issue
    auto input = stdin.byLineCopy;
    auto limit = args.length > 1 ? args[1].to!ulong : 2;

    writefln("First %d lines", limit);
    input.take(limit).each!writeln;
    writeln("Next lines");
    input.each!writeln;
}

3) Do not use byLine for the first lines in order to control how much you read.

import std.conv;
import std.stdio;
import std.range;
import std.algorithm;

void main(string[] args) {
    auto limit = args.length > 1 ? args[1].to!ulong : 2;

    writefln("First %d lines", limit);
    foreach (line ; 0 .. limit) {
        // I use write here because readln keeps the \n by default
        stdin.readln.write;
    }
    writeln("Next lines");
    stdin.byLine.each!writeln;
}


There are other options but I think these are worth considering first.

Reply via email to