Creating CLI Utilities in C++: From Idea to Ready Tool

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Why C++ is the Ideal Language for CLI Utilities?

When it comes to creating CLI utilities in C++, many developers shrug: "Why? There's Python, Go, Rust." But let's face the truth. If you need lightning speed, minimal memory consumption, and full control over the hardware — C++ is unrivaled. System administrators, DevOps engineers, and embedded systems developers still write their console tools in this language. And you know what? That's correct.

Today we will break down creating a CLI utility in C++ from scratch — from argument parsing to building the binary. You will learn how to write a real, useful tool that you won't be ashamed to publish on GitHub. Let's go.



Toolkit: What We'll Need

For comfortable work we will need:

  • C++17/20 Compiler — GCC (MinGW on Windows) or Clang. Personally, I recommend GCC 11+.
  • Text editor or IDE — VS Code with C++ plugin, CLion, or even Vim (for hardcore folks).
  • CMake — for convenient building. You can use Makefile too, but CMake is the modern standard.
  • Git — can't do without version control.

We will also need a library for command line argument parsing. We won't reinvent the wheel and will take the legendary getopt (available on POSIX systems) or write our own minimalist parser. The second option is even more interesting — you will understand how it works "under the hood".



Project Structure

Before writing code, let's decide what exactly we are creating. Let it be the fileutils utility — a console tool for working with files. It will be able to:

  • Count the number of lines, words, and characters in a file (analogous to wc).
  • Search for a string by pattern (analogous to grep in minimal form).
  • Display help (--help).

Folder structure:

fileutils/├── src/│   ├── main.cpp│   ├── parser.cpp│   └── parser.h├── CMakeLists.txt└── README.md


Step 1: Custom Argument Parser

Let's write a simple but working parser. It will handle long flags (--lines, --words) and positional arguments (file name).



File parser.h

#ifndef PARSER_H#define PARSER_H

#include <string>#include <vector>#include <map>

struct Args { bool show_lines = false; bool show_words = false; bool show_chars = false; std::string pattern; std::vector<std::string> files;};

Args parse_args(int argc, char* argv[]);

#endif


File parser.cpp

#include "parser.h"#include <iostream>

Args parse_args(int argc, char* argv[]) { Args args; for (int i = 1; i < argc; ++i) { std::string arg = argv[i]; if (arg == "--help" || arg == "-h") { std::cout << "Usage: fileutils [OPTIONS] FILE..." << "Options:" << " --lines, -l Print line count" << " --words, -w Print word count" << " --chars, -c Print character count" << " --search PAT Search for pattern" << " --help, -h Show this help"; exit(0); } else if (arg == "--lines" || arg == "-l") { args.show_lines = true; } else if (arg == "--words" || arg == "-w") { args.show_words = true; } else if (arg == "--chars" || arg == "-c") { args.show_chars = true; } else if (arg == "--search" && i + 1 < argc) { args.pattern = argv[++i];

Blogs

Book Recommendations