use std::env; use std::fs::File; use std::io; use std::io::BufRead; use std::result::Result; struct Count { lines: usize, words: usize, chars: usize, } impl Count { fn new() -> Self { Count { lines: 0, words: 0, chars: 0, } } fn add(&mut self, c: &Count) { self.lines += c.lines; self.words += c.words; self.chars += c.chars; } fn count(&mut self, line: &str) { self.count_line(); self.count_words_in_line(line); self.count_chars_in_line(line); } fn count_line(&mut self) { self.lines += 1; } fn count_words_in_line(&mut self, line: &str) { let mut in_word = false; for c in line.chars() { if c.is_alphabetic() { if !in_word { in_word = true; self.words += 1; } } else { in_word = false; } } } fn count_chars_in_line(&mut self, line: &str) { // add +1 for newline, which we ASSUME is there self.chars += line.chars().count() + 1; } } fn main() -> Result<(), io::Error> { let mut total = Count::new(); for filename in env::args().skip(1) { let mut f = File::open(&filename)?; let mut reader = io::BufReader::new(f); let c = wc(&mut reader)?; total.add(&c); println!("{:>5} {:>5} {:>5} {}", c.lines, c.words, c.chars, filename); } if env::args().skip(1).count() > 1 { println!("{:>5} {:>5} {:>5} {}", total.lines, total.words, total.chars, "total"); } Ok(()) } fn wc(reader: &mut io::BufReader) -> Result { let mut count = Count::new(); for line in reader.lines() { let line = line?; count.count(&line); } Ok(count) }