C++参数解析参数

《C/C++参数解析》

1. getopt库的使用

  getopt用于解析程序命令行输入的参数,可解析短参数和长参数;解析短参数使用getopt()函数,解析长参数可使用getopt_long();

1.1 getopt()解析短参数

  getopt()函数用来解析短参数,例如-a或者-b 100这样的参数,不能解析长参数,如--ip 198.11.23.45这样的参数;

函数原型:

int getopt(int argc, char * const argv[], const char *optstring);

// -- optstring: 选项字符串,告知getopt()可以处理哪些参数选项以及哪些参数选项有参数值

optstring参数详解:

const char* optstring = "ab:c::";
参数 含义 格式
a 单个字符a, 表示参数选项a可有可无,有的话不能加参数值, -a
b: 单个字符加上冒号,表示参数选项b可有可无,如果有的话必须加参数值 -b100
c:: 单个字符加上两个冒号,表示参数c可以有,也可以无,
有的话既可以加参数,也可以不加参数 (没参数的时候optarg==NULL)
-c100

在getopt函数接收到optstring参数后,会依次检查参数a,b,c是否被传入,当对应的参数被指定以后,就会返回对应的参数名,如果参数带有值的话,可通过以下方法获取参数的值 (getopt提供了一些全局变量,可通过这些全局变量来获取参数值):

  • optarg 指向当前参数的值的指针,NULL时表示参数选项没有值
  • optind —— 用来记录argv中下一个检索的位置。
  • optopt —— 存储不在选项字符串optstring中的参数。
  • opterr ­—— 如果不希望getopt()打印出错信息,则只要将全域变量opterr设为0即可

getopt()函数在命令解析完毕时候,会返回-1,如果解析到选项参数字符串中没有的参数,则会返回'?'.

示例代码:

#include <stdio.h>
#include "getopt.h"

int main(int argc, char** argv)
{
    opterr = 0;     // 是否输出错误信息
    int opt = 0;
    char const *optStr = "a::b:c";
    while ((opt=getopt(argc, argv, optStr)) != -1)
    {
        if (opt == 'a')  //可选参数,可传入或者不传入参数值
        {
            printf("Parameter a is get.\n");

            if (optarg==NULL)
                printf("No value");
            else
                printf("Value is %s", (char*)optarg);
        }
        else if (opt == 'b')   // 可选参数,必须传入参数值
        {
            printf("Parameter b is %s.\n", (char*)optarg);
        }
        else if (opt == 'c')   // 可选参数,不需要参数值
        {
            printf("Parameter c is get.\n");
        }
        else if (opt == '?')   // 未知参数,打印参数值  
        {
            printf("unknown para %c.\n", (char)optopt);
        }
    }

    return 0;
}

1.2 解析长参数

  getopt_long()包含了getopt()的功能,且可以解析长参数;

函数原型:

int getopt_long(int argc, char * const argv[], const char *optstring,
                         const struct option *longopts, int *longindex);

函数参数:

  • optstring 选项参数名
  • longopts 选项参数列表 (结构体)
  • longindex

longopts的类型为struct option,其定义如下所示:

// longopts指明了长参数的名称和属性,它是一个结构体指针
// 通常传一个结构体数组进去,每个元素代表一个参数,每个参数都是由下面的结构组成。

struct option 
{
   const char  *name;       /* 选项参数名称 */
   int          has_arg;    /* 指明选项参数是否带有参数值 0/1/2 */
   int          *flag;      
   int          val;        
};

// name:  选项参数的参数名
// has_arg: 选项参数是否有参数值 0/1/2 --> 无,有,可选
// *flag : 为NULL时,getopt_long()函数会返回val中指定的值作为选项标识;否则,getopt_long()函数会将val中指定的标识值存储在flag指向的内存中,且返回0。
// val: 指定选项的标识(int)
// longindex  如果longindex非空,它指向的变量将记录当前找到参数符合longopts里的第几个元素的描述,即是longopts的下标值。即符合条件的长选项的下标值

长参数的格式建议写为:

--reqarg1=werc16这种格式;避免出错;

代码示例:

#include <stdio.h>
#include "getopt.h"

// 定义长选项的标识
#define START_MODE_1   1
#define START_MODE_2   2
#define START_MODE_3   3

int main(int argc, char** argv)
{
    opterr = 1;     // 是否输出错误信息
    int opt = 0;
    char const *optStr = "a::b:c";

    // flag 为NULL, START_MODE直接由getopt_long()函数返回
    struct option longoptions[] = {
            {"reqarg1", required_argument, NULL, START_MODE_1},
            {"reqarg2", no_argument,       NULL, START_MODE_2},
            {"reqarg3", optional_argument, NULL, START_MODE_3}
    };

    while ((opt = getopt_long(argc, argv, optStr, longoptions, NULL)) != -1)
    {
        // 长参数处理
        if (opt == START_MODE_1)
        {
            printf("Start on mode 1 with para: %s.\n", (char*)optarg);
        }
        else if (opt == START_MODE_2)
        {
            printf("Start on mode 2.\n");
        }
        else if (opt == START_MODE_3)
        {
            if (optarg == NULL)
            {
                printf("Start on mode 3.\n");
            }
            else
            {
                printf("Start on mode 3 with para %s.\n", (char*)optarg);
            }
        }
        // 短参数处理
        else if (opt == 'a')  //可选参数,可传入或者不传入参数值
        {
            printf("Parameter a is get.\n");

            if (optarg==NULL)
                printf("No value");
            else
                printf("Value is %s", (char*)optarg);
        }
        else if (opt == 'b')   // 可选参数,必须传入参数值
        {
            printf("Parameter b is %s.\n", (char*)optarg);
        }
        else if (opt == 'c')   // 可选参数,不需要参数值
        {
            printf("Parameter c is get.\n");
        }
        else if (opt == '?')   // 未知参数,打印参数值  
        {
            printf("unknown para %c.\n", (char)optopt);
        }
    }

    return 0;
}

测试,flag设置为非空:

#include <stdio.h>
#include "getopt.h"

// 定义长选项的标识
#define START_MODE_1   1
#define START_MODE_2   2
#define START_MODE_3   3

int main(int argc, char** argv)
{
    opterr = 1;     // 是否输出错误信息
    int opt = 0;
    char const *optStr = "a::b:c";

    int cmd_code = 0;

    // flag 不为NULL, START_MODE的值会存储在cmd_code中;
    struct option longoptions[] = {
            {"reqarg1", required_argument, &cmd_code, START_MODE_1},
            {"reqarg2", no_argument,       &cmd_code, START_MODE_2},
            {"reqarg3", optional_argument, &cmd_code, START_MODE_3}
    };

    while ((opt = getopt_long(argc, argv, optStr, longoptions, NULL)) != -1)
    {
        if (cmd_code == START_MODE_1)
        {
            printf("Start on mode 1 with para: %s.\n", (char*)optarg);
        }
        else if (cmd_code == START_MODE_2)
        {
            printf("Start on mode 2.\n");
        }
        else if (cmd_code == START_MODE_3)
        {
            if (optarg == NULL)
            {
                printf("Start on mode 3.\n");
            }
            else
            {
                printf("Start on mode 3 with para %s.\n", (char*)optarg);
            }
        }
    }

    return 0;
}

1.3 解析长参数

   getopt_long_only()函数也可用来解析长参数;但是与getopt_long()函数有区别;getopt_long()函数会将-namre当作短参数来解为-n -a -m -e,而getopt_long_only会将-name和--name都当作长参数来解析;

2. getopt()源代码

  为解决getopt()能够跨平台使用,从网上找到经过修改的getopt源码,可将其编译成不同平台的库,实现跨平台使用。

2.1 getopt.h文件
# ifndef __GETOPT_H_
# define __GETOPT_H_
 
# ifdef _GETOPT_API
#     undef _GETOPT_API
# endif
//------------------------------------------------------------------------------
# if defined(EXPORTS_GETOPT) && defined(STATIC_GETOPT)
#     error "The preprocessor definitions of EXPORTS_GETOPT and STATIC_GETOPT \
can only be used individually"
# elif defined(STATIC_GETOPT)
#     pragma message("Warning static builds of getopt violate the Lesser GNU \
Public License")
#     define _GETOPT_API
# elif defined(EXPORTS_GETOPT)
#     pragma message("Exporting getopt library")
#     define _GETOPT_API __declspec(dllexport)
# else
#     pragma message("Importing getopt library")
#     define _GETOPT_API __declspec(dllimport)
# endif
 
# include <tchar.h>
// Standard GNU options
# define null_argument           0 /*Argument Null*/
# define no_argument             0 /*Argument Switch Only*/
# define required_argument       1 /*Argument Required*/
# define optional_argument       2 /*Argument Optional*/
// Shorter Versions of options
# define ARG_NULL 0 /*Argument Null*/
# define ARG_NONE 0 /*Argument Switch Only*/
# define ARG_REQ  1 /*Argument Required*/
# define ARG_OPT  2 /*Argument Optional*/
// Change behavior for C\C++
# ifdef __cplusplus
#     define _BEGIN_EXTERN_C extern "C" {
#     define _END_EXTERN_C }
#     define _GETOPT_THROW throw()
# else
#     define _BEGIN_EXTERN_C
#     define _END_EXTERN_C
#     define _GETOPT_THROW
# endif
_BEGIN_EXTERN_C
extern _GETOPT_API TCHAR *optarg;
extern _GETOPT_API int    optind;
extern _GETOPT_API int    opterr;
extern _GETOPT_API int    optopt;
struct option
{
/* The predefined macro variable __STDC__ is defined for C++, and it has the in-
   teger value 0 when it is used in an #if statement, indicating that the C++ l-
   anguage is not a proper superset of C, and that the compiler does not confor-
   m to C. In C, __STDC__ has the integer value 1. */
# if defined (__STDC__) && __STDC__
    const TCHAR* name;
# else
    TCHAR* name;
# endif
    int has_arg;
    int *flag;
    TCHAR val;
};
extern _GETOPT_API int getopt( int argc, TCHAR *const *argv
                             , const TCHAR *optstring ) _GETOPT_THROW;
extern _GETOPT_API int getopt_long
                             ( int ___argc, TCHAR *const *___argv
                             , const TCHAR *__shortopts
                             , const struct option *__longopts
                             , int *__longind ) _GETOPT_THROW;
extern _GETOPT_API int getopt_long_only
                             ( int ___argc, TCHAR *const *___argv
                             , const TCHAR *__shortopts
                             , const struct option *__longopts
                             , int *__longind ) _GETOPT_THROW;
// harly.he add for reentrant 12.09/2013
extern _GETOPT_API void getopt_reset() _GETOPT_THROW;
_END_EXTERN_C
// Undefine so the macros are not included
# undef _BEGIN_EXTERN_C
# undef _END_EXTERN_C
# undef _GETOPT_THROW
# undef _GETOPT_API
# endif  // __GETOPT_H_

2.2 getopt.cpp文件

# ifndef _CRT_SECURE_NO_WARNINGS
#     define _CRT_SECURE_NO_WARNINGS
# endif
 
# include <stdlib.h>
# include <stdio.h>
# include <tchar.h>
# include "getopt.h"
 
# ifdef __cplusplus
#     define _GETOPT_THROW throw()
# else
#     define _GETOPT_THROW
# endif
 
enum ENUM_ORDERING
{
    REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
};
 
struct _getopt_data
{
    int     optind;
    int     opterr;
    int     optopt;
    TCHAR*  optarg;
    int     __initialized;
    TCHAR*  __nextchar;
    int     __ordering;
    int     __posixly_correct;
    int     __first_nonopt;
    int     __last_nonopt;
};
static struct _getopt_data  getopt_data = { 0, 0, 0, NULL, 0, NULL, 0, 0, 0, 0 };
 
TCHAR*  optarg  = NULL;
int     optind  = 1;
int     opterr  = 1;
int     optopt  = _T( '?' );
 
static void exchange( TCHAR** argv, struct _getopt_data* d )
{
    int     bottom  = d->__first_nonopt;
    int     middle  = d->__last_nonopt;
    int     top     = d->optind;
    TCHAR*  tem;
    while ( top > middle && middle > bottom )
    {
        if ( top - middle > middle - bottom )
        {
            int len = middle - bottom;
            register int i;
            for ( i = 0; i < len; i++ )
            {
                tem = argv[bottom + i];
                argv[bottom + i] = argv[top - ( middle - bottom ) + i];
                argv[top - ( middle - bottom ) + i] = tem;
            }
            top -= len;
        }
        else
        {
            int len = top - middle;
            register int i;
            for ( i = 0; i < len; i++ )
            {
                tem = argv[bottom + i];
                argv[bottom + i] = argv[middle + i];
                argv[middle + i] = tem;
            }
            bottom += len;
        }
    }
    d->__first_nonopt += ( d->optind - d->__last_nonopt );
    d->__last_nonopt = d->optind;
}
 
static const TCHAR* _getopt_initialize( const TCHAR* optstring
                                      , struct _getopt_data* d
                                      , int posixly_correct )
{
    d->__first_nonopt = d->__last_nonopt = d->optind;
    d->__nextchar = NULL;
    d->__posixly_correct = posixly_correct
                         | !!_tgetenv( _T( "POSIXLY_CORRECT" ) );
    if ( optstring[0] == _T( '-' ) )
    {
        d->__ordering = RETURN_IN_ORDER;
        ++optstring;
    }
    else if ( optstring[0] == _T( '+' ) )
    {
        d->__ordering = REQUIRE_ORDER;
        ++optstring;
    }
    else if ( d->__posixly_correct )
    {
        d->__ordering = REQUIRE_ORDER;
    }
    else
    {
        d->__ordering = PERMUTE;
    }
    return optstring;
}
 
int _getopt_internal_r( int argc
                      , TCHAR *const * argv
                      , const TCHAR* optstring
                      , const struct option* longopts
                      , int* longind
                      , int long_only
                      , struct _getopt_data* d
                      , int posixly_correct )
{
    int print_errors    = d->opterr;
    if ( argc < 1 )
    {
        return -1;
    }
    d->optarg = NULL;
    if ( d->optind == 0 || !d->__initialized )
    {
        if ( d->optind == 0 )
        {
            d->optind = 1;
        }
        optstring = _getopt_initialize( optstring, d, posixly_correct );
        d->__initialized = 1;
    }
    else if ( optstring[0] == _T( '-' ) || optstring[0] == _T( '+' ) )
    {
        optstring++;
    }
    if ( optstring[0] == _T( ':' ) )
    {
        print_errors = 0;
    }
    if ( d->__nextchar == NULL || *d->__nextchar == _T( '\0' ) )
    {
        if ( d->__last_nonopt > d->optind )
        {
            d->__last_nonopt = d->optind;
        }
        if ( d->__first_nonopt > d->optind )
        {
            d->__first_nonopt = d->optind;
        }
        if ( d->__ordering == PERMUTE )
        {
            if ( d->__first_nonopt != d->__last_nonopt
              && d->__last_nonopt != d->optind )
            {
                exchange( ( TCHAR * * ) argv, d );
            }
            else if ( d->__last_nonopt != d->optind )
            {
                d->__first_nonopt = d->optind;
            }
            while ( d->optind
                  < argc
                 && ( argv[d->optind][0] != _T( '-' )
                   || argv[d->optind][1] == _T( '\0' ) ) )
            {
                d->optind++;
            }
            d->__last_nonopt = d->optind;
        }
        if ( d->optind != argc && !_tcscmp( argv[d->optind], _T( "--" ) ) )
        {
            d->optind++;
            if ( d->__first_nonopt != d->__last_nonopt
              && d->__last_nonopt != d->optind )
            {
                exchange( ( TCHAR * * ) argv, d );
            }
            else if ( d->__first_nonopt == d->__last_nonopt )
            {
                d->__first_nonopt = d->optind;
            }
            d->__last_nonopt = argc;
            d->optind = argc;
        }
        if ( d->optind == argc )
        {
            if ( d->__first_nonopt != d->__last_nonopt )
            {
                d->optind = d->__first_nonopt;
            }
            return -1;
        }
        if ( ( argv[d->optind][0] != _T( '-' )
            || argv[d->optind][1] == _T( '\0' ) ) )
        {
            if ( d->__ordering == REQUIRE_ORDER )
            {
                return -1;
            }
            d->optarg = argv[d->optind++];
            return 1;
        }
        d->__nextchar = ( argv[d->optind]
                        + 1 + ( longopts != NULL
                             && argv[d->optind][1] == _T( '-' ) ) );
    }
    if ( longopts != NULL
        && ( argv[d->optind][1] == _T( '-' )
            || ( long_only && ( argv[d->optind][2]
                                || !_tcschr( optstring, argv[d->optind][1] ) )
               )
           )
        )
    {
        TCHAR*                  nameend;
        const struct option*    p;
        const struct option*    pfound      = NULL;
        int                     exact       = 0;
        int                     ambig       = 0;
        int                     indfound    = -1;
        int                     option_index;
        for ( nameend = d->__nextchar;
              *nameend && *nameend != _T( '=' );
              nameend++ )
            ;
        for ( p = longopts, option_index = 0; p->name; p++, option_index++ )
        {
            if ( !_tcsncmp( p->name, d->__nextchar, nameend - d->__nextchar ) )
            {
                if ( ( unsigned int ) ( nameend - d->__nextchar )
                  == ( unsigned int ) _tcslen( p->name ) )
                {
                    pfound = p;
                    indfound = option_index;
                    exact = 1;
                    break;
                }
                else if ( pfound == NULL )
                {
                    pfound = p;
                    indfound = option_index;
                }
                else if ( long_only
                       || pfound->has_arg != p->has_arg
                       || pfound->flag != p->flag
                       || pfound->val != p->val )
                {
                         ambig = 1;
                }
            }
        }
        if ( ambig && !exact )
        {
            if ( print_errors )
            {
                _ftprintf( stderr
                         , _T( "%s: option '%s' is ambiguous\n" )
                         , argv[0]
                         , argv[d->optind] );
            }
            d->__nextchar += _tcslen( d->__nextchar );
            d->optind++;
            d->optopt = 0;
            return _T( '?' );
        }
        if ( pfound != NULL )
        {
            option_index = indfound;
            d->optind++;
            if ( *nameend )
            {
                if ( pfound->has_arg )
                {
                    d->optarg = nameend + 1;
                }
                else
                {
                    if ( print_errors )
                    {
                        if ( argv[d->optind - 1][1] == _T( '-' ) )
                        {
                            _ftprintf( stderr
                                     , _T( "%s: option '--%s' doesn't allow " )
                                       _T( "an argument\n" )
                                     , argv[0]
                                     , pfound->name );
                        }
                        else
                        {
                            _ftprintf( stderr
                                     , _T( "%s: option '%c%s' doesn't allow " )
                                       _T( "an argument\n" )
                                     , argv[0]
                                     , argv[d->optind - 1][0]
                                     , pfound->name );
                        }
                    }
                    d->__nextchar += _tcslen( d->__nextchar );
                    d->optopt = pfound->val;
                    return _T( '?' );
                }
            }
            else if ( pfound->has_arg == 1 )
            {
                if ( d->optind < argc )
                {
                    d->optarg = argv[d->optind++];
                }
                else
                {
                    if ( print_errors )
                    {
                        _ftprintf( stderr
                                 , _T( "%s: option '--%s' requires an " )
                                   _T( "argument\n" )
                                 , argv[0]
                                 , pfound->name );
                    }
                    d->__nextchar += _tcslen( d->__nextchar );
                    d->optopt = pfound->val;
                    return optstring[0] == _T( ':' ) ? _T( ':' ) : _T( '?' );
                }
            }
            d->__nextchar += _tcslen( d->__nextchar );
            if ( longind != NULL )
            {
                *longind = option_index;
            }
            if ( pfound->flag )
            {
                *( pfound->flag ) = pfound->val;
                return 0;
            }
            return pfound->val;
        }
        if ( !long_only
          || argv[d->optind][1]
          == _T( '-' )
          || _tcschr( optstring
                    , *d->__nextchar )
          == NULL )
        {
            if ( print_errors )
            {
                if ( argv[d->optind][1] == _T( '-' ) )
                {
                    /* --option */
                    _ftprintf( stderr
                             , _T( "%s: unrecognized option '--%s'\n" )
                             , argv[0]
                             , d->__nextchar );
                }
                else
                {
                    /* +option or -option */
                    _ftprintf( stderr
                             , _T( "%s: unrecognized option '%c%s'\n" )
                             , argv[0]
                             , argv[d->optind][0]
                             , d->__nextchar );
                }
            }
            d->__nextchar = ( TCHAR * ) _T( "" );
            d->optind++;
            d->optopt = 0;
            return _T( '?' );
        }
    }
    {
        TCHAR   c       = *d->__nextchar++;
        TCHAR*  temp    = ( TCHAR* ) _tcschr( optstring, c );
        if ( *d->__nextchar == _T( '\0' ) )
        {
            ++d->optind;
        }
        if ( temp == NULL || c == _T( ':' ) || c == _T( ';' ) )
        {
            if ( print_errors )
            {
                _ftprintf( stderr
                         , _T( "%s: invalid option -- '%c'\n" )
                         , argv[0]
                         , c );
            }
            d->optopt = c;
            return _T( '?' );
        }
        if ( temp[0] == _T( 'W' ) && temp[1] == _T( ';' ) )
        {
            TCHAR*                  nameend;
            const struct option*    p;
            const struct option*    pfound      = NULL;
            int                     exact       = 0;
            int                     ambig       = 0;
            int                     indfound    = 0;
            int                     option_index;
            if ( *d->__nextchar != _T( '\0' ) )
            {
                d->optarg = d->__nextchar;
                d->optind++;
            }
            else if ( d->optind == argc )
            {
                if ( print_errors )
                {
                    _ftprintf( stderr
                             , _T( "%s: option requires an argument -- '%c'\n" )
                             , argv[0]
                             , c );
                }
                d->optopt = c;
                if ( optstring[0] == _T( ':' ) )
                {
                    c = _T( ':' );
                }
                else
                {
                    c = _T( '?' );
                }
                return c;
            }
            else
            {
                d->optarg = argv[d->optind++];
            }
            for ( d->__nextchar = nameend = d->optarg;
                  *nameend && *nameend != _T( '=' );
                  nameend++ )
                ;
            for ( p = longopts, option_index = 0;
                  p->name;
                  p++, option_index++ )
            {
                if ( !_tcsncmp( p->name
                              , d->__nextchar
                              , nameend - d->__nextchar ) )
                {
                    if ( ( unsigned int ) ( nameend - d->__nextchar )
                      == _tcslen( p->name ) )
                    {
                        pfound = p;
                        indfound = option_index;
                        exact = 1;
                        break;
                    }
                    else if ( pfound == NULL )
                    {
                        pfound = p;
                        indfound = option_index;
                    }
                    else if ( long_only
                           || pfound->has_arg != p->has_arg
                           || pfound->flag != p->flag
                           || pfound->val != p->val )
                    {
                             ambig = 1;
                    }
                }
            }
            if ( ambig && !exact )
            {
                if ( print_errors )
                {
                    _ftprintf( stderr
                             , _T( "%s: option '-W %s' is ambiguous\n" )
                             , argv[0]
                             , d->optarg );
                }
                d->__nextchar += _tcslen( d->__nextchar );
                d->optind++;
                return _T( '?' );
            }
            if ( pfound != NULL )
            {
                option_index = indfound;
                if ( *nameend )
                {
                    if ( pfound->has_arg )
                    {
                        d->optarg = nameend + 1;
                    }
                    else
                    {
                        if ( print_errors )
                        {
                            _ftprintf( stderr
                                     , _T( "%s: option '-W %s' doesn't allow " )
                                       _T( "an argument\n" )
                                     , argv[0]
                                     , pfound->name );
                        }
                        d->__nextchar += _tcslen( d->__nextchar );
                        return _T( '?' );
                    }
                }
                else if ( pfound->has_arg == 1 )
                {
                    if ( d->optind < argc )
                    {
                        d->optarg = argv[d->optind++];
                    }
                    else
                    {
                        if ( print_errors )
                        {
                            _ftprintf( stderr
                                     , _T( "%s: option '-W %s' requires an " )
                                       _T( "argument\n" )
                                     , argv[0]
                                     , pfound->name );
                        }
                        d->__nextchar += _tcslen( d->__nextchar );
                        return optstring[0] == _T(':') ? _T(':') : _T('?');
                    }
                }
                else
                {
                    d->optarg = NULL;
                }
                d->__nextchar += _tcslen( d->__nextchar );
                if ( longind != NULL )
                {
                    *longind = option_index;
                }
                if ( pfound->flag )
                {
                    *( pfound->flag ) = pfound->val;
                    return 0;
                }
                return pfound->val;
            }
            d->__nextchar = NULL;
            return _T( 'W' );
        }
        if ( temp[1] == _T( ':' ) )
        {
            if ( temp[2] == _T( ':' ) )
            {
                if ( *d->__nextchar != _T( '\0' ) )
                {
                    d->optarg = d->__nextchar;
                    d->optind++;
                }
                else
                {
                    d->optarg = NULL;
                }
                d->__nextchar = NULL;
            }
            else
            {
                if ( *d->__nextchar != _T( '\0' ) )
                {
                    d->optarg = d->__nextchar;
                    d->optind++;
                }
                else if ( d->optind == argc )
                {
                    if ( print_errors )
                    {
                        _ftprintf( stderr
                                 , _T( "%s: option requires an " )
                                   _T( "argument -- '%c'\n" )
                                 , argv[0]
                                 , c );
                    }
                    d->optopt = c;
                    if ( optstring[0] == _T( ':' ) )
                    {
                        c = _T( ':' );
                    }
                    else
                    {
                        c = _T( '?' );
                    }
                }
                else
                {
                    d->optarg = argv[d->optind++];
                }
                d->__nextchar = NULL;
            }
        }
        return c;
    }
}
 
int _getopt_internal( int argc
                    , TCHAR *const * argv
                    , const TCHAR* optstring
                    , const struct option* longopts
                    , int* longind
                    , int long_only
                    , int posixly_correct )
{
    int result;
    getopt_data.optind = optind;
    getopt_data.opterr = opterr;
    result = _getopt_internal_r( argc
                               , argv
                               , optstring
                               , longopts
                               , longind
                               , long_only
                               , &getopt_data
                               , posixly_correct );
    optind = getopt_data.optind;
    optarg = getopt_data.optarg;
    optopt = getopt_data.optopt;
    return result;
}


int getopt( int argc, TCHAR *const * argv, const TCHAR* optstring) _GETOPT_THROW
{
    return _getopt_internal( argc
                           , argv
                           , optstring
                           , ( const struct option * ) 0
                           , ( int * ) 0
                           , 0
                           , 0 );
}


int getopt_long( int argc
               , TCHAR *const * argv
               , const TCHAR* options
               , const struct option* long_options
               , int* opt_index ) _GETOPT_THROW
{
    return _getopt_internal( argc
                           , argv
                           , options
                           , long_options
                           , opt_index
                           , 0
                           , 0 );
}
 
int _getopt_long_r( int argc
                  , TCHAR *const * argv
                  , const TCHAR* options
                  , const struct option* long_options
                  , int* opt_index
                  , struct _getopt_data* d )
{
    return _getopt_internal_r( argc
                             , argv
                             , options
                             , long_options
                             , opt_index
                             , 0
                             , d
                             , 0 );
}
 
int getopt_long_only( int argc
                    , TCHAR *const * argv
                    , const TCHAR* options
                    , const struct option* long_options
                    , int* opt_index ) _GETOPT_THROW
{
    return _getopt_internal( argc
                           , argv
                           , options
                           , long_options
                           , opt_index
                           , 1
                           , 0 );
}
 
int _getopt_long_only_r( int argc
                       , TCHAR *const * argv
                       , const TCHAR* options
                       , const struct option* long_options
                       , int* opt_index
                       , struct _getopt_data* d )
{
    return _getopt_internal_r( argc
                             , argv
                             , options
                             , long_options
                             , opt_index
                             , 1
                             , d
                             , 0 );
}
 
void getopt_reset() _GETOPT_THROW
{
    optarg  = NULL;
    optind  = 1;
    opterr  = 1;
    optopt  = _T( '?' );
    //
    getopt_data.optind            = 0;
    getopt_data.opterr            = 0;
    getopt_data.optopt            = 0;
    getopt_data.optarg            = NULL;
    getopt_data.__initialized     = 0;
    getopt_data.__nextchar        = NULL;
    getopt_data.__ordering        = 0;
    getopt_data.__posixly_correct = 0;
    getopt_data.__first_nonopt    = 0;
    getopt_data.__last_nonopt     = 0;
}


getopt库源代码以及编译方法可参考:CMake实战

posted @ 2023-11-04 10:05  Alpha205  阅读(605)  评论(0编辑  收藏  举报