CCF 201403-3 命令行选项

试题编号:201403-3
试题名称:命令行选项
时间限制:1.0s
内存限制:256.0MB

问题描述

请你写一个命令行分析程序,用以分析给定的命令行里包含哪些选项。每个命令行由若干个字符串组成,它们之间恰好由一个空格分隔。这些字符串中的第一个为该命令行工具的名字,由小写字母组成,你的程序不用对它进行处理。在工具名字之后可能会包含若干选项,然后可能会包含一 些不是选项的参数。

选项有两类:带参数的选项和不带参数的选项。一个合法的无参数选项的形式是一个减号后面跟单个小写字母,如-a-b。而带参数选项则由两个由空格分隔的字符串构成,前者的格式要求与无参数选项相同,后者则是该选项的参数,是由小写字母,数字和减号组成的非空字符串。

该命令行工具的作者提供给你一个格式字符串以指定他的命令行工具需要接受哪些选项。这个字符串由若干小写字母和冒号组成,其中的每个小写字母表示一个该程序接受的选项。如果该小写字母后面紧跟了一个冒号,它就表示一个带参数的选项,否则则为不带参数的选项。例如, ab:m: 表示该程序接受三种选项,即-a(不带参数),-b(带参数), 以及-m(带参数)。

命令行工具的作者准备了若干条命令行用以测试你的程序。对于每个命令行,你的工具应当一直向后分析。当你的工具遇到某个字符串既不是合法的选项,又不是某个合法选项的参数时,分析就停止。命令行剩余的未分析部分不构成该命令的选项,因此你的程序应当忽略它们。

输入格式

输入的第一行是一个格式字符串,它至少包含一个字符,且长度不超过 52。格式字符串只包含小写字母和冒号,保证每个小写字母至多出现一次,不会有两个相邻的冒号,也不会以冒号开头。
输入的第二行是一个正整数 N(1 ≤ N ≤ 20),表示你需要处理的命令行的个数。
接下来有 N 行,每行是一个待处理的命令行,它包括不超过 256 个字符。该命令行一定是若干个由单个空格分隔的字符串构成,每个字符串里只包含小写字母,数字和减号。

输出格式

输出有 N 行。其中第 i 行以Case i: 开始,然后应当有恰好一个空格,然后应当按照字母升序输出该命令行中用到的所有选项的名称,对于带参数的选项,在输出它的名称之后还要输出它的参数。如果一个选项在命令行中出现了多次,只输出一次。如果一个带参数的选项在命令行中出 现了多次,只输出最后一次出现时所带的参数。

样例输入

albw:x
4
ls -a -l -a documents -b
ls
ls -w 10 -x -w 15
ls -a -b -c -d -e -l

样例输出

Case 1: -a -l
Case 2:
Case 3: -w 15 -x
Case 4: -a -b

思路

字符串模拟。把每一行指令以空格为间隔处理出来放入vector中,然后按照题意进行判断就行了。

题目中的坑点:指令的最后一个选项可能是带参选项,需要进行特判,否则会越界

需要注意的是:当cingetline混用时,在cin的后面会有一个换行符,需要用cin.get()cin.ignore()处理掉这个换行符

代码

#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define ms(a,b) memset(a,b,sizeof(a))
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int maxn=1e6+10;
const int mod=1e9+7;
const int maxm=1e3+10;
using namespace std;
string tmp;
vector<string>res;
// 拆分命令行
void get(string s)
{
    tmp="";
    res.clear();
    int l=s.length();
    for(int i=0;i<l;i++)
    {
        if(s[i]==' ')
        {
            if(tmp=="")
            {
                tmp="";
                continue;
            }
            string ttmp="";
            for(auto j:tmp)
                if(j!=' ')
                    ttmp+=j;
            if(ttmp=="")
                continue;
            res.push_back(ttmp);
            tmp="";
            i++;
        }
        tmp+=s[i];
    }
    res.push_back(tmp);
}
bool check(string s)
{
    if(s[0]=='-')
        return true;
    return false;
}
int main(int argc, char const *argv[])
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    string s,s1;
    int n;
    cin>>s;
    cin.ignore();
    int l=s.length();
    map<char,int>vis;
    for(int i=0;i<l-1;i++)
    {
        // 带参选项标记为1,不带参选项标记为-1
        if(s[i+1]==':')
            vis[s[i]]=1,i++;
        else vis[s[i]]=-1;
    }
    vis[s[l-1]]=-1;
    cin>>n;
    cin.ignore();
    int _=0;
    while(n--)
    {
        set<string>st;
        getline(cin,s1);
        get(s1);
        int sz=res.size();
        map<string,string>mp;
        for(int i=1;i<sz;i++)
        {
            string ss=res[i];
            // 判断是否是参数
            int flag=0;
            char c=0;
            if(ss[0]=='-'&&ss.length()==2)
                c=ss[1],flag=1;
            if((flag&&!vis[c])||!(i|flag)||!flag)
                break;
            if(vis[c]==-1)
            {
                st.insert(ss);
                if(!check(res[i+1]))
                    break;
            }
            if(vis[c]==1)
            {
                if(i==sz-1)
                    continue;
                mp[ss]=res[i+1];
                st.insert(ss);
                i++;
            }
        }
        cout<<"Case "<<++_<<":";
        for(auto i:st)
        {
            cout<<" "<<i;
            if(mp[i]!="")
                cout<<" "<<mp[i];
        }
        cout<<endl;
    }
    return 0;
}

一个因为自己傻逼而错了无数遍的题。错误原因:把所有的指令都当成了ls开头;越界访问vector
我是大傻逼

Last modification:April 1st, 2021 at 12:40 pm
如果觉得我的文章对你有用,请随意赞赏