2014年首届CCF软件能力认证试题第三题

时间:2022-09-04 21:31:08

题目3 命令行选项
时间限制: 1 秒
空间限制: 256 MB
问题描述
请你写一个命令行分析程序,用以分析给定的命令行里包含哪些选项。
每个命令行由若干个字符串组成,它们之间恰好由一个空格分隔。这些字
符串中的第一个为该命令行工具的名字,由小写字母组成,你的程序不用
对它进行处理。在工具名字之后可能会包含若干选项,然后可能会包含一
些不是选项的参数。
选项有两类:带参数的选项和不带参数的选项。一个合法的无参数
选项的形式是一个减号后面跟单个小写字母,如”-a” 或”-b”。而带参数
选项则由两个由空格分隔的字符串构成,前者的格式要求与无参数选项相
同,后者则是该选项的参数,是由小写字母,数字和减号组成的非空字符串。
该命令行工具的作者提供给你一个格式字符串以指定他的命令行工具需要接受哪些选项。这个字符串由若干小写字母和冒号组成,其中的每个小写字母表示一个该程序接受的选项。如果该小写字母后面紧跟了一个冒号,它就表示一个带参数的选项,否则则为不带参数的选项。例如,”ab:m:” 表示该程序接受三种选项,即”-a”(不带参数),”-b”(带参数),
以及”-m”(带参数)。
命令行工具的作者准备了若干条命令行用以测试你的程序。对于每个命令行,你的工具应当一直向后分析。当你的工具遇到某个字符串既不是合法的选项,又不是某个合法选项的参数时,分析就停止。命令行剩余的未分析部分不构成该命令的选项,因此你的程序应当忽略它们。

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

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

思路:
字符串处理的题目,要很小心=.=
一开始是解析规则字符串rule,因为命令只可能是小写字母,所以用哈希表记录每一个命令的使用规则(0 没有这个码;1 有这个码不能接参数;2 接参数 )
接下来是处理输入的字符串,根据上面的规则来处理。相同命令只输出一次,要检查前面是否已经输出该命令,输出参数是注意修改前面命令的参数(因为只输出最后一个参数)。遇到不符合的情况就退出,结束解析。

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <map>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main(){
    int i,j,cnt;
    char cc;
    std::vector< std::vector<string> > res;
    string clause[20][256];
    //memset(clause,"",sizeof(string)*20*256);
    for(i=0;i<20;i++){
    for(j=0;j<256;j++){
    clause[i][j] = "";
    }
    }
    map<char,int> map;//0 没有这个码;1 有这个码不能接参数;2 可以接参数 
    for(char ch='a';ch <= 'z';ch++){
       map.insert(pair<char,int>(ch,0));
    }
    string rule;
    //处理规则 
    cin>>rule;
    for(i=0;i<rule.length()-1;i++){
      if(rule[i]>='a'&&rule[i]<='z'&&rule[i+1]==':'){
          map[rule[i]]=2;
          continue;
      }
      else {
          map[rule[i]]=1;
      }
    }
    if(rule[rule.length()-2]==':') map[rule[rule.length()-1]]=1;
    else if(rule[rule.length()-1]==':') map[rule[rule.length()-2]]=2;
    else map[rule[rule.length()-1]]=1;
    //读入命令 
    cin>>cnt;
    scanf("%c", &cc);
    int cn = 0,num=0;
    while(cnt){
    char buffer;
    string s;
    i=0;
    //输入命令 
    while(scanf("%c", &buffer)){
    if(buffer=='\n') break;
    else if(buffer==' ') i++;
    else clause[cn][i] += buffer;    
    }
    // 处理命令 
    vector<string> ans;
    num=i;
    i=1;
    for(i=1;clause[cn][i]!="";i++){
    if(clause[cn][i][0]=='-'&&map[clause[cn][i][1]]==0) break;
    else if(clause[cn][i][0]=='-'&&map[clause[cn][i][1]]==1) {

         if(find( ans.begin( ), ans.end( ), clause[cn][i] )==ans.end()) ans.push_back(clause[cn][i]);
         }  
    else if(clause[cn][i][0]=='-'&&map[clause[cn][i][1]]==2) {

         if(find( ans.begin( ), ans.end( ), clause[cn][i] )==ans.end()) ans.push_back(clause[cn][i]);
         if(clause[cn][i+1]!=""&&clause[cn][i+1][0]!='-') {
         if(ans[ans.size()-1]==clause[cn][i]) ans.push_back(clause[cn][i+1]);
         else *(find( ans.begin( ), ans.end( ), clause[cn][i] )+1) = clause[cn][i+1];
         i++;
         continue;
         }
         else break;
         }
    else break; 
    }
    res.push_back(ans);

    cn++;
    cnt--;
    }

    for(i=0;i<res.size();i++){
     cout<<"Case "<<i+1<<": ";
    for(j=0;j<res[i].size();j++){
     cout<<res[i][j]<<" ";
    }
    cout<<endl;
    }


    system("pause");
    return 0;
    }