Warum C++ die ideale Sprache für CLI-Tools ist?
Wenn es um die Erstellung von CLI-Tools in C++ geht, zucken viele Entwickler mit den Schultern: "Warum? Es gibt doch Python, Go, Rust". Aber sehen wir der Wahrheit ins Auge. Wenn Sie blitzschnelle Geschwindigkeit, minimalen Speicherverbrauch und volle Kontrolle über die Hardware benötigen, ist C++ unschlagbar. Systemadministratoren, DevOps-Ingenieure und Entwickler eingebetteter Systeme schreiben ihre Konsolen-Tools immer noch in dieser Sprache. Und wissen Sie was? Das ist richtig so.
Heute werden wir die Erstellung eines CLI-Tools in C++ von Grund auf durchgehen – vom Parsen von Argumenten bis zum Bau der Binärdatei. Sie erfahren, wie Sie ein echtes, nützliches Werkzeug schreiben, das Sie nicht schämen werden, auf GitHub zu veröffentlichen. Los geht's.
Werkzeuge: Was wir brauchen
Für komfortables Arbeiten benötigen wir:
- C++17/20 Compiler – GCC (MinGW unter Windows) oder Clang. Ich persönlich empfehle GCC 11+.
- Texteditor oder IDE – VS Code mit C++-Plugin, CLion oder sogar Vim (für Hardcore-Entwickler).
- CMake – für bequemes Bauen. Man kann auch ein Makefile verwenden, aber CMake ist der moderne Standard.
- Git – denn Versionskontrolle ist unverzichtbar.
Außerdem benötigen wir eine Bibliothek zum Parsen von Kommandozeilenargumenten. Wir werden das Rad nicht neu erfinden und das legendäre getopt verwenden (das es in POSIX-Systemen gibt) oder unseren eigenen minimalistischen Parser schreiben. Die zweite Option ist sogar interessanter – Sie verstehen, wie es "unter der Haube" funktioniert.
Projektstruktur
Bevor wir Code schreiben, legen wir fest, was genau wir erstellen. Es soll das Tool fileutils sein – ein Konsolenwerkzeug für die Dateiarbeit. Es soll können:
- Anzahl der Zeilen, Wörter und Zeichen in einer Datei zählen (Analogon zu
wc). - Eine Zeile nach einem Muster durchsuchen (Analogon zu
grepin minimaler Form). - Hilfe anzeigen (
--help).
Ordnerstruktur:
fileutils/├── src/│ ├── main.cpp│ ├── parser.cpp│ └── parser.h├── CMakeLists.txt└── README.mdSchritt 1: Eigener Argument-Parser
Schreiben wir einen einfachen, aber funktionierenden Parser. Er wird lange Flags (--lines, --words) und Positionsargumente (Dateiname) verarbeiten.
Datei 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[]);
#endifDatei 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 << "Verwendung: fileutils [OPTIONEN] DATEI..." << "Optionen:" << " --lines, -l Zeilenanzahl ausgeben" << " --words, -w Wortanzahl ausgeben" << " --chars, -c Zeichenanzahl ausgeben" << " --search MUST Nach Muster suchen" << " --help, -h Diese Hilfe anzeigen"; 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];