参数解析之写入参数解析
之前我们有篇关于参数解析的文章《参数解析》,在文章中我们讨论了对函数参数进行了解析,分为两种方法:状态转换图和顺序扫描。函数参数为一个字符串,格式为:
file1|dataitem1|dataitem2|dateitem3|$file2|dataitem4|dataitem5|$file3|dataitem6|$
通过我们的解析得到:
file1 dataitem1 dataitem2 dataitem3
file2 dataitem4 dataitem5
file3 dataitem6
这里的参数解析是针对read函数的参数解析,read函数根据输入参数的格式,读取相应的文件和字段,然后由输出参数将读取到的数据返回。输出参数的格式与输入参数的格式一致,即:file1|dataitem1的数据|dataitem2的数据|dataitem3的数据|$file2|dataitem4的数据|dataitem5的数据|$file3|dataitem6的数据|$。
上面是针对read函数的参数解析,对于write函数来说,参数解析不仅仅需要解析要write的文件和字段,而且还要将待write数据解析出来。
write文件和字段的格式与read函数的输入参数格式一致,即:file1|dataitem1|dataitem2|dateitem3|$file2|dataitem4|dataitem5|$file3|dataitem6|$,待write数据的格式为:dataitem1的数据|dataitem2的数据|dateitem3的数据|$dataitem4的数据|dataitem5的数据|$dataitem6的数据|$。所以,我们对write函数的参数解析需要解析以上两个参数。
下面我们给出实现的程序:
// write函数参数解析 #include <iostream> #include <string> #include <vector> using namespace std; struct FileDataItems { string file; vector<string> dataItems; }; 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 Write_ParaAnalysis(const string& fileDataItem, vector<FileDataItems>& fdis, const string& srcStr, vector<string>& srcData) { fdis.clear(); srcData.clear(); ParaAnalysis_Items(fileDataItem, fdis); string dataItem; for (auto i = 0; i != srcStr.size(); ++i) { switch (srcStr[i]) { case '|': srcData.push_back(dataItem); dataItem.clear(); break; case '$': dataItem.clear(); break; default: dataItem += srcStr[i]; break; } } } int main() { vector<FileDataItems> fdis; vector<string> srcData; int idx = 0; Write_ParaAnalysis("file1|dataitem1|dataitem2|dateitem3|$file2|dataitem4|dataitem5|$file3|dataitem6|$", fdis, "dataitem1的数据|dataitem2的数据|dateitem3的数据|$dataitem4的数据|dataitem5的数据|$dataitem6的数据|$", srcData); for (auto i = 0; i != fdis.size(); ++i) { for (auto j = 0; j != fdis[i].dataItems.size() && idx != srcData.size(); ++j, ++idx) { cout << fdis[i].dataItems[j] << '\t' << srcData[idx] << endl; } } cout << endl; idx = 0; Write_ParaAnalysis("file1|dataitem3|dataitem2|dateitem1|$file2|dataitem5|dataitem4|$file3|dataitem6|$", fdis, "dataitem3的数据|dataitem2的数据|dateitem1的数据|$dataitem5的数据|dataitem4的数据|$dataitem6的数据|$", srcData); for (auto i = 0; i != fdis.size(); ++i) { for (auto j = 0; j != fdis[i].dataItems.size() && idx != srcData.size(); ++j, ++idx) { cout << fdis[i].dataItems[j] << '\t' << srcData[idx] << endl; } } return 0; }
对于参数1的解析,我们还是沿用之前read函数的参数解析。对于参数2,我们顺序扫描,利用switch-case结构,检测当前字符,分为三种情况:’|’、’$’、其他,对不同的情况,进行相应的处理。
对于参数1和参数2之间的匹配,我们是顺序匹配的,参数1的解析结果有文件结构。参数2的解析没有文件结构,而是顺序下来的。也就是说,我们没有对参数2进行文件结构的检测,这样如果参数2中的文件结构和参数1中的文件结构不一致,只要数据项个数一致,就没问题。这种情况,不是太符合我们的要求。如果参数2的文件结构和参数1的文件结构不一致,我们应该返回错误,而不是按照正确的情况进行处理。
下面,我们给出检测参数2和参数1之间的文件结构是否一致的一种实现。对于参数1的解析依然沿用之前的解析方法。参数2的解析,不用到状态转换图来实现,而是对参数2进行顺序扫描,检测当前字符,根据当前字符的情况进行相应的处理。将参数1和参数2都解析完后,我们对两个参数中的文件结构进行匹配,如果匹配成功,则返回true,如果不成功,则返回false。下面是相应的程序实现:
// 检测参数1和参数2的文件结构是否一致 #include <iostream> #include <string> #include <vector> using namespace std; struct FileDataItems { string file; vector<string> dataItems; }; struct FileData { vector<string> fData; }; 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 Para2Analysis(const string& srcStr, vector<string>& srcData) { srcData.clear(); string dataItem; for (auto i = 0; i != srcStr.size(); ++i) { switch (srcStr[i]) { case '|': srcData.push_back(dataItem); dataItem.clear(); break; case '$': dataItem.clear(); break; default: dataItem += srcStr[i]; break; } } } void Para2Analysis_File(const string& srcStr, vector<FileData>& srcData) { srcData.clear(); string datus; FileData fd; for (auto i = 0; i != srcStr.size(); ++i) { switch (srcStr[i]) { case '|': fd.fData.push_back(datus); datus.clear(); break; case '$': srcData.push_back(fd); fd.fData.clear(); break; default: datus += srcStr[i]; break; } } } void Write_ParaAnalysis(const string& fileDataItem, vector<FileDataItems>& fdis, const string& srcStr, vector<string>& srcData) { fdis.clear(); srcData.clear(); ParaAnalysis_Items(fileDataItem, fdis); string dataItem; for (auto i = 0; i != srcStr.size(); ++i) { switch (srcStr[i]) { case '|': srcData.push_back(dataItem); dataItem.clear(); break; case '$': dataItem.clear(); break; default: dataItem += srcStr[i]; break; } } } void Write_ParaAnalysis_Func(const string& fileDataItem, vector<FileDataItems>& fdis, const string& srcStr, vector<string>& srcData) { fdis.clear(); srcData.clear(); ParaAnalysis_Items(fileDataItem, fdis); Para2Analysis(srcStr, srcData); } void Write_ParaAnalysis_File(const string& fileDataItem, vector<FileDataItems>& fdis, const string& srcStr, vector<FileData>& srcData) { fdis.clear(); srcData.clear(); ParaAnalysis_Items(fileDataItem, fdis); Para2Analysis_File(srcStr, srcData); } bool DetectFileStructure(const vector<FileDataItems>& fdis, const vector<FileData>& srcData) { if (fdis.size() != srcData.size()) { return false; } for (auto i = 0; i != fdis.size(); ++i) { if (fdis[i].dataItems.size() != srcData[i].fData.size()) { return false; } } return true; } int main() { vector<FileDataItems> fdis; vector<FileData> srcData; int idx = 0; Write_ParaAnalysis_File("file1|dataitem1|dataitem2|dateitem3|$file2|dataitem4|dataitem5|$file3|dataitem6|$", fdis, "dataitem1的数据|dataitem2的数据|dateitem3的数据|$dataitem4的数据|dataitem5的数据|$dataitem6的数据|$", srcData); if (DetectFileStructure(fdis, srcData)) { for (auto i = 0; i != fdis.size(); ++i) { for (auto j = 0; j != fdis[i].dataItems.size(); ++j) { cout << fdis[i].dataItems[j] << '\t' << srcData[i].fData[j] << endl; } } } else { cout << "参数1和参数2文件结构不匹配" << endl; } cout << endl; idx = 0; Write_ParaAnalysis_File("file1|dataitem3|dataitem2|dateitem1|$file2|dataitem5|dataitem4|$file3|dataitem6|$", fdis, "dataitem3的数据|dataitem2的数据|dateitem1的数据|$dataitem5的数据|dataitem4的数据|$dataitem6的数据|$", srcData); if (DetectFileStructure(fdis, srcData)) { for (auto i = 0; i != fdis.size(); ++i) { for (auto j = 0; j != fdis[i].dataItems.size(); ++j) { cout << fdis[i].dataItems[j] << '\t' << srcData[i].fData[j] << endl; } } } else { cout << "参数1和参数2文件结构不匹配" << endl; } cout << endl; idx = 0; Write_ParaAnalysis_File("file1|dataitem3|dataitem2|dateitem1|$file2|dataitem5|dataitem4|$file3|dataitem6|$", fdis, "dataitem3的数据|$dataitem2的数据|dateitem1的数据|$dataitem5的数据|dataitem4的数据|dataitem6的数据|$", srcData); if (DetectFileStructure(fdis, srcData)) { for (auto i = 0; i != fdis.size(); ++i) { for (auto j = 0; j != fdis[i].dataItems.size(); ++j) { cout << fdis[i].dataItems[j] << '\t' << srcData[i].fData[j] << endl; } } } else { cout << "参数1和参数2文件结构不匹配" << endl; } return 0; }
总结
本文我们对write函数的两个参数进行解析,先对参数2直接解析,并没有检测两个参数的文件结构是否一致;之后我们又对参数1和参数2的文件结构是否一致。