程序最美(寻路)

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

参数解析

参数解析

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

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

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

         例如:

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   unixfy  阅读(1004)  评论(0编辑  收藏  举报

编辑推荐:
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
阅读排行:
· C# 13 中的新增功能实操
· Ollama本地部署大模型总结
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(4)
· 卧槽!C 语言宏定义原来可以玩出这些花样?高手必看!
· langchain0.3教程:从0到1打造一个智能聊天机器人
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示