CCF計算機職業資格認證考試題解系列文章為meelo原創,請務必以鏈接形式注明本文地址
CCF CSP 201403-3 命令行選項
問題描述
請你寫一個命令行分析程序,用以分析給定的命令行里包含哪些選項。每個命令行由若干個字符串組成,它們之間恰好由一個空格分隔。這些字符串中的第一個為該命令行工具的名字,由小寫字母組成,你的程序不用對它進行處理。在工具名字之后可能會包含若干選項,然后可能會包含一 些不是選項的參數。
選項有兩類:帶參數的選項和不帶參數的選項。一個合法的無參數選項的形式是一個減號后面跟單個小寫字母,如"-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
解析
由於輸入的一行有空格,需要使用getline來獲取輸入。
獲取命令行的選項,可以用字符串初始化stringstream對象。然后通過>>獲取每一個選項。
異常的情況有三種:
1.非合法選項
2.有參數選項沒有輸入參數
3.多余的參數
提供一個額外的測試用例
albw:x
2
ls -w -w
ls -w
2
ls -w -w
ls -w
代碼
C++
#include "iostream" #include "string" #include "sstream" using namespace std; int type[26]; // 0:不存在 1:無參數選項 2:有參數選項 string argument[26]; int main() { string patten; cin >> patten; for(int i=0; i<patten.length(); i++) { int last_arg; if(patten[i] == ':') { type[last_arg] = 2; } else { last_arg = patten[i] - 'a'; type[last_arg] = 1; } } int n; cin >> n; cin.ignore(); for(int i=1; i<=n; i++) { string temp; getline(cin, temp); stringstream ss(temp); ss >> temp; while(ss >> temp) { if(temp[0] == '-') { int last_arg = temp[1] - 'a'; if(type[last_arg] == 0) { // 非合法選項 break; } else if(type[last_arg] == 1) { argument[last_arg] = " "; } else if(type[last_arg] == 2) { if(ss.eof()) break; // 有參數選項沒有輸入參數 ss >> temp; argument[last_arg] = temp; } } else { // 非合法參數 break; } } cout << "Case " << i << ":"; for(int j=0; j<26; j++) { if(type[j] == 1 && argument[j] != "") { cout << " -" << char(j + 'a'); } if(type[j] == 2 && argument[j] != "") { cout << " -" << char(j + 'a') << ' ' << argument[j]; } argument[j] = ""; } cout << endl; } }