程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 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.2cto.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, 
                                            char** argv) { 
    return SetFlagsFromCommandLine(argc, const_cast<const char**>(argv)); 
  } 
 
 private: 
  static Flag* list_; 
};  


2.4 實現
先看在鏈表中,查找指定的參數,這個實現比較簡單。


[cpp] 
Flag* FlagList::Lookup(const char* name) { 
  Flag* f = list_; 
  while (f != NULL && strcmp(name, f->name()) != 0) 
    f = f->next(); 
  return f; 

解析特定的命令行參數函數
[cpp]
void FlagList::SplitArgument(const char* arg, 
                            char* buffer, int buffer_size, 
                            const char** name, const char** value, 
                            bool* is_bool) { 
 *name = NULL; 
 *value = NULL; 
 *is_bool = false; 
 
 if (*arg == '-') { 
   // find the begin of the flag name 
   arg++;  // remove 1st '-' 
   if (*arg == '-') 
     arg++;  // remove 2nd '-' 
   if (arg[0] == 'n' && arg[1] == 'o') { 
     arg += 2;  // remove "no" 
     *is_bool = true; 
   } 
   *name = arg; 
 
   // find the end of the flag name 
   while (*arg != '\0' && *arg != '=') 
     arg++; 
 
   // get the value if any 
   if (*arg == '=') { 
     // make a copy so we can NUL-terminate flag name 
     int n = static_cast<int>(arg - *name); 
     if (n >= buffer_size) 
       Fatal(__FILE__, __LINE__, "CHECK(%s) failed", "n < buffer_size"); 
     memcpy(buffer, *name, n * sizeof(char)); 
     buffer[n] = '\0'; 
     *name = buffer; 
     // get the value 
     *value = arg + 1; 
   } 
 } 
  
上面的函數是對諸如--prefix=/usr 、--prefix、--prefix /usr之類的命令行進行解析,如果某項輸入不以-開頭,則不被解析。
流程如下:

如果以"-"開頭,則去掉這個開頭,接下來如果還是"-",還是把這個字符去掉。
如果接下來的字符是no,則表示這是一個布爾類型輸入,此時將arg的值賦值給name。
然後一直跳過字符,直到遇到“=”號,或者arg的結尾。
如果後面是“=”號,則後面的部分為name所對應的value值。

解析所有的命令行輸入
[cpp] 
int FlagList::SetFlagsFromCommandLine(int* argc, const char** argv) { 
  // parse arguments 
  for (int i = 1; i < *argc; /* see below */) { 
    int j = i;  // j > 0 
    const char* arg = argv[i++]; 
 
    // split arg into flag components 
    char buffer[1024]; 
    const char* name; 
    const char* value; 
    bool is_bool; 
    SplitArgument(arg, buffer, sizeof buffer, &name, &value, &is_bool); 
 
    if (name != NULL) { 
      // lookup the flag 
      Flag* flag = Lookup(name); 
      if (flag == NULL) { 
        fprintf(stderr, "Error: unrecognized flag %s\n", arg); 
        return j; 
      } 
 
      // if we still need a flag value, use the next argument if available 
      if (flag->type() != Flag::BOOL && value == NULL) { 
        if (i < *argc) { 
          value = argv[i++]; 
        } else { 
          fprintf(stderr, "Error: missing value for flag %s of type %s\n", 
            arg, Type2String(flag->type())); 
          return j; 
        } 
      } 
 
      // set the flag 
      char empty[] = { '\0' }; 
      char* endp = empty; 
      switch (flag->type()) { 
        case Flag::BOOL: 
          *flag->bool_variable() = !is_bool; 
          break; 
        case Flag::INT: 
          *flag->int_variable() = strtol(value, &endp, 10); 
          break; 
        case Flag::FLOAT: 
          *flag->float_variable() = strtod(value, &endp); 
          break; 
        case Flag::STRING: 
          *flag->string_variable() = value; 
          break; 
      } 
 
      // handle errors 
      if ((flag->type() == Flag::BOOL && value != NULL) || 
          (flag->type() != Flag::BOOL && is_bool) || 
          *endp != '\0') { 
        fprintf(stderr, "Error: illegal value for flag %s of type %s\n", 
          arg, Type2String(flag->type())); 
        return j; 
      } 
 
    } 
  } 
  return 0; 

 粘貼如下:

flags.h

[cpp] 
#ifndef TALK_BASE_FLAGS_H__ 
#define TALK_BASE_FLAGS_H__ 
 
#include <assert.h> 
 
#include "talk/base/checks.h" 
#include "talk/base/common.h" 
 
// Internal use only. 
union FlagValue { 
  // Note: Because in C++ non-bool values are silently converted into 
  // bool values ('bool b = "false";' results in b == true!), we pass 
  // and int argument to New_BOOL as this appears to be safer - sigh. 
  // In particular, it prevents the (not uncommon!) bug where a bool 
  // flag is defined via: DEFINE_bool(flag, "false", "some comment");. 
  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; 
}; 
 
 
// Each flag can be accessed programmatically via a Flag object. 
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; 
  } 
   
  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_ 
}; 
 
 
// Internal use only. 
#define DEFINE_FLAG(type, c_type, name, default, comment) \ 
  /* define and initialize the flag */                    \ 
  c_type FLAG_##name = (default);                         \ 
  /* register the flag */                                 \ 
  static Flag Flag_##name(__FILE__, #name, (comment),   \ 
                          Flag::type, &FLAG_##name,       \ 
                          FlagValue::New_##type(default)) 
 
 
// Internal use only. 
#define DECLARE_FLAG(c_type, name)              \ 
  /* declare the external flag */               \ 
  extern c_type FLAG_##name 
 
 
// Use the following macros to define a new flag: 
#define DEFINE_bool(name, default, comment) \ 
  DEFINE_FLAG(BOOL, bool, name, default, comment) 
#define DEFINE_int(name, default, comment) \ 
  DEFINE_FLAG(INT, int, name, default, comment) 
#define DEFINE_float(name, default, comment) \ 
  DEFINE_FLAG(FLOAT, double, name, default, comment) 
#define DEFINE_string(name, default, comment) \ 
  DEFINE_FLAG(STRING, const char*, name, default, comment) 
 
 
// Use the following macros to declare a flag defined elsewhere: 
#define DECLARE_bool(name)  DECLARE_FLAG(bool, name) 
#define DECLARE_int(name)  DECLARE_FLAG(int, name) 
#define DECLARE_float(name)  DECLARE_FLAG(double, name) 
#define DECLARE_string(name)  DECLARE_FLAG(const char*, name) 
 
 
// The global list of all flags. 
class FlagList { 
 public: 
  FlagList(); 
 
  // The NULL-terminated list of all flags. Traverse with Flag::next(). 
  static Flag* list()  { return list_; } 
 
  // If file != NULL, prints information for all flags defined in file; 
  // otherwise prints information for all flags in all files. The current 
  // flag value is only printed if print_current_value is set. 
  static void Print(const char* file, bool print_current_value); 
 
  // Lookup a flag by name. Returns the matching flag or NULL. 
  static Flag* Lookup(const char* name); 
 
  // Helper function to parse flags: Takes an argument arg and splits it into 
  // a flag name and flag value (or NULL if they are missing). is_bool is set 
  // if the arg started with "-no" or "--no". The buffer may be used to NUL- 
  // terminate the name, it must be large enough to hold any possible name. 
  static void SplitArgument(const char* arg, 
                            char* buffer, int buffer_size, 
                            const char** name, const char** value, 
                            bool* is_bool); 
 
  // Set the flag values by parsing the command line. If remove_flags 
  // is set, the flags and associated values are removed from (argc, 
  // argv). Returns 0 if no error occurred. Otherwise, returns the 
  // argv index > 0 for the argument where an error occurred. In that 
  // case, (argc, argv) will remain unchanged indepdendent of the 
  // remove_flags value, and no assumptions about flag settings should 
  // be made. 
  // 
  // The following syntax for flags is accepted (both '-' and '--' are ok): 
  // 
  //   --flag        (bool flags only) 
  //   --noflag      (bool flags only) 
  //   --flag=value  (non-bool flags only, no spaces around '=') 
  //   --flag value  (non-bool flags only) 
  static int SetFlagsFromCommandLine(int* argc, 
                                     const char** argv, 
                                     bool remove_flags); 
  static inline int SetFlagsFromCommandLine(int* argc, 
                                            char** argv, 
                                            bool remove_flags) { 
    return SetFlagsFromCommandLine(argc, const_cast<const char**>(argv), 
                                   remove_flags); 
  } 
 
  // Registers a new flag. Called during program initialization. Not 
  // thread-safe. 
  static void Register(Flag* flag); 
 
 private: 
  static Flag* list_; 
}; 
 
#ifdef WIN32 
// A helper class to translate Windows command line arguments into UTF8, 
// which then allows us to just pass them to the flags system. 
// This encapsulates all the work of getting the command line and translating 
// it to an array of 8-bit strings; all you have to do is create one of these, 
// and then call argc() and argv(). 
class WindowsCommandLineArguments { 
 public: 
  WindowsCommandLineArguments(); 
  ~WindowsCommandLineArguments(); 
 
  int argc() { return argc_; } 
  char **argv() { return argv_; } 
 private: 
  int argc_; 
  char **argv_; 
 
 private: 
  DISALLOW_EVIL_CONSTRUCTORS(WindowsCommandLineArguments); 
}; 
#endif  // WIN32 
 
 
#endif  // SHARED_COMMANDLINEFLAGS_FLAGS_H__ 

flags.cc
[cpp]
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
 
 
#ifdef WIN32 
#include "talk/base/win32.h" 
#include <shellapi.h> 
#endif 
 
#include "talk/base/flags.h" 
 
 
// ----------------------------------------------------------------------------- 
// Implementation of Flag 
 
Flag::Flag(const char* file, const char* name, const char* comment, 
           Type type, void* variable, FlagValue default__) 
    : file_(file), 
      name_(name), 
      comment_(comment), 
      type_(type), 
      variable_(reinterpret_cast<FlagValue*>(variable)), 
      default_(default__) { 
  FlagList::Register(this); 

 
 
void Flag::SetToDefault() { 
  // Note that we cannot simply do '*variable_ = default_;' since 
  // flag variables are not really of type FlagValue and thus may 
  // be smaller! The FlagValue union is simply 'overlayed' on top 
  // of a flag variable for convenient access. Since union members 
  // are guarantee to be aligned at the beginning, this works. 
  switch (type_) { 
    case Flag::BOOL: 
      variable_->b = default_.b; 
      return; 
    case Flag::INT: 
      variable_->i = default_.i; 
      return; 
    case Flag::FLOAT: 
      variable_->f = default_.f; 
      return; 
    case Flag::STRING: 
      variable_->s = default_.s; 
      return; 
  } 
  UNREACHABLE(); 

 
 
static const char* Type2String(Flag::Type type) { 
  switch (type) { 
    case Flag::BOOL: return "bool"; 
    case Flag::INT: return "int"; 
    case Flag::FLOAT: return "float"; 
    case Flag::STRING: return "string"; 
  } 
  UNREACHABLE(); 
  return NULL; 

 
 
static void PrintFlagValue(Flag::Type type, FlagValue* p) { 
  switch (type) { 
    case Flag::BOOL: 
      printf("%s", (p->b ? "true" : "false")); 
      return; 
    case Flag::INT: 
      printf("%d", p->i); 
      return; 
    case Flag::FLOAT: 
      printf("%f", p->f); 
      return; 
    case Flag::STRING: 
      printf("%s", p->s); 
      return; 
  } 
  UNREACHABLE(); 

 
 
void Flag::Print(bool print_current_value) { 
  printf("  --%s (%s)  type: %s  default: ", name_, comment_, 
          Type2String(type_)); 
  PrintFlagValue(type_, &default_); 
  if (print_current_value) { 
    printf("  current value: "); 
    PrintFlagValue(type_, variable_); 
  } 
  printf("\n"); 

 
 
// ----------------------------------------------------------------------------- 
// Implementation of FlagList 
 
Flag* FlagList::list_ = NULL; 
 
 
FlagList::FlagList() { 
  list_ = NULL; 

 
void FlagList::Print(const char* file, bool print_current_value) { 
  // Since flag registration is likely by file (= C++ file), 
  // we don't need to sort by file and still get grouped output. 
  const char* current = NULL; 
  for (Flag* f = list_; f != NULL; f = f->next()) { 
    if (file == NULL || file == f->file()) { 
      if (current != f->file()) { 
        printf("Flags from %s:\n", f->file()); 
        current = f->file(); 
      } 
      f->Print(print_current_value); 
    } 
  } 

 
 
Flag* FlagList::Lookup(const char* name) { 
  Flag* f = list_; 
  while (f != NULL && strcmp(name, f->name()) != 0) 
    f = f->next(); 
  return f; 

 
 
void FlagList::SplitArgument(const char* arg, 
                             char* buffer, int buffer_size, 
                             const char** name, const char** value, 
                             bool* is_bool) { 
  *name = NULL; 
  *value = NULL; 
  *is_bool = false; 
 
  if (*arg == '-') { 
    // find the begin of the flag name 
    arg++;  // remove 1st '-' 
    if (*arg == '-') 
      arg++;  // remove 2nd '-' 
    if (arg[0] == 'n' && arg[1] == 'o') { 
      arg += 2;  // remove "no" 
      *is_bool = true; 
    } 
    *name = arg; 
 
    // find the end of the flag name 
    while (*arg != '\0' && *arg != '=') 
      arg++; 
 
    // get the value if any 
    if (*arg == '=') { 
      // make a copy so we can NUL-terminate flag name 
      int n = static_cast<int>(arg - *name); 
      if (n >= buffer_size) 
        Fatal(__FILE__, __LINE__, "CHECK(%s) failed", "n < buffer_size"); 
      memcpy(buffer, *name, n * sizeof(char)); 
      buffer[n] = '\0'; 
      *name = buffer; 
      // get the value 
      *value = arg + 1; 
    } 
  } 

 
 
int FlagList::SetFlagsFromCommandLine(int* argc, const char** argv, 
                                      bool remove_flags) { 
  // parse arguments 
  for (int i = 1; i < *argc; /* see below */) { 
    int j = i;  // j > 0 
    const char* arg = argv[i++]; 
 
    // split arg into flag components 
    char buffer[1024]; 
    const char* name; 
    const char* value; 
    bool is_bool; 
    SplitArgument(arg, buffer, sizeof buffer, &name, &value, &is_bool); 
 
    if (name != NULL) { 
      // lookup the flag 
      Flag* flag = Lookup(name); 
      if (flag == NULL) { 
        fprintf(stderr, "Error: unrecognized flag %s\n", arg); 
        return j; 
      } 
 
      // if we still need a flag value, use the next argument if available 
      if (flag->type() != Flag::BOOL && value == NULL) { 
        if (i < *argc) { 
          value = argv[i++]; 
        } else { 
          fprintf(stderr, "Error: missing value for flag %s of type %s\n", 
            arg, Type2String(flag->type())); 
          return j; 
        } 
      } 
 
      // set the flag 
      char empty[] = { '\0' }; 
      char* endp = empty; 
      switch (flag->type()) { 
        case Flag::BOOL: 
          *flag->bool_variable() = !is_bool; 
          break; 
        case Flag::INT: 
          *flag->int_variable() = strtol(value, &endp, 10); 
          break; 
        case Flag::FLOAT: 
          *flag->float_variable() = strtod(value, &endp); 
          break; 
        case Flag::STRING: 
          *flag->string_variable() = value; 
          break; 
      } 
 
      // handle errors 
      if ((flag->type() == Flag::BOOL && value != NULL) || 
          (flag->type() != Flag::BOOL && is_bool) || 
          *endp != '\0') { 
        fprintf(stderr, "Error: illegal value for flag %s of type %s\n", 
          arg, Type2String(flag->type())); 
        return j; 
      } 
 
      // remove the flag & value from the command 
      if (remove_flags) 
        while (j < i) 
          argv[j++] = NULL; 
    } 
  } 
 
  // shrink the argument list 
  if (remove_flags) { 
    int j = 1; 
    for (int i = 1; i < *argc; i++) { 
      if (argv[i] != NULL) 
        argv[j++] = argv[i]; 
    } 
    *argc = j; 
  } 
 
  // parsed all flags successfully 
  return 0; 

 
void FlagList::Register(Flag* flag) { 
  assert(flag != NULL && strlen(flag->name()) > 0); 
  if (Lookup(flag->name()) != NULL) 
    Fatal(flag->file(), 0, "flag %s declared twice", flag->name()); 
  flag->next_ = list_; 
  list_ = flag; 

 
#ifdef WIN32 
WindowsCommandLineArguments::WindowsCommandLineArguments() { 
  // start by getting the command line. 
  LPTSTR command_line = ::GetCommandLine(); 
   // now, convert it to a list of wide char strings. 
  LPWSTR *wide_argv = ::CommandLineToArgvW(command_line, &argc_); 
  // now allocate an array big enough to hold that many string pointers. 
  argv_ = new char*[argc_]; 
 
  // iterate over the returned wide strings; 
  for(int i = 0; i < argc_; ++i) { 
    std::string s = talk_base::ToUtf8(wide_argv[i], wcslen(wide_argv[i])); 
    char *buffer = new char[s.length() + 1]; 
    talk_base::strcpyn(buffer, s.length() + 1, s.c_str()); 
 
    // make sure the argv array has the right string at this point. 
    argv_[i] = buffer;  www.2cto.com
  } 
  LocalFree(wide_argv); 

 
WindowsCommandLineArguments::~WindowsCommandLineArguments() { 
  // need to free each string in the array, and then the array. 
  for(int i = 0; i < argc_; i++) { 
    delete[] argv_[i]; 
  } 
 
  delete[] argv_; 

#endif  // WIN32 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved