Midterm Project: Build a Real CLI Tool
মিডটার্ম প্রজেক্ট — একটা বাস্তব CLI টুল
1. Pick a Track
You have learned enough C++ to build a complete program. Pick one of the projects below and ship it: multi-file, with a CMakeLists.txt and a README. Better small and working than big and broken.
এতদিনে আপনি যথেষ্ট C++ শিখেছেন একটি সম্পূর্ণ প্রোগ্রাম তৈরি করার জন্য। নিচের যেকোনো একটি প্রজেক্ট বেছে নিয়ে শেষ করুন। আকারে ছোট হলেও সঠিকভাবে কাজ করুক — সেটাই গুরুত্বপূর্ণ।
Track A · Word Counter (wc)
- Count lines, words, bytes in a file
- Multiple files, totals row
- Flags:
-l,-w,-c
Track B · Todo CLI
- add / list / done / remove subcommands
- Persist to a text file
- Pretty output with colors
Track C · Calculator (rpn)
- Reverse Polish Notation
- Stack-based evaluator
- +, -, *, /, sqrt, pow
Track D · CSV Stats
- Read a CSV file
- min, max, mean, median per column
- Format as table
2. Reading Command-line Arguments
argv.cpp
#include <iostream>
#include <string>
#include <vector>
int main(int argc, char* argv[]) {
std::vector<std::string> args(argv, argv + argc);
std::cout << "Program: " << args[0] << "\n";
for (size_t i = 1; i < args.size(); ++i)
std::cout << " arg " << i << ": " << args[i] << "\n";
}
3. Reading a File
readfile.cpp
#include <iostream>
#include <fstream>
#include <string>
int main() {
std::ifstream in("data.txt");
if (!in) { std::cerr << "can't open\n"; return 1; }
std::string line;
int lines = 0, words = 0, bytes = 0;
while (std::getline(in, line)) {
++lines;
bytes += line.size() + 1;
bool in_word = false;
for (char c : line) {
if (std::isspace(static_cast<unsigned char>(c))) in_word = false;
else if (!in_word) { in_word = true; ++words; }
}
}
std::cout << lines << " " << words << " " << bytes << "\n";
}
4. Project Structure
Recommended layout
my-cli/
├── CMakeLists.txt
├── README.md
├── src/
│ ├── main.cpp
│ ├── counter.cpp
│ └── counter.hpp
└── tests/
└── test_counter.cpp
5. CMakeLists.txt Skeleton
CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(my_cli LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(my_cli
src/main.cpp
src/counter.cpp)
target_include_directories(my_cli PRIVATE src)
target_compile_options(my_cli PRIVATE -Wall -Wextra -O2)
6. Starter Exercises
- Print all command-line arguments, one per line.
✨ Show Answer
See section 2 above.
- Read a file and print every line numbered.
✨ Show Answer
std::ifstream in(path); std::string line; int n = 1; while (std::getline(in, line)) std::cout << n++ << ": " << line << "\n"; - Implement a simple
--helpflag.✨ Show Answer
if (argc > 1 && std::string{argv[1]} == "--help") { std::cout << "Usage: my_cli [options] file\n"; return 0; } - Count words in a hardcoded string for testing.
✨ Show Answer
wc.cpp#include <iostream> #include <sstream> #include <string> int main() { std::string text = "the quick brown fox jumps"; std::istringstream ss(text); std::string word; int count = 0; while (ss >> word) ++count; std::cout << count << " words\n"; } - Append a line to a file.
✨ Show Answer
std::ofstream out("todo.txt", std::ios::app); out << "new item\n";
Submission Checklist
- Multi-file project (at least 1 source + 1 header)
- CMakeLists.txt builds cleanly with
-Wall -Wextra - README explains how to build and use
- Handles
--helpand bad input gracefully - At least one unit test (or a hand-tested input file)
- Compiles with no warnings