参数解析
参数解析
一函数传递的参数为以字符串,其具体格式是用”$”和”|”来间隔文件名和数据项名,我们的工作时将参数字符串进行解析,得到一个个具体的文件名-数据项的形式。
我们可以采用顺序扫描的方法进行解析,也可以利用状态转换图进行解析。
字符串的格式为:文件之间用”$”来间隔,数据项之间用”|”来间隔。
例如:
A|01|02|03|04|05|$B|01|02|03|$C|01|09|$
该字符串指明了四个文件:A、B、C、D,其中,A文件的数据项为01、02、03、04、05,B文件的数据项为01、02、03,C文件的数据项为01、09。
我们是想得到如下的结果:
A 01
A 02
A 03
A 04
A 05
B 01
B 02
B 03
C 01
C 09
我们还想得到如下的结果形式:
A 01 02 03 04 05
B 01 02 03
C 01 09
一、利用状态自动机
我们首先给出自动转换机的方法来解决该问题,其中状态转换图如下:
利用自动机编程进行参数解析的程序如下:
// 自动机 #include <iostream> #include <string> #include <vector> #include <map> using namespace std; struct FileData { string file; string data; }; struct FileDataItems { string file; vector<string> dataItems; }; void ParaAnalysis(const string& para, vector<FileData>& fds) { fds.clear(); string file, data; FileData fd; int state = 1; for (auto i = 0; i < para.size(); ++i) { switch (state) { case 1: if (para[i] == '|') { state = 2; } else { file += para[i]; } break; case 2: if (para[i] == '|') { fd.file = file; fd.data = data; fds.push_back(fd); data.clear(); } else if (para[i] == '$') { file.clear(); state = 1; } else { data += para[i]; } break; } } } void ParaAnalysis_Items(const string& para, vector<FileDataItems>& fdis) { fdis.clear(); string file, data; FileDataItems fdi; int state = 1; for (auto i = 0; i < para.size(); ++i) { switch (state) { case 1: if (para[i] == '|') { fdi.file = file; fdis.push_back(fdi); state = 2; } else { file += para[i]; } break; case 2: if (para[i] == '|') { fdis[fdis.size() - 1].dataItems.push_back(data); data.clear(); } else if (para[i] == '$') { file.clear(); state = 1; } else { data += para[i]; } break; } } } int main() { string para; getline(cin, para); vector<FileData> fds; ParaAnalysis(para, fds); for (auto i = 0; i != fds.size(); ++i) { cout << fds[i].file << '\t' << fds[i].data << endl; } cout << endl << endl; vector<FileDataItems> fdis; ParaAnalysis_Items(para, fdis); for (auto i = 0; i != fdis.size(); ++i) { cout << fdis[i].file << '\t'; for (auto j = 0; j != fdis[i].dataItems.size(); ++j) { cout << fdis[i].dataItems[j] << '\t'; } cout << endl; } return 0; }
二、顺序扫描
顺序扫描的原理是设置一个bool型标识量,用来表明是否是file区域。具体的代码如下:
// 顺序扫描 void ParaAnalysisSeqScan(const string& para, vector<FileData>& fds) { fds.clear(); string file, data; FileData fd; bool fflag = true; for (auto i = 0; i < para.size(); ++i) { if (fflag) { if (para[i] == '|') { fflag = false; } else { file += para[i]; } } else { if (para[i] == '|') { fd.file = file; fd.data = data; fds.push_back(fd); data.clear(); } else if (para[i] == '$') { file.clear(); fflag = true; } else { data += para[i]; } } } } void ParaAnalysisSeqScan_Items(const string& para, vector<FileDataItems>& fdis) { fdis.clear(); string file, data; FileDataItems fdi; bool fflag = true; for (auto i = 0; i < para.size(); ++i) { if (fflag) { if (para[i] == '|') { fdi.file = file; fdis.push_back(fdi); fflag = false; } else { file += para[i]; } } else { if (para[i] == '|') { fdis[fdis.size() - 1].dataItems.push_back(data); data.clear(); } else if (para[i] == '$') { file.clear(); fflag = true; } else { data += para[i]; } } } }
三、总结
上面利用状态自动机和顺序扫描的方法进行参数的解析,其实顺序扫描和自动机方法是一致的,只不过自动机的state变为了fflag。由于state只有1和2两种状态(分别表示了file和data),所以可以用bool型的fflag来代替。另外switch-case语句完全可以用if-elseif-else语句来代替。
利用自动机编程,首先需要划分好状态,然后根据各个状态分析该状态下的具体操作以及什么情况下导致该状态的变迁。
附:自动机程序和顺序扫描程序
// 自动机+顺序扫描 #include <iostream> #include <string> #include <vector> #include <map> using namespace std; struct FileData { string file; string data; }; struct FileDataItems { string file; vector<string> dataItems; }; void ParaAnalysis(const string& para, vector<FileData>& fds) { fds.clear(); string file, data; FileData fd; int state = 1; for (auto i = 0; i < para.size(); ++i) { switch (state) { case 1: if (para[i] == '|') { state = 2; } else { file += para[i]; } break; case 2: if (para[i] == '|') { fd.file = file; fd.data = data; fds.push_back(fd); data.clear(); } else if (para[i] == '$') { file.clear(); state = 1; } else { data += para[i]; } break; } } } void ParaAnalysis_Items(const string& para, vector<FileDataItems>& fdis) { fdis.clear(); string file, data; FileDataItems fdi; int state = 1; for (auto i = 0; i < para.size(); ++i) { switch (state) { case 1: if (para[i] == '|') { fdi.file = file; fdis.push_back(fdi); state = 2; } else { file += para[i]; } break; case 2: if (para[i] == '|') { fdis[fdis.size() - 1].dataItems.push_back(data); data.clear(); } else if (para[i] == '$') { file.clear(); state = 1; } else { data += para[i]; } break; } } } void ParaAnalysisSeqScan(const string& para, vector<FileData>& fds) { fds.clear(); string file, data; FileData fd; bool fflag = true; for (auto i = 0; i < para.size(); ++i) { if (fflag) { if (para[i] == '|') { fflag = false; } else { file += para[i]; } } else { if (para[i] == '|') { fd.file = file; fd.data = data; fds.push_back(fd); data.clear(); } else if (para[i] == '$') { file.clear(); fflag = true; } else { data += para[i]; } } } } void ParaAnalysisSeqScan_Items(const string& para, vector<FileDataItems>& fdis) { fdis.clear(); string file, data; FileDataItems fdi; bool fflag = true; for (auto i = 0; i < para.size(); ++i) { if (fflag) { if (para[i] == '|') { fdi.file = file; fdis.push_back(fdi); fflag = false; } else { file += para[i]; } } else { if (para[i] == '|') { fdis[fdis.size() - 1].dataItems.push_back(data); data.clear(); } else if (para[i] == '$') { file.clear(); fflag = true; } else { data += para[i]; } } } } int main() { string para; getline(cin, para); vector<FileData> fds; //ParaAnalysis(para, fds); ParaAnalysisSeqScan(para, fds); for (auto i = 0; i != fds.size(); ++i) { cout << fds[i].file << '\t' << fds[i].data << endl; } cout << endl << endl; vector<FileDataItems> fdis; //ParaAnalysis_Items(para, fdis); ParaAnalysisSeqScan_Items(para, fdis); for (auto i = 0; i != fdis.size(); ++i) { cout << fdis[i].file << '\t'; for (auto j = 0; j != fdis[i].dataItems.size(); ++j) { cout << fdis[i].dataItems[j] << '\t'; } cout << endl; } return 0; }
(完)
文档信息
·版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0
·博客地址:http://www.cnblogs.com/unixfy
·博客作者:unixfy
·作者邮箱:goonyangxiaofang(AT)163.com
·如果你觉得本博文的内容对你有价值,欢迎对博主 小额赞助支持
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· C# 13 中的新增功能实操
· Ollama本地部署大模型总结
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(4)
· 卧槽!C 语言宏定义原来可以玩出这些花样?高手必看!
· langchain0.3教程:从0到1打造一个智能聊天机器人