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 incr_lines(&mut self) { self.lines += 1; } fn incr_words(&mut self, n: usize) { self.words += n; } fn incr_chars(&mut self, n: usize) { self.chars += n; } } fn main() -> Result<(), io::Error> { 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)?; println!("{:>5} {:>5} {:>5} {}", c.lines, c.words, c.chars, filename); } Ok(()) } fn wc(reader: &mut io::BufReader) -> Result { let mut count = Count::new(); for line in reader.lines() { let line = line?; count.add(&count_line(&line)); } Ok(count) } fn count_line(line: &str) -> Count{ let mut count = Count::new(); // we have a line! count.incr_lines(); // add +1 for newline, which we ASSUME is there count.incr_chars(line.chars().count() + 1); // count words count.incr_words(count_line_words(line)); count } fn count_line_words(line: &str) -> usize { let mut in_word = false; let mut num_words = 0; for c in line.chars() { if c.is_alphabetic() { if !in_word { in_word = true; num_words += 1; } } else { in_word = false; } } num_words }