当前位置: 代码迷 >> 综合 >> CCF201403-3命令行选项(c++,字符串处理)
  详细解决方案

CCF201403-3命令行选项(c++,字符串处理)

热度:11   发布时间:2023-12-17 02:46:12.0
试题编号: 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

 

        本题大意是给定一个格式,再给几个命令行,命令行中包括选项或参数,要求输出命令行中符合格式条件的选项或参数。

        本题难点在于命令行中的选项或参数是由空格分隔开的,处理输入和将选项或参数取出时比较麻烦。输入的问题可以用c++中的getline函数来解决,getline作用是接收一行数据;需要注意的是,程序开始时输入了一个字符串和一个数字,getline函数会将输入数字时的换行符接收上,导致接收的第一行命令行为空,所以要在输入数字的语句后加getchar(),用于接收换行符。取出选项和参数的问题可以用strtok函数来解决,这个函数类似于java中的split函数,用于分割字符串。

        若选项带参数,需要输出最后一个参数。这个问题用一个map来解决,map的key为选项,value储存最后一次出现的参数。代码如下:

#include<iostream>
#include<string.h>
#include<map>
using namespace std;
string format;    //格式字符串
char word[256];    //输入的命令行
int n;
int main()
{cin>>format>>n;getchar();    //接收上一句的换行符for(int i=0;i<n;i++){map<string,string> m;bool flag=false;cin.getline(word,256);char *cmd=strtok(word," ");    //此时取出的是命令行的名字,应该忽略。cmd=strtok(NULL," ");    //此后strtok的参数都应该是NULL,此时取出的是第一个选项char *temp=NULL;while(cmd){//若取出的字符串是一个选项,即一个减号加一个字母if(strlen(cmd)==2 && cmd[0]=='-'){//查找这个选项在不在格式中int pos=format.find(cmd[1]);if(pos==-1)break;//若map中还没有出现过这个选项,则添加进去if(m.find(cmd)==m.end())m[cmd]=="";//temp取出当前选项后面的字符串temp=strtok(NULL," ");//判断当前选项带不带参,如果带参数就把temp保存到map中。if(format[pos+1]==':' && temp){m[cmd]=temp;flag=true;}}//若当前遇到了不是选项的字符串就退出,当前命令行剩余的字符串全部忽略。elsebreak;//现在的temp为当前选项的后一个字符串//若当前的字符串是个带参的选项,那么就跳到temp的后面的那个字符串上if(flag){cmd=strtok(NULL," ");flag=false;}//若当前选项不带参,就把temp作为下一个选项来处理。elsecmd=temp;}cout<<"Case "<<i+1<<":";for(map<string,string>::iterator it=m.begin();it!=m.end();it++){cout<<" "<<it->first;if(it->second!="")cout<<" "<<it->second;}cout<<endl;}return 0;
}