模拟题练习与反思
题目
请你写一个命令行分析程序,用以分析给定的命令行里包含哪些选项。
每个命令行由若干个字符串组成,它们之间恰好由一个空格分隔。
这些字符串中的第一个为该命令行工具的名字,由小写字母组成,你的程序不用对它进行处理。
在工具名字之后可能会包含若干选项,然后可能会包含一些不是选项的参数。
选项有两类:带参数的选项和不带参数的选项。
一个合法的无参数选项的形式是一个减号后面跟单个小写字母,如 -a 或 -b。
而带参数选项则由两个由空格分隔的字符串构成,前者的格式要求与无参数选项相同,后者则是该选项的参数,是由小写字母,数字和减号组成的非空字符串。
该命令行工具的作者提供给你一个格式字符串以指定他的命令行工具需要接受哪些选项。
这个字符串由若干小写字母和冒号组成,其中的每个小写字母表示一个该程序接受的选项。
如果该小写字母后面紧跟了一个冒号,它就表示一个带参数的选项,否则则为不带参数的选项。
例如,ab:m: 表示该程序接受三种选项,即 -a(不带参数),-b(带参数),以及 -m(带参数)。
命令行工具的作者准备了若干条命令行用以测试你的程序。
对于每个命令行,你的工具应当一直向后分析。
当你的工具遇到某个字符串既不是合法的选项,又不是某个合法选项的参数时,分析就停止。
命令行剩余的未分析部分不构成该命令的选项,因此你的程序应当忽略它们。
输入格式
输入的第一行是一个格式字符串,它至少包含一个字符,且长度不超过 52。
格式字符串只包含小写字母和冒号,保证每个小写字母至多出现一次,不会有两个相邻的冒号,也不会以冒号开头。
输入的第二行是一个正整数 N,表示你需要处理的命令行的个数。
接下来有 N 行,每行是一个待处理的命令行,它包括不超过 256 个字符。该命令行一定是若干个由单个空格分隔的字符串构成,每个字符串里只包含小写字母,数字和减号。
输出格式
输出有 N 行。其中第 i 行以 Case i: 开始,然后应当有恰好一个空格,然后应当按照字母升序输出该命令行中用到的所有选项的名称,对于带参数的选项,在输出它的名称之后还要输出它的参数。
如果一个选项在命令行中出现了多次,只输出一次。
如果一个带参数的选项在命令行中出现了多次,只输出最后一次出现时所带的参数。
数据范围
1≤N≤20,
对于每组数据,所有命令行工具的名字一定相同,且由小写字母构成。
输入样例:
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
题目需要注意的细节与反思
本题中要求的细节是,每个命令只输出一次且按照字典序输出,那么我们应该进行的操做就是拿到输入命令以后,去掉重复,按序输出。这个时候我们可以使用数组计数法。数组计数在数据量小的时候可以代替哈希表去重,因为英文字母只有26个,所以完全可以使用数组计数再输出。
对于字符串的读取操做,应该采用getline()函数读取,要注意getline函数在使用之前要先进行getchar操做,来读取输入n时留下的换行。接着可以使用stringstream读取使用空格分隔的字符串,这样可以保证按照单词分割。
在逻辑上面可以翻译题意成代码。
代码实现
#include<iostream>
#include<vector>
#include<set>
#include<algorithm>
#include<string>
#include<cstring>
#include<sstream>
using namespace std;
const int maxn = 29;
int stp[maxn];
int st[maxn];
int main() {
string str;
cin >> str;
for (int i = 0; i < str.size(); i++) {
if (i == ':') continue;
if (i < str.size() - 1 && str[i + 1] == ':') stp[str[i] - 'a'] = 1;
st[str[i] - 'a'] = 1;
}
int n; cin >> n;
getchar();
for (int t = 1; t <= n; t++) {
string line;
getline(cin, line);
stringstream ss(line);
vector<string> vec;
while (ss >> str) vec.push_back(str);
int quchong[maxn];
memset(quchong, 0, sizeof(quchong));
string param[maxn];
for (int i = 1; i < vec.size(); i++) {
char c = vec[i][1];
if (vec[i][0] != '-' || c > 'z' || c < 'a' || vec[i].size() != 2 || !st[c - 'a']) break;
if (stp[c - 'a']) {
if (i == vec.size() - 1) break;
else param[c - 'a'] = vec[i + 1];
quchong[c - 'a'] = 1;
i++;
continue;
}
else quchong[c - 'a'] = 1;
}
printf("Case %d: ", t);
for (int i = 0; i <= 26; i++) {
if (quchong[i])
{
cout << '-' << char('a' + i) << " ";
if (stp[i]) cout << param[i] << " ";
}
}
cout << endl;
}
return 0;
}
反思
在写代码的时候一定要注意边写便检查,要做到仔细。
另外,对于数据结构的选择上,一定要选择最合适的数据结构,也要具有大道至简的思想,对于本题,没有必要用set,但是我一开始用到了set,虽说没有问题,但是在面对更复杂的任务时,全面的构思与数据结构的精简会对题目完成有很大的帮助。
同时,我需要更加熟悉语言。例如stringstream流我一开始是没有想到的,而是对命令行进行按位处理,造成了繁琐的代码以及不必要的逻辑。
我认为以后应该多做做模拟,多看看题解,来提升自己的代码水平。