C/C++代码无法正确识别变量与预处理器,求修正方案
问题:C++变量与预处理器识别程序修正
任务要求
- 编写名为ID.cpp的C++程序,完成以下操作:
a. 读取名为“program.cpp”的文件;
b. 识别并统计其中唯一的变量名与预处理器名,输出结果。
现有问题
编写的代码无法正确识别变量与预处理器,需进行修正。
现有代码
#include <iostream> #include <fstream> #include <string> #include <map> #include <algorithm> #include <cctype> using namespace std; int main() { string filename; cout << "Enter filename: "; cin >> filename; ifstream infile(filename.c_str()); if (!infile) { cerr << "Error: could not open file " << filename << endl; return 1; } map<string, int> variables; map<string, int> preprocessors; string line; while (getline(infile, line)) { string::iterator it = line.begin(); while (it != line.end()) { if (*it == '#') { string preprocessor; ++it; while (it != line.end() && !isspace(*it)) { preprocessor += *it; ++it; } ++preprocessors[preprocessor]; } else if (isalpha(*it) || *it == '_') { string variable; while (it != line.end() && (isalnum(*it) || *it == '_')) { variable += *it; ++it; } ++variables[variable]; } else { ++it; } } } cout << "Variables:" << endl; for (map<string, int>::iterator it = variables.begin(); it != variables.end(); ++it) { cout << it->first << ": " << it->second << endl; } cout << "Preprocessors:" << endl; for (map<string, int>::iterator it = preprocessors.begin(); it != preprocessors.end(); ++it) { cout << it->first << ": " << it->second << endl; } return 0; }
预期输出
Variable-1: a Variable-2: b Variable-3: c Variable-4: d Variable-5: e Total number of the variables: 5 Preprocessor-1: include Preprocessor-2: define Total number of preprocessor: 2
修正方案
原代码核心问题
- 未排除C++关键字:把
int、string这类关键字误统计为变量。 - 未处理注释与字符串:注释、字符串中的标识符会被错误识别。
- 预处理器识别逻辑粗糙:会把
#后所有非空白字符都当成指令,且未跳过注释/字符串中的#。 - 输出格式不符预期:原输出是“变量名: 出现次数”,但要求按序号列出唯一标识符并统计总数。
- 未满足固定文件名要求:任务要求读取
program.cpp,但原代码让用户输入文件名。
修正后的代码
#include <iostream> #include <fstream> #include <string> #include <map> #include <unordered_set> #include <cctype> using namespace std; // C++关键字集合,用于排除非变量标识符 const unordered_set<string> keywords = { "alignas", "alignof", "and", "and_eq", "asm", "auto", "bitand", "bitor", "bool", "break", "case", "catch", "char", "char8_t", "char16_t", "char32_t", "class", "compl", "concept", "const", "consteval", "constexpr", "constinit", "const_cast", "continue", "co_await", "co_return", "co_yield", "decltype", "default", "delete", "do", "double", "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false", "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable", "namespace", "new", "noexcept", "not", "not_eq", "nullptr", "operator", "or", "or_eq", "private", "protected", "public", "reflexpr", "register", "reinterpret_cast", "requires", "return", "short", "signed", "sizeof", "static", "static_assert", "static_cast", "struct", "switch", "template", "this", "thread_local", "throw", "true", "try", "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual", "void", "volatile", "wchar_t", "while", "xor", "xor_eq" }; int main() { const string filename = "program.cpp"; ifstream infile(filename); if (!infile) { cerr << "Error: could not open file " << filename << endl; return 1; } map<string, int> variables; map<string, int> preprocessors; string line; bool in_multi_comment = false; // 标记是否处于多行注释 while (getline(infile, line)) { string::iterator it = line.begin(); bool in_single_comment = false; // 标记是否处于单行注释 bool in_string = false; // 标记是否处于字符串 char string_quote = '\0'; // 记录字符串的引号类型('或") while (it != line.end()) { // 处理多行注释 if (in_multi_comment) { if (*it == '*' && next(it) != line.end() && *(next(it)) == '/') { in_multi_comment = false; advance(it, 2); } else { ++it; } continue; } // 单行注释直接跳至行尾 if (in_single_comment) { break; } // 处理字符串内容 if (in_string) { if (*it == string_quote && prev(it) != line.begin() && *(prev(it)) != '\\') { in_string = false; } ++it; continue; } // 识别预处理器指令 if (*it == '#') { ++it; // 跳过#后的空白字符 while (it != line.end() && isspace(*it)) { ++it; } string preprocessor; while (it != line.end() && !isspace(*it)) { preprocessor += *it; ++it; } if (!preprocessor.empty()) { ++preprocessors[preprocessor]; } continue; } // 识别多行注释开始 if (*it == '/' && next(it) != line.end() && *(next(it)) == '*') { in_multi_comment = true; advance(it, 2); continue; } // 识别单行注释开始 if (*it == '/' && next(it) != line.end() && *(next(it)) == '/') { in_single_comment = true; advance(it, 2); continue; } // 识别字符串开始 if (*it == '"' || *it == '\'') { in_string = true; string_quote = *it; ++it; continue; } // 识别变量标识符 if (isalpha(*it) || *it == '_') { string identifier; while (it != line.end() && (isalnum(*it) || *it == '_')) { identifier += *it; ++it; } // 排除关键字,只统计变量 if (keywords.find(identifier) == keywords.end()) { ++variables[identifier]; } } else { ++it; } } } // 按预期格式输出变量 cout << "Variables:" << endl; int var_idx = 1; for (const auto& pair : variables) { cout << "Variable-" << var_idx << ": " << pair.first << endl; var_idx++; } cout << "Total number of the variables: " << variables.size() << endl; // 按预期格式输出预处理器 cout << "\nPreprocessors:" << endl; int pre_idx = 1; for (const auto& pair : preprocessors) { cout << "Preprocessor-" << pre_idx << ": " << pair.first << endl; pre_idx++; } cout << "Total number of preprocessor: " << preprocessors.size() << endl; return 0; }
修正说明
- 新增关键字集合,排除
int、string等非变量标识符。 - 加入注释、字符串识别逻辑,避免误统计这些区域内的内容。
- 优化预处理器识别,仅提取
#后的有效指令,跳过无关空白字符。 - 调整输出格式,完全匹配预期的序号式列表+总数统计。
- 固定读取
program.cpp,符合任务要求。
内容的提问来源于stack exchange,提问作者sajid mahbub
相关产品推荐
相关产品推荐

