当前位置:编程学习 > C/C++ >>

C++实现的命令行参数管理

在编写可运行程序时,经常需要输入除了可运行文件之外的其它的命令行参数,可以用传统的getopt函数来分析,本文基于面向对象,分析一种管理命令行参数方法 -- 来源于webrtc项目,在阅读过程中,大家分享一下。

 

一,传统命令行分析

[cpp]
包含头文件:#include<unistd.h> 
  int getopt(int argc,char * const argv[ ],const char * optstring); 
  extern char *optarg; 
  extern int optind, opterr, optopt; 

二,命令行参数管理
假设命令行的输入格式的规则如下:

--flag           布尔类型。
--noflag       布尔类型。
--flag=value   等号周边没有空格。
2.1 参数的值封装---FlagValue

      这个类对参数的值进行封装,如--prefix=/usr,作为一个命令行参数时,prefix为键,/usr为值。在参数中,在此定义值的类型为布尔、整型、浮点、字符串中的一种。

      由于一个值在只能取四种的一种,所以此处用联合类型表示FlagValue。

[cpp]
union FlagValue { 
  static FlagValue New_BOOL(int b) { 
    FlagValue v; 
    v.b = (b != 0); 
    return v; 
  } 
 
  static FlagValue New_INT(int i) { 
    FlagValue v; 
    v.i = i; 
    return v; 
  } 
 
  static FlagValue New_FLOAT(float f) { 
    FlagValue v; 
    v.f = f; 
    return v; 
  } 
 
  static FlagValue New_STRING(const char* s) { 
    FlagValue v; 
    v.s = s; 
    return v; 
  } 
 
  bool b; 
  int i; 
  double f; 
  const char* s; 
}; 
这个联合类型对命令行中键值对中的值进行封装,可以表示四种类型。

2.2 命令行中键值的表示 -- Flag

    这个类是表示一对键值的抽象,包含下列元素:

键值对。包括name和variable_表示键和值。如--prefix=/usr中,name的值为prefix,variable_为/usr的一个表示。
链表维护域。Flag *next_用于指向下一个命令行参数。
comment_表示该参数的解释。
file表示和键值相关的外部文件。
default_表示默认情况下,就是用户没有输入该参数的情况下默认的值。
定义友元类FlagList,因为FlagList需要访问Flag的next_域。
[cpp] 
class Flag { 
 public: 
  enum Type { BOOL, INT, FLOAT, STRING }; 
 
  // Internal use only. 
  Flag(const char* file, const char* name, const char* comment, 
       Type type, void* variable, FlagValue default_); 
 
  // General flag information 
  const char* file() const  { return file_; } 
  const char* name() const  { return name_; } 
  const char* comment() const  { return comment_; } 
 
  // Flag type 
  Type type() const  { return type_; } 
 
  // Flag variables 
  bool* bool_variable() const { 
    assert(type_ == BOOL); 
    return &variable_->b; 
  }  www.zzzyk.com
   
  int* int_variable() const { 
    assert(type_ == INT); 
    return &variable_->i; 
  } 
   
  double* float_variable() const { 
    assert(type_ == FLOAT); 
    return &variable_->f; 
  } 
   
  const char** string_variable() const { 
    assert(type_ == STRING); 
    return &variable_->s; 
  } 
 
  // Default values 
  bool bool_default() const { 
    assert(type_ == BOOL); 
    return default_.b; 
  } 
   
  int int_default() const { 
    assert(type_ == INT); 
    return default_.i; 
  } 
   
  double float_default() const { 
    assert(type_ == FLOAT); 
    return default_.f; 
  } 
   
  const char* string_default() const { 
    assert(type_ == STRING); 
    return default_.s; 
  } 
 
  // Resets a flag to its default value 
  void SetToDefault(); 
 
  // Iteration support 
  Flag* next() const  { return next_; } 
 
  // Prints flag information. The current flag value is only printed 
  // if print_current_value is set. 
  void Print(bool print_current_value); 
 
 private: 
  const char* file_; 
  const char* name_; 
  const char* comment_; 
 
  Type type_; 
  FlagValue* variable_; 
  FlagValue default_; 
 
  Flag* next_; 
 
  friend class FlagList;  // accesses next_ 
}; 


2.3 命令行键值链表--- FlagList
这个类维护一个全局的链表,链表中每一项都是命令行参数解析的结果,如:--prefix=/usr --localstatedir=/var/data 这就表示两个Flag对象,通过Flag对象的next域来关联。

这个类的属性和方法都是静态的,属性只有Flag* list_,用于维护命令行所有输入的参数所组成的链表。

主要方法如下:

SetFkagsFromCommandLine:解析根据命令行的输入,这里传入的是所有的命令行输入。

SplitArgument:解析命令行中具体的一个可以被解析的键值对。

 

[cpp]
 class FlagList { 
 public: 
  FlagList(); 
  
  static Flag* list()  { return list_; } 
 
  static void Print(const char* file, bool print_current_value); 
 
  static Flag* Lookup(const char* name); 
 
  static void SplitArgument(const char* arg, 
                            char* buffer, int buffer_size, 
                            const char** name, const char** value, 
                            bool* is_bool); 
 
  static int SetFlagsFromCommandLine(int* argc, 
                                     const char** argv); 
  static inline int SetFlagsFromCommandLine(int* argc, 
                 &nbs

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,