C++ CLI उपयोगिताओं के लिए आदर्श भाषा क्यों है?
\nजब C++ में CLI उपयोगिताएँ बनाने की बात आती है, तो कई डेवलपर्स कंधे उचकाते हैं: "क्यों? Python, Go, Rust तो हैं।" लेकिन आइए सच्चाई का सामना करें। यदि आपको बिजली की गति, न्यूनतम मेमोरी खपत और हार्डवेयर पर पूर्ण नियंत्रण चाहिए — तो C++ अद्वितीय है। सिस्टम एडमिनिस्ट्रेटर, DevOps इंजीनियर और एम्बेडेड सिस्टम डेवलपर आज भी अपने कंसोल टूल्स इसी भाषा में लिखते हैं। और जानते हैं क्या? यह सही है।
\nआज हम C++ में CLI उपयोगिता को शुरुआत से बनाने पर चर्चा करेंगे — आर्गुमेंट पार्सिंग से लेकर बाइनरी बिल्ड तक। आप सीखेंगे कि एक वास्तविक, उपयोगी उपकरण कैसे लिखा जाए जिसे GitHub पर साझा करने में शर्म न आए। चलिए शुरू करते हैं।
\n\nउपकरण: हमें क्या चाहिए
\nआरामदायक काम के लिए हमें आवश्यकता होगी:
\n- \n
- C++17/20 कंपाइलर — GCC (Windows पर MinGW) या Clang। मैं व्यक्तिगत रूप से GCC 11+ की सिफारिश करता हूँ। \n
- टेक्स्ट एडिटर या IDE — C++ प्लगइन के साथ VS Code, CLion, या Vim (हार्डकोर के लिए)। \n
- CMake — आसान बिल्ड के लिए। हालाँकि Makefile भी चल सकता है, लेकिन CMake आधुनिक मानक है। \n
- Git — संस्करण नियंत्रण के बिना कैसे चलेगा। \n
हमें कमांड लाइन आर्गुमेंट पार्स करने के लिए एक लाइब्रेरी की भी आवश्यकता होगी। हम पहिया का पुनः आविष्कार नहीं करेंगे और प्रसिद्ध getopt (जो POSIX सिस्टम में उपलब्ध है) का उपयोग करेंगे या अपना न्यूनतम पार्सर लिखेंगे। दूसरा विकल्प और भी दिलचस्प है — आप समझेंगे कि यह "हुड के नीचे" कैसे काम करता है।
प्रोजेक्ट संरचना
\nकोड लिखने से पहले, आइए तय करें कि हम वास्तव में क्या बना रहे हैं। मान लीजिए यह fileutils उपयोगिता है — फ़ाइलों के साथ काम करने के लिए एक कंसोल टूल। यह निम्नलिखित कार्य करेगी:
\n- \n
- फ़ाइल में पंक्तियों, शब्दों और वर्णों की संख्या गिनना (
wcका एनालॉग)। \n - पैटर्न द्वारा स्ट्रिंग खोजना (न्यूनतम रूप में
grepका एनालॉग)। \n - सहायता प्रदर्शित करना (
--help)। \n
फ़ोल्डर संरचना:
\nfileutils/\n├── src/\n│ ├── main.cpp\n│ ├── parser.cpp\n│ └── parser.h\n├── CMakeLists.txt\n└── README.md\n\nचरण 1: स्वयं का आर्गुमेंट पार्सर
\nएक सरल लेकिन कार्यशील पार्सर लिखें। यह लंबे फ़्लैग (--lines, --words) और पोज़िशनल आर्गुमेंट (फ़ाइल नाम) को संसाधित करेगा।
फ़ाइल parser.h
\n#ifndef PARSER_H\n#define PARSER_H\n\n#include <string>\n#include <vector>\n#include <map>\n\nstruct Args {\n bool show_lines = false;\n bool show_words = false;\n bool show_chars = false;\n std::string pattern;\n std::vector<std::string> files;\n};\n\nArgs parse_args(int argc, char* argv[]);\n\n#endif\n\nफ़ाइल parser.cpp
\n#include "parser.h"\n#include <iostream>\n\nArgs parse_args(int argc, char* argv[]) {\n Args args;\n \n for (int i = 1; i < argc; ++i) {\n std::string arg = argv[i];\n \n if (arg == "--help" || arg == "-h") {\n std::cout << "Usage: fileutils [OPTIONS] FILE...\\n"\n << "Options:\\n"\n << " --lines, -l Print line count\\n"\n << " --words, -w Print word count\\n"\n << " --chars, -c Print character count\\n"\n << " --search PAT Search for pattern\\n"\n << " --help, -h Show this help\\n";\n exit(0);\n } else if (arg == "--lines" || arg == "-l") {\n args.show_lines = true;\n } else if (arg == "--words" || arg == "-w") {\n args.show_words = true;\n } else if (arg == "--chars" || arg == "-c") {\n args.show_chars = true;\n } else if (arg == "--search" && i + 1 < argc) {\n args.pattern = argv[++i];\n