解析命令行参数-ACE_Get_Opt类的用法

来源:互联网 发布:php字符串分割成数组 编辑:程序博客网 时间:2024/05/19 13:58
通常我们开发后台服务程序时经常要提供命令行解析和搜集配置信息的功能。重复这样的

劳动不仅耗时而且对操作系统平台也有依赖性,ACE框架提供了对命令行参数的解析及配置

文件的解析的API接口使我们可以方面的对我们的程序进行方面的配置。

解析命令行参数-ACE_Get_Opt类的用法
ARGV_Example.cpp
此示例演示了ACE_Get_Optint类的基本用法,用来解析类似 program -c -g -a param 这样的程序参数源码解释
/**
* ARGV_Example.cpp,v 1.3 2004/01/03 13:04:35 jwillemsen Exp
*
* ACE_ARGV examples not in a larger program. Sample code from The ACE
* Programmer's Guide, Copyright 2003 Addison-Wesley. All Rights Reserved.
*/

#include "ace/os_include/os_netdb.h"
#include "ace/OS_NS_string.h"
#include "ace/Log_Msg.h"

// Listing 1 code/ch04
#include "ace/ARGV.h"
#include "ace/Get_Opt.h"

//此示例演示了ACE_Get_Optint类的基本用法,用来解析类似 program -c -g -a param  //这样的程序参数
ACE_TMAIN (int argc, ACE_TCHAR *argv[])
{
    //'(":f:h:")'类似一个参数解析的模版 字母紧跟着一个冒号':'那就意味着该“参数开关”    //后期望一个参数
    //"f:" 和"h:"说明参数列表必须是 -f parm1 -h parm2的形式
    //options[] = "ab:" 则说明参数列表应该是 -a -b parm1类似的形式
    static const ACE_TCHAR options[] = ACE_TEXT (":f:h:");
   //ACE_Get_Opt会根据指定的参数和模版生产我们需要的参数列表
   ACE_Get_Opt cmd_opts (argc, argv, options);


// Listing 1

  int option;
  ACE_TCHAR config_file[MAXPATHLEN];
  ACE_TCHAR hostname[MAXHOSTNAMELEN];
  ACE_OS_String::strcpy (config_file, ACE_TEXT ("HAStatus.conf"));
  ACE_OS_String::strcpy (hostname, ACE_TEXT ("not set"));
  //遍历参数列表并进行读取、解析
  while ((option = cmd_opts ()) != EOF)
    switch (option) {
    case 'f':
      ACE_OS_String::strncpy (config_file,
                              cmd_opts.opt_arg (),
                              MAXPATHLEN);
      break;

    case 'h':
      ACE_OS_String::strncpy (hostname,
                              cmd_opts.opt_arg (),
                              MAXHOSTNAMELEN);
      break;
     //':'放在"参数模版"的最前面,如果根据模版指示如没有找到期待的参数
     //重载的'='操作符会返回':'否则会返回'?'
     case ':':
      ACE_ERROR_RETURN
        ((LM_ERROR, ACE_TEXT ("-%c requires an argument\n"),
          cmd_opts.opt_opt ()), -1);


    default:
      ACE_ERROR_RETURN
        ((LM_ERROR, ACE_TEXT ("Parse error.\n")), -1);
    }

  ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Config file: %s\n"), config_file));
  ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Hostname: %s\n"), hostname));
  return 0;
}执行结果演示

//正常的参数解析
D:\project\ACE_wrappers\examples\APG\Config>ARGV_Example -f my.conf -h chengkai
Config file: my.conf
Hostname: chengkai
//确实一个必要的参数
D:\project\ACE_wrappers\examples\APG\Config>ARGV_Example -f my.conf -h
-h requires an argument
//指定了一个无效的参数
D:\project\ACE_wrappers\examples\APG\Config>ARGV_Example -f my.conf -a
Parse error.
Get_Opt_Long.cpp
此示例演示长参数开关的使用,你可以用'program -config my.conf' 或用'program --config my.conf'
这样形式的用法和 'program -f my.conf'是等价的。源码解释

/**
* Get_Opt_Long.cpp,v 1.2 2004/01/03 13:04:35 jwillemsen Exp
*
* ACE_Get_Opt long_only examples. Sample code from The ACE
* Programmer's Guide, Copyright 2003 Addison-Wesley. All Rights Reserved.
*/

#include "ace/OS_NS_string.h"
#include "ace/Get_Opt.h"
#include "ace/Log_Msg.h"

//此示例演示长参数开关的使用,你可以用'program -config my.conf'//或用'program --config my.conf'
//这样形式的用法和 'program -f my.conf'是等价的
int
ACE_TMAIN (int argc, ACE_TCHAR *argv[])
{

  static const ACE_TCHAR options[] = ACE_TEXT (":f:");
  ACE_Get_Opt cmd_opts
    (argc, argv, options, 1, 0, ACE_Get_Opt::PERMUTE_ARGS, 1);
  //指定短选项开关对应的长选项开关
  if (cmd_opts.long_option
      (ACE_TEXT ("config"), 'f', ACE_Get_Opt::ARG_REQUIRED) == -1)
    return -1;

  int option;
  ACE_TCHAR config_file[MAXPATHLEN];
  ACE_OS_String::strcpy (config_file, ACE_TEXT ("HAStatus.conf"));
  while ((option = cmd_opts ()) != EOF)
    switch (option) {
    case 'f':
      ACE_OS_String::strncpy (config_file,
                              cmd_opts.opt_arg (),
                              MAXPATHLEN);
      break;

    case ':':
      ACE_ERROR_RETURN
        ((LM_ERROR, ACE_TEXT ("-%c requires an argument\n"),
          cmd_opts.opt_opt ()), -1);


    default:
      ACE_ERROR_RETURN
        ((LM_ERROR, ACE_TEXT ("Parse error.\n")), -1);
    }

  ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Config file is %s\n"), config_file));

  return 0;
}执行结果演示

D:\project\ACE_wrappers\examples\APG\Config>Get_Opt_Long -f my.conf
Config file is my.conf

D:\project\ACE_wrappers\examples\APG\Config>Get_Opt_Long -config my.conf
Config file is my.conf

D:\project\ACE_wrappers\examples\APG\Config>Get_Opt_Long --config my.conf
Config file is my.conf
Get_Opt.cpp
此示例展示了在使用长选项并且没有指定与之对应的短选项的时候,ACE_Get_Opt可以通过指定一个整数返回值与长选项匹配/**
* Get_Opt.cpp,v 1.2 2004/01/03 13:04:35 jwillemsen Exp
*
* ACE_Get_Opt examples not in a larger program. Sample code from The ACE
* Programmer's Guide, Copyright 2003 Addison-Wesley. All Rights Reserved.
*/

#include "ace/OS_NS_string.h"
#include "ace/Get_Opt.h"
#include "ace/Log_Msg.h"

//此示例展示了在使用长选项并且没有指定与之对应的短选项的时候,可以通过指定一个//  整数返回值与长选项匹配
int
ACE_TMAIN (int argc, ACE_TCHAR *argv[])
{

  // Example for a long option without a corresponding short option.
  // Just put some context here so the following compiles and runs.
  static const ACE_TCHAR options[] = ACE_TEXT (":f:");
  ACE_Get_Opt cmd_opts (argc, argv, options);

  // 指定长选项--cool_option 并且其缺省返回值0
  cmd_opts.long_option (ACE_TEXT ("cool_option"));
  cmd_opts.long_option (ACE_TEXT ("the_answer"), 42);
  // Listing 1

  int option;
  ACE_TCHAR config_file[MAXPATHLEN];
  ACE_OS_String::strcpy (config_file, ACE_TEXT ("HAStatus.conf"));
  while ((option = cmd_opts ()) != EOF)
    switch (option) {
    case 'f':
      ACE_OS_String::strncpy (config_file,
                              cmd_opts.opt_arg (),
                              MAXPATHLEN);
      break;

      // Listing 2 code/ch04
    case 0:
      ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Yes, very cool.\n")));
      break;

    case 42:
      ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("the_answer is 42\n")));
      break;
      // Listing 2

    case ':':
      ACE_ERROR_RETURN
        ((LM_ERROR, ACE_TEXT ("-%c requires an argument\n"),
          cmd_opts.opt_opt ()), -1);


    default:
      ACE_ERROR_RETURN
        ((LM_ERROR, ACE_TEXT ("Parse error.\n")), -1);
    }

  return 0;
}执行结果演示

Get_Opt --cool_option  --the_answer
Yes, very cool.
the_answer is 42
读写配置文件-ACE_Configuration_Heap类的用法
HA_Status.cpp
此示例演示了ACE对配置文件的读取的功能,ACE可以方便的从配置文件读取字符串类型、整数类型、二进制信息/**
* HA_Status.cpp,v 1.4 2005/06/29 16:35:46 shuston Exp
*
* Home Automation Status server. Sample code from The ACE Programmer's Guide,
* Copyright 2003 Addison-Wesley. All Rights Reserved.
*/

#include "ace/OS_NS_string.h"
#include "ace/Configuration.h"
#include "ace/Configuration_Import_Export.h"
#include "ace/Get_Opt.h"
#include "ace/Log_Msg.h"
#include "ace/INET_Addr.h"
#include "ace/Service_Object.h"

class HA_Status : public ACE_Service_Object
{
public:
  virtual int init (int argc, ACE_TCHAR *argv[]);

private:
  ACE_INET_Addr listen_addr_;
};


int
HA_Status::init (int argc, ACE_TCHAR *argv[])
{

  // Do ACE_Get_Opt and get conf file name, read out the sections
  // and print the names.

  // Listing 1 code/ch04
  static const ACE_TCHAR options[] = ACE_TEXT (":f:");
  ACE_Get_Opt cmd_opts (argc, argv, options);
  if (cmd_opts.long_option
      (ACE_TEXT ("config"), 'f', ACE_Get_Opt::ARG_REQUIRED) == -1)
    return -1;
  int option;
  ACE_TCHAR config_file[MAXPATHLEN];
  ACE_OS::strcpy (config_file, ACE_TEXT ("HAStatus.conf"));
  while ((option = cmd_opts ()) != EOF)
    switch (option) {
    case 'f':
      ACE_OS::strncpy (config_file,
                       cmd_opts.opt_arg (),
                       MAXPATHLEN);
      break;
    case ':':
      ACE_ERROR_RETURN
        ((LM_ERROR, ACE_TEXT ("-%c requires an argument\n"),
          cmd_opts.opt_opt ()), -1);
    default:
      ACE_ERROR_RETURN
        ((LM_ERROR, ACE_TEXT ("Parse error.\n")), -1);
    }
  // Listing 1

  // Listing 2 code/ch04
  ACE_Configuration_Heap config;
  if (config.open () == -1)
    ACE_ERROR_RETURN
      ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("config")), -1);
  ACE_Registry_ImpExp config_importer (config);
  if (config_importer.import_config (config_file) == -1)
    ACE_ERROR_RETURN
      ((LM_ERROR, ACE_TEXT ("%p\n"), config_file), -1);

  ACE_Configuration_Section_Key status_section;
  //指定打开HAStatus 节进行读取
  if (config.open_section (config.root_section (),
                           ACE_TEXT ("HAStatus"),
                           0,
                           status_section) == -1)
    ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
                       ACE_TEXT ("Can't open HAStatus section")),
                      -1);

  //分别用来保存读取的字符串类型的地址和整形的端口号
  u_int status_port;
  ACE_TString  server_ip ;
  //读取取字符串类型的地址属性
  if(config.get_string_value(status_section,ACE_TEXT ("ServerIP"),                                                   server_ip) ==-1) 
       ACE_ERROR_RETURN
      ((LM_ERROR,
        ACE_TEXT ("HAStatus ServerIP does not exist\n")),
       -1);
  //读取整形的端口属性
  if (config.get_integer_value (status_section,
                                ACE_TEXT ("ListenPort"),
                                status_port) == -1)
    ACE_ERROR_RETURN
      ((LM_ERROR,
        ACE_TEXT ("HAStatus ListenPort does not exist\n")),
       -1);
  //this->listen_addr_.set (static_cast<u_short> (status_port));
  // Listing 2
  ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ServerIP = %s\n"),                                            server_ip.c_str()));
  ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ListenPort = %d"),status_port));


  return 0;
}

int
ACE_TMAIN (int argc, ACE_TCHAR *argv[])
{
  HA_Status status;
  status.init (argc, argv);
  return 0;
}配置文件内容格式
•[名称]用来定义一个节。
•可以用'#' 或';'来作为注释
•“attribute”=“value”表示一个字符串类型的属性 。
•attribute=#value 或 表示一个整数类型的属性值。
•“attribute”=dword:value 表示一个64位的双字(十六进制)
•“attribute”=hex:value 以十六进制串表示二进制序列
ACE对配置文件的解析和我们通常用的对配置文件读写的类库不太一样1),感觉ACE对配置文件的

读取对格式要求比较严格和我们普通使用的配置文件格式兼容性稍差一些。

有以下几点点需要我们注意。


1.如果你用来表示一个字符串类型的属性值,你应该用'”'包括你的属性值和属性名称,
2.否则ACE将不能正常解析
3.如果你使用类似”dword:“、”hex:“等前缀表示数字类型的属性值,
4.你需要把属性名称用'”'包括起来 ,属性值能用'”'包括起来
5.表示整数类型的属性时,属性名称和属性值都不要'”'包括起来

测试程序
配置文件内容

#这用来表示一个"节"
[HAStatus]
;字符串类型的属性值
"ServerIP"="127.0.0.1"
;整数类型的属性值
ListenPort=#8080
执行结果

D:\project\ACE_wrappers\examples\APG\Config>HA_Status.exe
ServerIP = 127.0.0.1
ListenPort = 8080
1) 象 attribute=value 这样的定义ACE将不能正常解析,这也是我在读了ACE的实现代码后才得知的,
一开始还以为这是一个BUG