为什么我的 println!() 输出有尾随 "D"?

Why is there a trailing "D" of my println!() output?

我正在按照这个 reference 来实现一个计算最小输入数量的简单程序:

use std::io::prelude::*;
use std::io;

fn read_vec() -> Vec<i32> {
    let mut vec: Vec<i32> = Vec::<i32>::new();

    let stdin = io::stdin();
    println!("Enter a list of numbers, one per line. End with Ctrl-D (Linux) or Ctrl-Z (Windows).");
    
    for line in stdin.lock().lines() {
        let line = line.unwrap();
        match line.trim().parse::<i32>()  {
            Ok(num) => vec.push(num),
            Err(_) => println!("What did I say about numbers?"),
        }
    }

    vec
}

pub enum SomethingOrNothing<T> {
    Something(T),
    Nothing,
}

pub use self::SomethingOrNothing::*;

type NumberOrNothing = SomethingOrNothing<i32>;

pub trait Minimum: Copy {
    fn min(self, b: Self) -> Self;
}

pub fn vec_min<T: Minimum>(v: Vec<T>) -> SomethingOrNothing<T> {
    let mut min = Nothing;
    for e in v {
        min = match min {
            Something(t) => Something(e.min(t)),
            Nothing => Something(e),
        }
    }
    min
}

impl Minimum for i32 {
    fn min (self, b: Self) -> Self {
        if self < b {self} else {b}
    }
}

impl NumberOrNothing {
    pub fn print(self) {
        match self {
            Nothing => println!("The number is: <nothing>"),
            Something(n) => println!("{}", n),
        };
    }
}

fn main() {
    let vec = read_vec();
    let min = vec_min(vec);
    min.print();
}

构建一个运行程序:

Enter a list of numbers, one per line. End with Ctrl-D (Linux) or Ctrl-Z (Windows).
100
8
200
8D

我们可以看到在最小数字8之后有一个尾随的“D”。但是,如果我将输出更改为:

Something(n) => println!("{}", n),

至:

Something(n) => println!("The number is: {}", n),

输出似乎正常:

Enter a list of numbers, one per line. End with Ctrl-D (Linux) or Ctrl-Z (Windows).
100
8
200
The number is: 8

我猜这个问题与标准输出缓冲区有关,但无法弄清楚原因。谁能给点线索?

P.S.,我可以在 macOS(zsh) 和 OmniOS (bash) 上重现此问题,但无法在Linux(bash).

我能够使用 iTerm 在 macOS 上重新创建它(使用 zsh 和 bash 测试)。看起来问题与终端回显信号控制命令有关:

因此,要停止此操作,您需要关闭 echoctl

查看正在发生的事情的最简单方法是点击 Crtl-D,同时仍然在带有数字的行上:

Enter a list of numbers, one per line. End with Ctrl-D (Linux) or Ctrl-Z (Windows).
1
2
3
4^D

你的情况是:你在一个空行上并点击 Ctrol-D,终端将 ^D 回显到该行,然后将光标移回该行的开头,那么您的程序输出将覆盖 ^D。因此,如果您输出一个数字, ^ 将被覆盖,但 D 仍然存在(如您的示例所示)。当您输出更多字符时,^D 将被覆盖。

下面是 D 被覆盖的演示:

Enter a list of numbers, one per line. End with Ctrl-D (Linux) or Ctrl-Z (Windows).
100
200
300
100