命令行符号生成器免编译新增符号:能否将输入串作为cout指令调用?
解决符号生成器无需编译新增符号的问题
首先得明确:你想的直接cout<<x的方式行不通。因为x是你传入的符号名称字符串(比如"butterfly"),cout只会输出这个字符串本身,而不会自动关联到你原来定义的butterfly变量里的ASCII艺术内容。C是静态编译语言,变量名在编译后就变成了内存地址,运行时没法通过字符串名称直接找到对应的变量值(原生C没有反射机制)。
那怎么实现不用重新编译主程序就能新增符号呢?答案是把符号数据放到外部配置文件里,主程序运行时读取这个文件,建立名称到符号内容的映射。下面给你两种可行的方案:
方案一:用JSON配置文件(推荐)
JSON格式结构清晰,容易编辑和解析,是这类场景的首选。
步骤1:创建符号配置文件
新建一个symbols.json文件,把你的符号按键值对的形式存进去:
{ "butterfly": "$¶¶$¶¶$¶$ $¶¶$ø¢¢øø17¶$ ¶¢1 7oøoø o7¶1 11¶¶¶¶¶¶¶¶¶ø ø¶ø 1oø¢o1ø o¶¢ ¶¶¢¶ø¢¢¢¢77oø¶¶¶ ¶¢7ø$øoo7o$77¶o ¶¶7 7o77177777oø¶¶1 ¶øooo77777oø7¶¶ ¶¶¶7o¢øø77ø¢ooooø¶¶¶¶¶¶¢oooo7177¢7o¶7 ¶¶7 oooooooo77177o7øø¢¢ø¢ooooøø¢¶ 7¶¢o7¢øoo7717oøø¶¶øoø¢ooo¢¢ooooo$7 7¶¶ø17oo7oø¶øøooøooooo777o¢oo71 o¶1 1¶¶$oø$$¢111¢1o¶¶ø7oøøo7ooooø7¢1¶ ø177 o1 ooo ¢ø ¶ø7oooø¢oo1¢1ø7¶ ¶¢¢7o7oo¢oøo ø¶ ¶¶ooo77o7ø¶1 o¶ 1ø$oøo1øø¢¢7o ¶ø ø¶¢$$¢$¶77oø¶7 7¶17ø77¢7711¶7¶ ¢¢ø 71¢¶1 ø¶$¢øø71oøø¢¢¶ øø¶¶¶¶¶o 7¶oø¶¶¶¢77¶¶ $¶¶ø¢¶¶¶7", "hello": "这里放hello对应的ASCII艺术内容", "hi": "这里放hi对应的ASCII艺术内容" }
步骤2:修改主程序代码
用一个轻量的JSON库(比如nlohmann/json,单头文件,直接下载放到项目里就行)来读取配置文件。修改后的代码如下:
#include <iostream> #include <fstream> #include <unordered_map> #include <string> #include <nlohmann/json.hpp> using json = nlohmann::json; using namespace std; // 找不到符号时的提示内容 string const notfound = R"~( ______ _________ .---""" """---. :______.-': : .--------------. : | ______ | | : : | |:______B:| | | Little Error: | | |:______B:| | | | | |:______B:| | | Symbol not | | | | | | found. | | |:_____: | | | | | | == | | : : | | O | : '--------------' : | o | :'---...______...---' | o |-._.-i___/' \._ |'-.____o_| '-. '-...______...-' -._ :_________: .____________________ -.___.-. '.eeeeeeeeeeeeeeeeee.'. :___: '.eeeeeeeeeeeeeeeeeeeeee.'. :____________________________: )~"; // 从JSON文件加载符号映射 unordered_map<string, string> loadSymbols(const string& filename) { unordered_map<string, string> symbols; ifstream file(filename); if (!file.is_open()) { cerr << "Error: Could not open symbols file!" << endl; return symbols; } json symbolData; file >> symbolData; // 遍历JSON的键值对,存入map for (auto& [symbolName, symbolContent] : symbolData.items()) { symbols[symbolName] = symbolContent.get<string>(); } return symbols; } // 根据名称打印符号 void Print_Symbol(const string& name, const unordered_map<string, string>& symbols) { auto it = symbols.find(name); if (it != symbols.end()) { cout << it->second << endl; } else { cout << notfound << endl; } } int main(int argc, char* argv[]) { // 加载外部符号配置 auto symbols = loadSymbols("symbols.json"); if (argc < 2) { cout << "To get a symbol enter: sym Symbol_Name" << '\n'; cout << "Available Symbols: " << '\n'; // 打印所有可用符号名称 for (auto& [name, _] : symbols) { cout << name << ", "; } if (!symbols.empty()) { cout << "\b\b " << endl; // 移除最后一个多余的逗号 } return 0; } // 处理每个命令行参数 for (int i = 1; i < argc; i++) { string symbolName = argv[i]; Print_Symbol(symbolName, symbols); } return 0; }
使用方式
以后新增符号,只需要编辑symbols.json,添加新的键值对即可,完全不用重新编译主程序。
方案二:自定义文本格式配置
如果你不想用JSON库,也可以自己实现一个简单的配置文件格式,比如每行是符号名称=符号内容(注意:如果符号内容里有换行或等号,需要做转义处理)。
示例配置文件symbols.txt
butterfly=$¶¶$¶¶$¶$ $¶¶$ø¢¢øø17¶$ ¶¢1 7oøoø o7¶1 ... hello=你的ASCII艺术内容 hi=另一个ASCII内容
对应的加载函数
替换方案一里的loadSymbols函数即可:
unordered_map<string, string> loadSymbols(const string& filename) { unordered_map<string, string> symbols; ifstream file(filename); if (!file.is_open()) { cerr << "Error: Could not open symbols file!" << endl; return symbols; } string line; while (getline(file, line)) { size_t equalPos = line.find('='); if (equalPos == string::npos) continue; // 跳过无效行 string name = line.substr(0, equalPos); string content = line.substr(equalPos + 1); symbols[name] = content; } return symbols; }
这种方案不需要额外的库,但处理复杂内容(比如带换行的ASCII艺术)会比较麻烦,所以还是更推荐JSON方案。
内容的提问来源于stack exchange,提问作者AmineTrabelsi
相关产品推荐
相关产品推荐

