當我們用C++開發一些C++控制台小工具時,會需要一些用戶輸入的參數來決定程序如何工作和執行,而用戶輸入參數的方式大部分都是采用命令行參數的方式。
比如上一篇文章 玩轉Windows服務系列——命令行管理Windows服務 中介紹的sc和net工具。
既然命令行參數這麼普遍也這麼有用,那麼就有必要學習一下如何解析命令行參數。
如何解析命令行參數
那麼命令行參數要如何解析呢。
最最最笨的辦法就是每次程序中需要解析命令行參數時,就寫一堆解析的代碼,但是這樣的效率其實很低的,不如使用開源庫中的幫助類來解析。
我所了解的開源庫的幫助類有
ACE庫的ACE_Get_Opt
boost的Program_options
ACE_Get_Opt類的主要使用方法介紹
那麼我們主要看一下ACE_Get_Opt類
先看它的構造方法
CollapseACE_Get_Opt (int argc, ACE_TCHAR **argv, const ACE_TCHAR *optstring = ACE_TEXT (""), int skip_args = 1, int report_errors = 0, int ordering = PERMUTE_ARGS, int long_only = 0);
下面是代碼中的注釋
Collapse/** * Constructor initializes the command line to be parsed. All information * for parsing must be supplied to this constructor. * * @param argc The number of @a argv elements to parse. * @param argv Command line tokens, such as would be passed * to @c main(). * @param optstring Nul-terminated string containing the legitimate * short option characters. A single colon ":" * following an option character means the option * requires an argument. A double colon "::" following * an option character means the argument is optional. * The argument is taken from the rest of the current * @a argv element, or from the following @a argv * element (only valid for required arguments; * optional arguments must always reside in the same * @a argv element). The argument value, if any is * returned by the @c opt_arg() method. * @a optstring can be extended by adding long options * with corresponding short options via the * @c long_option() method. If the short option * already appears in @a optstring, the argument * characteristics must match, otherwise it is added. * See @c long_option() for more information. * If 'W', followed by a semi-colon ';' appears in * @a optstring, then any time a 'W' appears on the * command line, the following argument is treated as * a long option. For example, if the command line * contains "program -W foo", "foo" is treated as a * long option, that is, as if "program --foo" had * been passed. * The following characters can appear in @a optstring * before any option characters, with the described * effect: * - '+' changes the @a ordering to @a REQUIRE_ORDER. * - '-' changes the @a ordering to @a RETURN_IN_ORDER. * - ':' changes the return value from @c operator() * and get_opt() from '?' to ':' when an option * requires an argument but none is specified. * * @param skip_args Optional (default 1). The specified number of * initial elements in @a argv are skipped before * parsing begins. Thus, the default prevents * @a argv[0] (usually the command name) from being * parsed. @a argc includes all @a argv elements, * including any skipped elements. * @param report_errors Optional, if non-zero then parsing errors cause * an error message to be displayed from the * @c operator() method before it returns. The * error message is suppressed if this argument is 0. * This setting also controls whether or not an error * message is displayed in @c long_option() encounters * an error. * @param ordering Optional (default is @c PERMUTE_ARGS); determines * how the @a argv elements are processed. This argument * is overridden by two factors: * -# The @c POSIXLY_CORRECT environment variable. If * this environment variable is set, the ordering * is changed to @c REQUIRE_ORDER. * -# Leading characters in @a optstring (see above). * Any leading ordering characters override both * the @a ordering argument and any effect of the * @c POSIXLY_CORRECT environment variable. * @param long_only Optional. If non-zero, then long options can be * specified using a single '-' on the command line. * If the token is not a long option, it is processed * as usual, that is, as a short option or set of * short options. * * Multiple short options can be combined as long as only the last * one can takes an argument. For example, if @a optstring is defined as * @c "abc:" or @c "abc::" then the command line @e "program -abcxxx" short * options @e a, @e b, and @e c are found with @e "xxx" as the argument for * @e c. * However, if the command line is specified as @e "program -acb" only * options @e a and @e c are found with @e "b" as the argument for @e c. * Also, for options with optional arguments, that is, those followed by * "::", the argument must be in the same @a argv element, so "program -abc * xxx" will only find "xxx" as the argument for @e c if @a optstring is * specified as @c "abc:" not @c "abc::". */
構造函數共有七個參數,
argc、argv為程序入口函數main方法的參數,也就是程序的命令行。
optstring 為指定的參數選項,並且是一個字符作為一個選項,主要包含三種形式
單純的一個字符選項,比如 s,表示此選項後面不能添加選項的參數
一個字符選項後跟一個冒號,比如 s:,表示此選項後面會有一個參數
一個字符後面跟兩個冒號,比如 s::,表示此選項後面即可以有參數也可以無參數
skip_args 表示從argv的第幾個元素開始,默認為1,一般情況下argv[0]為程序的path
report_errors遇到不識別的參數時是否提示錯誤
long_only表示是否只包含字符串的選項參數。
下面解釋一下 字符選項和字符串選項,也就是 short option 和 long option.
short option 以 字符’-’開始,比如 -s
long option 以兩個字符’-’開始,日入 --server
這是在默認的情況下,也就是long_only = 0的情況下。而當long_only不等於0的時候,就可以通過-server來表示long option了。
long_option方法二:
Collapse/// Adds a long option with a corresponding short option. /** * @param name The long option to add. * @param short_option A character, the short option that corresponds * to @a name. * @param has_arg Defines the argument requirements for * the new option. If the short option has already * been supplied in the @a optstring, @a has_arg * must match or an error is returned; otherwise, the * new short option is added to the @a optstring. * * @retval 0 Success * @retval -1 The long option can not be added. */ int long_option (const ACE_TCHAR *name, int short_option, OPTION_ARG_MODE has_arg = NO_ARG);
這個方法中增加了一個short_option參數,表示這個long_option與對應的short_option所表達的意義是一致的,當解析命令行時,遇到這個long_option時,就按此處的short option進行處理。
此方法可以這樣使用
if(opt.long_option("server", 's', ACE_Get_Opt::ARG_REQUIRED) == -1) { cout << "server option can not be added" << endl; }
long_option方法三:
/// Returns the name of the long option found on the last call to /// @c operator() or 0 if none was found. const ACE_TCHAR *long_option (void) const;
這個方法表示解析命令行時,如果遇到long_option,則可以通過這個方法來獲取是哪一個long_option。
命令行的解析
命令行的解析就要依賴 operator()()方法,和opt_arg方法,前者解析遇到的是哪個short option 或者 long option,而 opt_arg方法則獲取option的參數。
下面看一下方法的聲明
Collapse/** * Scan elements of @a argv (whose length is @a argc) for short option * characters given in @a optstring or long options (with no short * option equivalents). * * If an element of @a argv starts with '-', and is not exactly "-" * or "--", then it is a short option element. The characters of this * element (aside from the initial '-') are option characters. If * it starts with "--" followed by other characters it is treated as * a long option. If @c operator() is called repeatedly, it returns * each of the option characters from each of the option elements. * * @return The parsed option character. The following characters have * special significance. * @retval 0 A long option was found * @retval '\?' Either an unknown option character was found, or the * option is known but requires an argument, none was * specified, and @a optstring did not contain a leading * colon. * @retval ':' A known option character was found but it requires an * argument and none was supplied, and the first character * of @a optstring was a colon. @c opt_opt() indicates * which option was specified. * @retval '1' @c RETURN_IN_ORDER was specified and a non-option argument * was found. * @retval EOF No more option characters were found. @c opt_ind() will * return the index in @a argv of the first @a argv element * that is not an option. If @c PERMUTE_ARGS was * specified, the @a argv elements have been permuted so that * those that are not options now come last. * * @note The standards are unclear with respect to the conditions under * which '?' and ':' are returned, so we scan the initial characters of * @a optstring up unto the first short option character for '+', '-', * and ':' in order to determine ordering and missing argument behavior. */ int operator () (void);
Collapse/** * For communication from @c operator() to the caller. When * @c operator() finds an option that takes an argument, the argument * value is returned from this method, otherwise it returns 0. */ ACE_TCHAR *opt_arg (void) const;
operator()方法有幾種返回值:
具體的option 字符,表示命令行中遇到了此 short option,或者關聯了short option的 long option
0,表示遇到了一個long option,可以通過上面介紹的long_option的方法三來獲取一下具體是哪一個long option
EOF,也就是-1,表示解析結束。
當operator()方法返回一個short option或者 long option時,如果這個option可以有參數,則通過opt_arg方法來獲取具體的參數。
完整的命令行解析代碼
下面展示一個完整但是比較簡單的命令行解析的示例程序代碼
Collapse#include "ace/Get_Opt.h" #include <iostream> using namespace std; int _tmain(int argc, _TCHAR* argv[]) { //定義了三個short option, 類型為 ARG_REQUIRED ACE_Get_Opt opt(argc, argv, "s:u:p:", 1, 0); //定義三個long option, 並與相應的short option 進行關聯 if(opt.long_option("server", 's', ACE_Get_Opt::ARG_REQUIRED) == -1) { cout << "server option can not be added" << endl; } if(opt.long_option("user", 'u', ACE_Get_Opt::ARG_REQUIRED) == -1) { cout << "user option can not be added" << endl; } if(opt.long_option("pwd", 'p', ACE_Get_Opt::ARG_REQUIRED) == -1) { cout << "pwd option can not be added" << endl; } //開始解析 for(int arg = 0; (arg = opt()) != -1;) { switch (arg) { case 's': cout << "server is " << opt.opt_arg() << endl; break; case 'u': cout << "user is " << opt.opt_arg() << endl; break; case 'p': cout << "pwd is " << opt.opt_arg() << endl; break; //解析 long option case 0: if(_stricmp(opt.long_option(), "server") == 0) { cout << "long option server is" << opt.opt_arg() << endl; } break; default: break; } } //如果直接運行,或者使用方式不對,則顯示幫助 if(opt.opt_ind() + 2 < argc) { cout << "the usage is : GetOptTest.exe [option]" << endl; cout << "\t [-s] server address" << endl; cout << "\t [-u] user name" << endl; cout << "\t [-p] password of user" << endl << endl; } return 0; }
命令行解析實戰
至此命令行解析的基本功能已經都介紹了,而且相應的代碼已經完成,那麼就讓我們來欣賞一下解析的效果吧。
具體的命令行
-s 127.0.0.1 --server 192.168.0.1 -u hbccdf -p pwdfortest
運行效果圖
其實功能很簡單,ACE_Get_Opt的使用也很簡單,但是一點點學習,並進行總結,是我一直需要提高的地方。以後會堅持把學到的東西進行總結,並分享到博客上。
作者:cnblogs 緣生夢