【问题标题】:Why is there an extra loop before reaching EOF in this D example?为什么在这个 D 示例中到达 EOF 之前有一个额外的循环?
【发布时间】:2014-09-14 21:38:19
【问题描述】:

这是官方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);
    }
}

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

ldc2 -run file.d
read line -> |Name  : Zafer
read line -> |Number: 123
read line -> |Class : 1A
read line -> |

请注意打印了一个空行。现在如果我把第三个 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);
    }
}

那么最后一个空行就不再打印了:

ldc2 -run file.d
read line -> |Name  : Zafer
read line -> |Number: 123
read line -> |Class : 1A

我想知道为什么这会有所不同:无论如何,readln 都应该读到包括行终止符号在内的行尾,为什么当我们显然已经达到 EOF 时还要有一个额外的循环?

【问题讨论】:

    标签: io d


    【解决方案1】:

    我的猜测是 readln 读取到并包括行终止符 ('\n') 但不到 EOF。您的文件如下所示:

    Name  : Zafer\n   <---- first readln
    Number: 123\n     <---- second readln
    Class : 1A\n      <---- third readln
    EOF               <---- fourth readln
    

    在第三次调用readln 之后,还有更多内容需要阅读,即使它只是 EOF。最后一次对readln 的调用返回null,writeln 很高兴地接受并且不打印任何内容(在字符串“read line -> |”之后)。 docs on 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);
    }
    

    另一种选择是使用foreach

    foreach(line ; file1.byLine) {
        writeln("read line -> |", line.chomp);
    }
    

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

    如上所述,在创建文件时将最后一个writeln 替换为write 也可以避免打印最后一个空行,因为少了一个\n,因此对readln 的第三次调用直接读取到EOF 不会在最后的 \n 处停下来。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-20
      • 2019-03-11
      • 2023-01-16
      • 2015-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多