程序最美(寻路)

你还在坚持练习你的技术吗?运动员天天训练,音乐家也会演练更难的曲章。你呢?

参数解析

参数解析

         一函数传递的参数为以字符串,其具体格式是用”$”和”|”来间隔文件名和数据项名,我们的工作时将参数字符串进行解析,得到一个个具体的文件名-数据项的形式。

         我们可以采用顺序扫描的方法进行解析,也可以利用状态转换图进行解析。

         字符串的格式为:文件之间用”$”来间隔,数据项之间用”|”来间隔。

         例如:

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;
}

 

posted on 2013-09-11 10:37  unixfy  阅读(1001)  评论(0编辑  收藏  举报

导航