试题编号: | 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 |
这道题题目好长,我记得我昨天题目读到一半就读不下去了,困得不行,其实有时候符号比文字表述起来更简明清晰。
感觉考察的还是字符串的处理,用STL会简单很多,一些简单的操作就不用自己去实现了,例如:查找、排序、去重……
有思路跟程序AC真的是两码事T^T
在我越写越乱之时,还是参考了海岛BLOG,前期还是先多学习、模仿、积累,其间还查了些之前不懂的用法,恩,还是学到很多。
这次在vc++6.0下编译调试通过,但在CCF下又提示我编译出错,好气啊,最后在开头加上#include <cstring>就莫名好了,鬼知道为什么。
※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※ ※※
1、从键盘输入一行命令,我用了cin.getline(),但是因为cin.getline()前进行了cin输入,cin.getline()会把cin输入时行末丢弃的换行符读入,造成cin.getline()第一次获得的数据为空行。貌似小学期做网络课设时,我也遇到了这个问题,当时YX用了暴力的方法解决了,笑哭。。
解决办法有两种:
(1)cin.ignore() //忽略cin输入所遗留的换行符
(2)getchar() //读取cin输入所遗留的换行符
2、map的一些特性
(1)键值对,键是唯一的。键:选项,值:参数。因此,选项重复时,尤其是有参选项,替换参数方便很多。
(2)key自动按字典序排列(即本题:选项),输出时不必再排序。
(3)m.find(#)==m.end() → #在map中未出现过
(1)map的定义
map<string,string> m;
(2)map的遍历
for(map<string,string>::iterator iter=m.begin();iter!=m.end();iter++)
iter->first键
iter->second值
3、string的find()函数
例:string s="abc";
int pos = s.find("a");
若pos=-1,则字符串不含该字符,否则返回该字符出现的位子。
4、字符串分割strtok()
这个网络课设里也用到过,一个套路。
char *cmd=strtok(s[i]," ");
while(cmd)
{
cmd=strtok(NULL," ");
}
5、字符指针char *cmd 的大小
strlen(cmd)
不是cmd.size(),也不是cmd.length()
6、【审题注意】
(1)选项只含两个字符,减号+字母, -ab是错误的格式。
(2)有参的选项,若没有输入参数,这种情况似乎CCF不判错。
暂时就这些吧= = 网络上其他代码有点懒得再看了。
代码:
#include <iostream>
#include <string>
#include <cstring> //*编译出错
#include <map>
using namespace std;
int main()
{
// 输入
string format; //格式
int n; //需要处理的命令行的个数,<=20
cin>>format>>n;
char s[20][257];
//cin.ignore(); //*忽略第一次输入所遗留的换行符 或getchar()?
getchar();
// 输入命令,并进行处理
for(int i=0;i<n;i++)
{
bool flag=false;
map<string,string> m; //存待输出选项、参数
// 输入命令行
cin.getline(s[i],257);
// 切分命令行
char *cmd=strtok(s[i]," ");
cmd=strtok(NULL," ");
char *temp=NULL;
while(cmd)
{
// 处理
if(strlen(cmd)==2 && cmd[0]=='-') //判断是否为选项,** -ab ×
{
// 选项在格式中未找到则出错结束
int pos=format.find(cmd[1]);
if(pos==-1)
break;
// 选项未出现过则添加
if(m.find(cmd)==m.end())
m[cmd]="";
// 若有参,则更新参数
temp=strtok(NULL," ");
if(format[pos+1]==':' && temp) //*漏temp
{
m[cmd]=temp;
flag=true; //*漏
}
}
else
break;
if(flag)
{
cmd=strtok(NULL," ");
flag=false;
}
else
cmd=temp;
}
//输出结果
cout<<"Case "<<i+1<<":";
for(map<string,string>::iterator iter=m.begin();iter!=m.end();iter++)
{
cout<<" "<<iter->first;
if(iter->second!="")
cout<<" "<<iter->second;
}
cout<<endl;
}
return 0;
}
痛定思痛,暴饮暴食……