Capstone: wordfreq CLI

Contents
The spec
Parse argv
HashMap counting
Unit tests for count

The spec

Build wordfreq: a tool that takes one file path, counts how often each word appears, and prints the top ten lines as word plus count. No flags, no subcommands, just argv, files, and a HashMap.

Success means running wordfreq on this very lesson text and seeing small words like the and and near the top. The three sections below build it piece by piece, and the last one locks the counting logic behind tests.

Parse argv

The tool needs exactly one argument, the file path. Demand it with the usage pattern from lesson 41 and keep the path for the next step:

use std::env; fn main() { let args: Vec<String> = env::args().collect(); if args.len() != 2 { eprintln!("usage: wordfreq <file>"); std::process::exit(1); } println!("counting words in {}", args[1]); }

HashMap counting

Counting is the heart of the tool. Take a vector of word slices, then let the entry API create each counter on first sight and bump it after:

use std::collections::HashMap; fn count(words: Vec<&str>) -> HashMap<String, u32> { let mut freq = HashMap::new(); for w in words { *freq.entry(w.to_string()).or_insert(0) += 1; } freq }

The entry call borrows the map once and or_insert supplies zero for new words. Pure functions like count are a joy to test, which is exactly next.

Unit tests for count

Pin the counter down with a test function beside the code. Feed known words and assert the exact tallies:

#[test] fn counts_repeats() { let got = count(vec!["a", "b", "a"]); assert_eq!(got["a"], 2); assert_eq!(got["b"], 1); }

Run with cargo test and green means the core logic is frozen. File reading and sorting are then just wiring around a tested heart.

Next: Capstone: tiny HTTP server

Article author: Arthur Isaev

Related articles
Rust
Rust course: zero to hero in 50 lessons
What is Rust and where it runs
Install Rust
cargo new
Your first program
Variables
Numbers
Strings
Booleans
Tuples
Arrays
Vectors
Slices
if and else
match
Loops
Ownership
Borrowing
Lifetimes
Functions
Structs
Enums in Rust
Advanced match in Rust
Option combinators in Rust
Result and the question mark in Rust
Advanced strings in Rust
Vec methods in Rust
HashMaps in Rust
Modules in Rust
Crates and workspaces in Rust
Testing in Rust
Error handling
Traits
Generics
Trait bounds
Closures
Iterators
Smart pointers
Threads
Mutex and Arc
Files
CLI arguments
Environment variables
Diagnostics
Time
Parsing strings
TCP networking
Capstone: wordfreq CLI
Capstone: tiny HTTP server
Modern Rust tour
Hero roadmap: the whole course on one page
Install Rust on Windows 11
Install Rust on Ubuntu
Install Rust on Rocky Linux
Install Rust on macOS
Install Rust on FreeBSD
Rust in Docker
Banner image

Search this site

Channel @aofeed Chat @aofeedchat

Contacts and cooperation:
I recommend our hosting beget.com
Write to info@aredel.com if you:
1. Want to write an article for our site or translate an article into your native language.
2. Want to place thematically relevant ads on the site.
3. Ads on my site pass maximum censorship. If you see an ad block unsuitable for school-age children, shocking or misleading - please contact us by e-mail
4. Found a mistake, inaccuracy, bug, etc. on the site. ... .......
5. Articles can be shared on social media by clicking a network icon: