为什么在这个D例子中到达EOF之前还有一个额外的循环?

qed*_*qed 2 io d

以下是官方D书中的一个例子:

import std.stdio;
import std.string;

void main()
{
    File file = File("student_records", "w");

    file.writeln("Name  : ", "Zafer");
    file.writeln("Number: ", 123);
    file.writeln("Class : ", "1A");
    file.close();

    File file1 = File("student_records", "r");

    while (!file1.eof()) {
        string line = (chomp(file1.readln()));
        writeln("read line -> |", line);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你运行它,你会得到:

ldc2 -run file.d
read line -> |Name  : Zafer
read line -> |Number: 123
read line -> |Class : 1A
read line -> |
Run Code Online (Sandbox Code Playgroud)

请注意,打印出一个空行.现在,如果我将第三个writeln更改为write,

import std.stdio;
import std.string;

void main()
{
    File file = File("student_records", "w");

    file.writeln("Name  : ", "Zafer");
    file.writeln("Number: ", 123);
    file.write("Class : ", "1A");
    file.close();

    File file1 = File("student_records", "r");

    while (!file1.eof()) {
        string line = (chomp(file1.readln()));
        writeln("read line -> |", line);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后不再打印最后一个空行:

ldc2 -run file.d
read line -> |Name  : Zafer
read line -> |Number: 123
read line -> |Class : 1A
Run Code Online (Sandbox Code Playgroud)

我想知道为什么这会产生影响:readln应该读到行的末尾,包括行终止符号,为什么当我们明显达到EOF时应该有一个额外的循环?

rco*_*rre 8

我的猜测是readln读取并包括行终止符('\n')但不包括EOF.你的文件看起来像这样:

Name  : Zafer\n   <---- first readln
Number: 123\n     <---- second readln
Class : 1A\n      <---- third readln
EOF               <---- fourth readln
Run Code Online (Sandbox Code Playgroud)

在第三次调用之后readln,还有更多要阅读,即使它只是EOF.这最后一次调用readln返回null,它很writeln乐意接受并且不打印任何内容(在字符串"read line - > |"之后).readln上文档中给出的示例实际上检查是否readln返回null并使用它来终止.

// Reads $(D stdin) and writes it to $(D stdout).
import std.stdio;

void main()
{
    string line;
    while ((line = stdin.readln()) !is null)
        write(line);
}
Run Code Online (Sandbox Code Playgroud)

另一种选择是使用foreach:

foreach(line ; file1.byLine) {
    writeln("read line -> |", line.chomp);
}
Run Code Online (Sandbox Code Playgroud)

以上和文档中的示例都避免打印该空行.

与上面的描述,免去您的最后一个writelnwrite创建文件时,也避免了打印的最后一个空行有一个少\n,因此第三个呼叫readln直通到读EOF不停止在最后\n.