I am following this reference to implement a simple program which calculates the minimum number of inputs:
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();
}
Build an run the program:
Enter a list of numbers, one per line. End with Ctrl-D (Linux) or Ctrl-Z (Windows).
100
8
200
8D
We can see there is a trailing "D
" after the minimum number: 8
. But if I changed the output from:
Something(n) => println!("{}", n),
to:
Something(n) => println!("The number is: {}", n),
The output seems normal:
Enter a list of numbers, one per line. End with Ctrl-D (Linux) or Ctrl-Z (Windows).
100
8
200
The number is: 8
I guess the issue is related to stdout buffer, but can't figure out why. Anyone can give some clues?
P.S., I can reproduce this issue on macOS
(zsh
) and OmniOS
(bash
), but can't reproduce on Linux
(bash
).
I was able to recreate this on macOS using iTerm (tested with zsh and bash). It looks like the problem is related to the the terminal echoing signal control commands:
So to stop this, you'll want to turn off echoctl
The easiest way to see what's happening is to hit Crtl-D
while still on a line with a number:
Enter a list of numbers, one per line. End with Ctrl-D (Linux) or Ctrl-Z (Windows).
1
2
3
4^D
What's happening in your case is: you're on an empty line and hit Ctrol-D
, the terminal echos ^D
to the line and then moves the cursor back to the beginning of the line, then your programs output overwrites the ^D
. So, if you output a single digit number, the ^
is overwritten but the D
remains (as in your example). When you output more characters the ^
and the D
are overwritten.
Here's a demonstration where the D
is overwritten:
Enter a list of numbers, one per line. End with Ctrl-D (Linux) or Ctrl-Z (Windows).
100
200
300
100