问题描述
请你写一个命令行分析程序,用以分析给定的命令行里包含哪些选项。每个命令行由若干个字符串组成,它们之间恰好由一个空格分隔。这些字符串中的第一个为该命令行工具的名字,由小写字母组成,你的程序不用对它进行处理。在工具名字之后可能会包含若干选项,然后可能会包含一 些不是选项的参数。
选项有两类:带参数的选项和不带参数的选项。一个合法的无参数选项的形式是一个减号后面跟单个小写字母,如"-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
解题思路
1,字符串处理想到使用c++11正则比较好处理,
2,将第一个输入的albw:x进行分析存入一个map中,方便后面的查找和确定是否带参
3,为了方便处理将每一个输出的命令行先进行去空格处理,然后使用正则将所有“”-a15”类格式的子串找出,并进行存储,作为后序处理的源。
4,题目要求按字母升序输出可以采用map,使用map的key存储特性
5,涉及的正则使用可参考网上几个博客:
https://blog.csdn.net/qq_34802416/article/details/79307102
https://blog.csdn.net/A315776/article/details/104921039
测试代码
#include<iostream>
#include<stdlib.h>
#include<regex>
#include<vector>
#include<string>
#include<iterator>
#include<map>
#include<stdio.h>
using namespace std;
typedef map<char, int> map_i_c;
typedef vector<map<char, string>> OUT;
map_i_c rule_sub;//对rule进行分解,int为1时表示有参,0时无参
bool is_find(char m) {
map_i_c::iterator itA;
for (itA = begin(rule_sub); itA != end(rule_sub); ++itA) {
if (itA->first == m) {
return true;
}
}
return false;
}
int main() {
int num;//记录个数
string rule;
cin >> rule;
cin >> num;
//vector<string> str{ "ab:l","albw:x" ,"al::xw"};
vector<string> str;
for (int i = 0; i < num+1; ++i) {
string temp;
getline(cin, temp);
str.push_back(temp);
}
//由于使用getline函数导致str对象中的sring对象比预期多一,所以进行前移一位的操作,并且将str的size重置
for (int i = 1; i < str.size(); ++i) {
str.at(i - 1) = str.at(i);
}
str.resize(num);
regex ref( "([a-z]{1,}[:]{0,1}){1,}" );
if (regex_match(rule, ref)) {//判断规则输入是否合理
for (string::iterator itA = rule.begin(); itA != rule.end();++itA) {
if (*itA >= 'a'&&*itA <= 'z') {
if (itA + 1 != rule.end()) {//防止越界
if (*(itA + 1) == ':') {
rule_sub[*itA] = 1;
}
else {
rule_sub[*itA] = 0;
}
}
else {
rule_sub[*itA] = 0;
}
}
}
//处理
int count = 1;
regex par{ " " };
for (string tmp : str) {
#if 1
tmp = regex_replace(tmp, par, "");//将空格去掉方便处理
string::const_iterator itB = tmp.begin();
string::const_iterator itE = tmp.end();
smatch result;
vector<string> res_fianl;
map<char, string> out_sub;
regex res{ "-[a-z]{1}[a-z0-9]*[\s]{0,1}" };
while (regex_search(itB, itE, result, res)) {
res_fianl.push_back(result[0]);//result[0]存放匹配到的结果
itB = result[0].second;///更新搜索起始位置,搜索剩下的字符串
}
//处理
for (string m : res_fianl) {
//cout << m << endl;
OUT out;
if (is_find(m.at(1))) {
if (rule_sub[m.at(1)] == 0) {
if (m.size() == 2) {//使用map可以实现字母升序输出
out_sub[m.at(1)] = m;
}
}
else if (rule_sub[m.at(1)] == 1) {//有参,分两种情况有正确参数,没有正确参数
if (m.size() > 3 && m.at(2) >= '0'&&m.at(2) <= '9') {
string t;
t += m.at(0);
t += m.at(1);
t += " ";
for (string::iterator j = m.begin() + 2; j != m.end(); ++j) {
t += *j;
}
out_sub[m.at(1)] = t;
}
//没有正确参数,不用处理只处理有正确参数的
}
}
}
cout << "Case " << count << " :";
for (map<char, string>::iterator it = begin(out_sub); it != end(out_sub); ++it) {
cout << " "<<it->second;
}
out_sub.clear();//清空,便于存储下一组数据
cout << endl;
count++;
#endif
}
}
system("pause");
return 0;
}
运行结果
问题:
原题样例中输出为什么没有-l,尽力了,这道题太麻烦了我觉得,也可能我太菜了吧。
想放着吧,二刷在看看,欢迎各位大佬提供思路