问题描述
请你写一个命令行分析程序,用以分析给定的命令行里包含哪些选项。每个命令行由若干个字符串组成,它们之间恰好由一个空格分隔。这些字符串中的第一个为该命令行工具的名字,由小写字母组成,你的程序不用对它进行处理。在工具名字之后可能会包含若干选项,然后可能会包含一 些不是选项的参数。
选项有两类:带参数的选项和不带参数的选项。一个合法的无参数选项的形式是一个减号后面跟单个小写字母,如"-a" 或"-b"。而带参数选项则由两个由空格分隔的字符串构成,前者的格式要求与无参数选项相同,后者则是该选项的参数,是由小写字母,数字和减号组成的非空字符串。
该命令行工具的作者提供给你一个格式字符串以指定他的命令行工具需要接受哪些选项。这个字符串由若干小写字母和冒号组成,其中的每个小写字母表示一个该程序接受的选项。如果该小写字母后面紧跟了一个冒号,它就表示一个带参数的选项,否则则为不带参数的选项。例如, "ab:m:" 表示该程序接受三种选项,即"-a"(不带参数),"-b"(带参数), 以及"-m"(带参数)。
命令行工具的作者准备了若干条命令行用以测试你的程序。对于每个命令行,你的工具应当一直向后分析。当你的工具遇到某个字符串既不是合法的选项,又不是某个合法选项的参数时,分析就停止。命令行剩余的未分析部分不构成该命令的选项,因此你的程序应当忽略它们。
选项有两类:带参数的选项和不带参数的选项。一个合法的无参数选项的形式是一个减号后面跟单个小写字母,如"-a" 或"-b"。而带参数选项则由两个由空格分隔的字符串构成,前者的格式要求与无参数选项相同,后者则是该选项的参数,是由小写字母,数字和减号组成的非空字符串。
该命令行工具的作者提供给你一个格式字符串以指定他的命令行工具需要接受哪些选项。这个字符串由若干小写字母和冒号组成,其中的每个小写字母表示一个该程序接受的选项。如果该小写字母后面紧跟了一个冒号,它就表示一个带参数的选项,否则则为不带参数的选项。例如, "ab:m:" 表示该程序接受三种选项,即"-a"(不带参数),"-b"(带参数), 以及"-m"(带参数)。
命令行工具的作者准备了若干条命令行用以测试你的程序。对于每个命令行,你的工具应当一直向后分析。当你的工具遇到某个字符串既不是合法的选项,又不是某个合法选项的参数时,分析就停止。命令行剩余的未分析部分不构成该命令的选项,因此你的程序应当忽略它们。
输入格式
输入的第一行是一个格式字符串,它至少包含一个字符,且长度不超过 52。格式字符串只包含小写字母和冒号,保证每个小写字母至多出现一次,不会有两个相邻的冒号,也不会以冒号开头。
输入的第二行是一个正整数 N(1 ≤ N ≤ 20),表示你需要处理的命令行的个数。
接下来有 N 行,每行是一个待处理的命令行,它包括不超过 256 个字符。该命令行一定是若干个由单个空格分隔的字符串构成,每个字符串里只包含小写字母,数字和减号。
输入的第二行是一个正整数 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
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
思路:考察对字符串处理,对题意细节的把握,细节还是很多的,满分较难。
Case 2:
Case 3: -w 15 -x
Case 4: -a -b
解题步骤:
1、将每次输入的命令行字符串以空格分开装进vector<string>容器中
2、然后对容器中的每个字符串进行判断,第一个字符串是工具名不用判断,然后从容器中第二个开始判断当前字符串是否为合法命令。这里要分为2中情况:一种是命令带参数的时,一种是命令不带参数时。
当命令不带参数时:该字符串长度为2且以‘-’开头,且第二个字符出现在格式字符串中-->该命令合法为命令。
当该命令带参数时:该字符串长度为2且以‘-‘开头,且第二个字符串出现在格式字符串中,还要看这个字符串后面是否有对应的参数字符串,若有,该命令合法,否则不合法,停止分析。
3、合法命令的集合存放在map<string,string>中,因为map中的key是要求按key升序排列(命令都是-字母开头),且key-value的value可以用来存放参数值(无参设为null)。map中插入合法命令时应考虑该命令是否已经存在map中。对于无参的命令,直接插入。对于有参数的命令:若不存在map中直接插入该命令和参数值,若已经存在就将该命令的参数值更新(C++的map中对于key相同的插入不会覆盖,而是放弃处理)
4、按格式输出map冲存放的合法命令行
AC代码(VC上输入可能有点问题,但是在Dev上没问题,所以提交也没问题):
#include<iostream>
#include<map>
#include<vector>
#include<windows.h>
#include<string>
using namespace std;
int isRepeat(map<string,string> m,string s) //判断命令是否重复
{
map<string,string>::iterator it;
it = m.find(s);
if(it == m.end())
{
return 0;
}else
{
return 1;
}
}
int find(string str,char c) // 查找命令是否存在和是否带参
{
int i;
int flag = str.find(c);
if(flag != -1) // 该命令存在
{
if(flag < str.length()-1 && str.at(flag+1) == ':')
{
return 2; // 有参数
}else
{
return 1; // 无参数
}
}
return 0; //命令不存在
}
int main()
{
string str;
int i,j,n;
cin>>str;
cin>>n;
getchar();
for(i = 0; i < n; i++)
{
vector<string> v;
map<string,string> m;
string op;
getline(cin,op);
string line = op;
int t;
for(t = line.find(" "); t != -1; t = line.find(" ")) //将字符串以空格切割装进vector中
{
v.push_back(line.substr(0,t));
line = line.substr(t+1);
}
v.push_back(line);
vector<string>::iterator it;
for(it = v.begin()+1; it != v.end(); it++)
{
string ss = *it;
if(ss.at(0) == '-' && ss.length() == 2 && find(str,ss.at(1)))
{
if(find(str,ss.at(1)) == 1) //无参数命令
{
m.insert(pair<string,string>(ss,"null"));
}else if(find(str,ss.at(1)) == 2 && ++it != v.end()) // 有参数命令
{
if(isRepeat(m,ss)) //有重复的
{
m[ss] = *it; //修改key对应的值
}else
{
m.insert(pair<string,string>(ss,*it));
}
}else //有参数命令(如 -w),但是后面没参数,也为不合法的命令
{
break;
}
}else
{
break;
}
}
cout<<"Case "<<i+1<<":";
map<string,string>::iterator itr;
for(itr = m.begin(); itr != m.end(); itr++)
{
if(itr->second != "null")
{
cout<<" "<<itr->first<<" "<<itr->second;
}else
{
cout<<" "<<itr->first;
}
}
cout<<endl;
}
system("pause");
return 0;
}