CSP201403-3:命令列選項

husterzxh發表於2018-09-07

引言:CSP(http://www.cspro.org/lead/application/ccf/login.jsp)是由中國計算機學會(CCF)發起的”計算機職業資格認證”考試,針對計算機軟體開發、軟體測試、資訊管理等領域的專業人士進行能力認證。認證物件是從事或將要從事IT領域專業技術與技術管理人員,以及高校招考研究生的複試物件。

 

  • 問題描述

  請你寫一個命令列分析程式,用以分析給定的命令列裡包含哪些選項。每個命令列由若干個字串組成,它們之間恰好由一個空格分隔。這些字串中的第一個為該命令列工具的名字,由小寫字母組成,你的程式不用對它進行處理。在工具名字之後可能會包含若干選項,然後可能會包含一些不是選項的引數。

  選項有兩類:帶引數的選項和不帶引數的選項。一個合法的無引數選項的形式是一個減號後面跟單個小寫字母,“-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

 

  • 原始碼

# include <iostream>

# include <string>

# include <vector>

# include <map>

 

using namespace std;

 

vector<string> split(string &s, const string &seperator);

 

int main(void)

{

    map<string, int> format_map; // 判斷命令選項是否帶引數

    string format_string; // 格式字串

    int sample_count; // 命令數

    

    cin >> format_string;

    cin >> sample_count;

    

    for (string::size_type i = 0; i != format_string.length(); i++)

    {

        // 如果當前字元是冒號,不做任何處理

        if (format_string[i] == `:`)

        {

            continue;

        }

        

        // 選項帶引數,將對應選項的value設為1

        if (i != format_string.length()-1 && format_string[i+1] == `:`)

        {

            string s = “-“;

            s = s + format_string[i];

            format_map[s] = 1;

        }

        // 選項不帶引數,將對應選項的value設為2

        else

        {

            string s = “-“;

            s = s + format_string[i];

            format_map[s] = 2;

        }

    }

    

//    // 迭代器遍歷format_map,判斷結果是否正確

//    for (map<string, int>::iterator it = format_map.begin(); it != format_map.end(); it++)

//    {

//        cout << it->first << ” ” << it->second << endl;

//    }

 

    // cin不會讀入換行,如果這裡不對換行做特殊處理,第一次執行for迴圈時,getline會讀入之前的換行

    string assist_string;

    getline(cin, assist_string);

    for (int i = 0; i < sample_count; i++)

    {

        map<string, string> output_map; // 最終要輸出的map

        string input_string; // 輸入的一行命令

        getline(cin, input_string);

        vector<string> v = split(input_string, ” “); // 呼叫自定義函式對字串分割

        for (vector<string>::iterator it = v.begin(); it != v.end(); it++)

        {

            if (it == v.begin())

            {

                continue;    

            }

            

            if (format_map.find(*it) != format_map.end()) // 關鍵字存在,即命令選項存在

            {

                if (format_map[*it] == 1) // 選項帶引數

                {

                    if (it+1 == v.end()) // 本該帶引數的選項沒帶引數

                    {

                        break;

                    }

                    else

                    {

                        output_map[*it] = ” ” + *(it+1);

                        it++;

                    }

                }

                else // 選項不帶引數

                {

                    output_map[*it] = “”;

                }

            }

            else // 關鍵字不存在,也就說命令選項不存在

            {

                break;    

            }

        }

        cout << “Case ” << i+1 << “:”;

        for (map<string, string>::iterator mit = output_map.begin(); mit != output_map.end(); mit++)

        {

            cout << ” ” << mit->first << mit->second;

 

        }

        cout << endl;

    }

    

 

    return 0;

}

 

vector<string> split(string &s, const string &seperator)

{

    string::size_type index = 0;

    vector<string> vector_string;

    

    while ((index = s.find(seperator)) != -1)

    {

        string temp = s.substr(0, index);

        vector_string.push_back(temp);

        s = s.substr(index+1, s.length()-index-1);

    }

    if (s.length() > 0)

    {

        vector_string.push_back(s);

    }

    

    return vector_string;

}

 

相關文章