201403-3命令列選項(c++,字串處理)
試題編號: | 201403-3 |
試題名稱: | 命令列選項 |
時間限制: | 1.0s |
記憶體限制: | 256.0MB |
問題描述: | 問題描述 請你寫一個命令列分析程式,用以分析給定的命令列裡包含哪些選項。每個命令列由若干個字串組成,它們之間恰好由一個空格分隔。這些字串中的第一個為該命令列工具的名字,由小寫字母組成,你的程式不用對它進行處理。在工具名字之後可能會包含若干選項,然後可能會包含一 些不是選項的引數。 輸入格式 輸入的第一行是一個格式字串,它至少包含一個字元,且長度不超過 52。格式字串只包含小寫字母和冒號,保證每個小寫字母至多出現一次,不會有兩個相鄰的冒號,也不會以冒號開頭。 輸出格式 輸出有 N 行。其中第 i 行以"Case i:" 開始,然後應當有恰好一個空格,然後應當按照字母升序輸出該命令列中用到的所有選項的名稱,對於帶引數的選項,在輸出它的名稱之後還要輸出它的引數。如果一個選項在命令列中出現了多次,只輸出一次。如果一個帶引數的選項在命令列中出 現了多次,只輸出最後一次出現時所帶的引數。 樣例輸入 albw:x 樣例輸出 Case 1: -a -l |
本題大意是給定一個格式,再給幾個命令列,命令列中包括選項或引數,要求輸出命令列中符合格式條件的選項或引數。
本題難點在於命令列中的選項或引數是由空格分隔開的,處理輸入和將選項或引數取出時比較麻煩。輸入的問題可以用c++中的getline函式來解決,getline作用是接收一行資料;需要注意的是,程式開始時輸入了一個字串和一個數字,getline函式會將輸入數字時的換行符接收上,導致接收的第一行命令列為空,所以要在輸入數字的語句後加getchar(),用於接收換行符。取出選項和引數的問題可以用strtok函式來解決,這個函式類似於java中的split函式,用於分割字串。
若選項帶引數,需要輸出最後一個引數。這個問題用一個map來解決,map的key為選項,value儲存最後一次出現的引數。程式碼如下:
#include<iostream>
#include<string.h>
#include<map>
using namespace std;
string format; //格式字串
char word[256]; //輸入的命令列
int n;
int main()
{
cin>>format>>n;
getchar(); //接收上一句的換行符
for(int i=0;i<n;i++)
{
map<string,string> m;
bool flag=false;
cin.getline(word,256);
char *cmd=strtok(word," "); //此時取出的是命令列的名字,應該忽略。
cmd=strtok(NULL," "); //此後strtok的引數都應該是NULL,此時取出的是第一個選項
char *temp=NULL;
while(cmd)
{
//若取出的字串是一個選項,即一個減號加一個字母
if(strlen(cmd)==2 && cmd[0]=='-')
{
//查詢這個選項在不在格式中
int pos=format.find(cmd[1]);
if(pos==-1)
break;
//若map中還沒有出現過這個選項,則新增進去
if(m.find(cmd)==m.end())
m[cmd]=="";
//temp取出當前選項後面的字串
temp=strtok(NULL," ");
//判斷當前選項帶不帶參,如果帶引數就把temp儲存到map中。
if(format[pos+1]==':' && temp)
{
m[cmd]=temp;
flag=true;
}
}
//若當前遇到了不是選項的字串就退出,當前命令列剩餘的字串全部忽略。
else
break;
//現在的temp為當前選項的後一個字串
//若當前的字串是個帶參的選項,那麼就跳到temp的後面的那個字串上
if(flag)
{
cmd=strtok(NULL," ");
flag=false;
}
//若當前選項不帶參,就把temp作為下一個選項來處理。
else
cmd=temp;
}
cout<<"Case "<<i+1<<":";
for(map<string,string>::iterator it=m.begin();it!=m.end();it++)
{
cout<<" "<<it->first;
if(it->second!="")
cout<<" "<<it->second;
}
cout<<endl;
}
return 0;
}