C++中解析状态字符串并填充状态转换信息的技术问题
C++ 解析状态机格式字符串实现修正
问题需求
需要解析特定格式的字符串,生成包含输入触发条件及对应跳转目标状态的状态信息。现有代码无法正确提取状态名称(会包含n{前缀),且无法提取转换信息,需修正实现。
示例输入字符串
i{OPEN}a{LOCKED}s{n{OPEN}t{i{PUSH}d{CLOSED}}t{i{PULL}d{OPEN}}t{i{TURN}d{OPEN}}}s{n{CLOSED}t{i{PUSH}d{CLOSED}}t{i{PULL}d{OPEN}}t{i{TURN}d{LOCKED}}}s{n{LOCKED}t{i{PUSH}d{LOCKED}}t{i{PULL}d{LOCKED}}t{i{TURN}d{CLOSED}}}
格式规则
s{...}表示一个状态,所有状态信息位于大括号内n{xxx}表示状态名称为xxx,嵌套在s{}中t{...}表示状态转换规则,一个状态可包含多个t{}块t{}内的i{xxx}是触发转换的输入值,d{xxx}是跳转的目标状态,二者顺序不固定i{xxx}表示初始状态名称,a{xxx}表示接受状态名称,二者可出现在字符串任意位置(包括s{}外)
修正后的代码实现
类定义
#include <iostream> #include <string> #include <unordered_map> #include <vector> // 转换规则类 struct Transition { std::string input; std::string targetState; }; // 状态类 struct State { std::string name; std::vector<Transition> transitions; }; // 全局状态机信息 std::unordered_map<std::string, State> states; std::string initialState; std::string acceptState;
解析核心函数
// 辅助函数:提取大括号内的纯内容,同时移动迭代器到闭合括号后 std::string extractBracketContent(std::string::iterator& it) { std::string content; ++it; // 跳过开头的'{' int bracketCount = 1; while (it != content.end() && bracketCount > 0) { if (*it == '{') { bracketCount++; } else if (*it == '}') { bracketCount--; if (bracketCount == 0) { ++it; // 跳过闭合的'}' break; } } content += *it; ++it; } return content; } // 解析状态机字符串 void parseAndPopulateStates(const std::string& inputStr) { auto it = inputStr.begin(); while (it != inputStr.end()) { if (*it == 'i') { // 提取初始状态 ++it; initialState = extractBracketContent(it); } else if (*it == 'a') { // 提取接受状态 ++it; acceptState = extractBracketContent(it); } else if (*it == 's') { // 解析单个状态块 ++it; std::string stateContent = extractBracketContent(it); auto stateIt = stateContent.begin(); State currentState; while (stateIt != stateContent.end()) { if (*stateIt == 'n') { // 提取纯状态名称 ++stateIt; currentState.name = extractBracketContent(stateIt); } else if (*stateIt == 't') { // 解析单条转换规则 ++stateIt; std::string transContent = extractBracketContent(stateIt); auto transIt = transContent.begin(); Transition trans; while (transIt != transContent.end()) { if (*transIt == 'i') { ++transIt; trans.input = extractBracketContent(transIt); } else if (*transIt == 'd') { ++transIt; trans.targetState = extractBracketContent(transIt); } else { // 跳过空格等无关字符 ++transIt; } } currentState.transitions.push_back(trans); } else { // 跳过空格等无关字符 ++stateIt; } } states[currentState.name] = currentState; } else { // 跳过空格等无关字符 ++it; } } }
测试与输出函数
// 打印解析结果 void printStateMachine() { std::cout << "初始状态: " << initialState << std::endl; std::cout << "接受状态: " << acceptState << std::endl; std::cout << "\n状态转换信息:" << std::endl; for (const auto& pair : states) { const State& state = pair.second; std::cout << "\n状态: " << state.name << std::endl; for (const Transition& trans : state.transitions) { std::cout << " 输入[" << trans.input << "] -> 目标状态[" << trans.targetState << "]" << std::endl; } } } int main() { std::string input = "i{OPEN}a{LOCKED}s{n{OPEN}t{i{PUSH}d{CLOSED}}t{i{PULL}d{OPEN}}t{i{TURN}d{OPEN}}}s{n{CLOSED}t{i{PUSH}d{CLOSED}}t{i{PULL}d{OPEN}}t{i{TURN}d{LOCKED}}}s{n{LOCKED}t{i{PUSH}d{LOCKED}}t{i{PULL}d{LOCKED}}t{i{TURN}d{CLOSED}}}"; parseAndPopulateStates(input); printStateMachine(); return 0; }
关键修正点
- 纯内容提取:通过辅助函数
extractBracketContent直接获取{}内部的纯文本,彻底解决状态名称携带n{前缀的问题。 - 转换规则兼容:遍历
t{}内容时分别提取i{}和d{}的值,支持二者任意顺序。 - 鲁棒性处理:添加对空格等无关字符的跳过逻辑,避免解析流程中断。
- 嵌套括号兼容:辅助函数通过括号计数处理嵌套场景,兼容更复杂的输入格式。
内容的提问来源于stack exchange,提问作者Stormmv
相关产品推荐
相关产品推荐

