65.9K
CodeProject 正在变化。 阅读更多。
Home

C 和 C++ 的另一个参数解析函数

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.72/5 (9投票s)

2013年10月13日

MIT

5分钟阅读

viewsIcon

30841

downloadIcon

391

参数解析函数可识别可选参数和位置参数。

引言

get_arguments函数是为了提供跨平台的参数解析代码而编写的。此外,与其他一些常见的参数解析函数不同,get_arguments代码可以根据MIT许可条款使用。

get_arguments函数支持短选项和长选项,并且可以处理ASCII、UTF-8和Unicode字符集。

允许使用单个字符和长选项名称。

可选参数和位置参数可以混合使用。允许混合使用
可选参数和位置参数的优点是,可选参数要么必须接受一个附加参数,要么不接受,但不能同时兼顾。


另外,可选参数名称不能以数字、句点或加号开头。这简化了解析,因为以破折号后跟这些字符之一开头的可能是数字位置参数的开头。

背景 

C和C++的“main”函数接受两个参数。一个是名为“argc”的整数参数,另一个是指向字符串参数的指针数组。字符串参数是在程序运行时由用户在命令行提供的。第一个字符串参数是正在运行的程序的路径和文件名。

此代码中的get_arguments函数接受可选参数和位置参数。可选参数使用以破折号开头的开关来指定。单个破折号接受单个字符的开关名称。双破折号接受一个以上字符的可选开关名称。可选开关名称可能是完整的可选参数,或者后面可能跟一个必需的字符串。

示例

ProgramName -x --name Fred --age 57

该示例在指定“-x”开关时设置程序值,并设置名字为Fred和年龄为57。

位置参数通常不以前导破折号开头。只有当参数是数字时,位置参数才以破折号(即减号)开头。为避免解析歧义,开关名称从不以数字开头。位置参数必须始终按指定顺序指定。

在先前的程序行中添加两个位置参数将得到

ProgramName positional1 someotherargument -x --name Fred --age 57

代码

get_arguments.h头文件显示了定义,并记录了“get_arguments”函数的参数和用法。包含在get_arguments.h中以定义“TCHAR”的platform_os.h文件如下所示。

get_arguments函数的参数在get_arguments头文件中,此处重复。

        参数名称
        描述
argc参数的数量。

        
argv


指向参数字符串的指针数组。

argument_option_array_ptr 

指向ArgOption_t结构体数组的指针,该数组指定每个可选参数的属性。

该数组的一个示例声明可能是

static const ArgOption_t argument_option_array[] =
{
    { 'x', NULL, OPTION_NO_PARAMETER, },
    { 'f', NULL, OPTION_REQUIRES_PARAMETER, },
    { 'b', "build", OPTION_REQUIRES_PARAMETER, },
    { 'h', "help", OPTION_NO_PARAMETER, },
    {   0, NULL, OPTION_NO_PARAMETER }
};

这将允许以下形式的可选参数

-x
-f <somestring>
-b <somestring>
--build <somestring>
-h
--help

由于使用了OPTION_REQUIRES_PARAMETER,因此必须在-s参数后提供一个字符串。

最后一行必须按原样提供以终止数据。

必须指定短参数名、长参数名或两者都指定。如果只指定了长名称,则ArgOption_t结构体的第一个字段必须设置为一个带外整型值,对于ASCII或Unicode字符集,该值可以是0x011FFFF以上的任何值。
arg_index_ptr 指向“int”值的指针,该值用于索引argv[]数组。arg_index_ptr指向的值指定了位置参数的索引,或者指定了具有OPTION_REQUIRES_PARAMETER属性的可选参数的必需参数的索引。

/* ********************************************************************
 * Header File: get_arguments.h
 * Author: Bill Hallahan
 * Date: September 26, 2013
 *
 * Copyright (C) 2013 William Hallahan
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge,
 * publish, distribute, sublicense, and/or sell copies of the Software,
 * and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 ******************************************************************* */

#ifndef GET_ARGUMENTS_H
#define GET_ARGUMENTS_H

#include "platform_os.h"

#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */

/* The get_arguments function either returns an option
 * character or one of these values. */
typedef enum
{
    ARG_ERROR_INVALID_SWITCH = -2,
    ARG_ERROR_MISSING_SWITCH_ARGUMENT = -1,
    ARG_NO_MORE_ARGUMENTS = 0,
    ARG_POSITIONAL_ARGUMENT = 0x7FFFFFFF
} ArgOptionChar_t;

/* Used to set whether an option requires a parameter. */
typedef enum
{
    OPTION_NO_PARAMETER,
    OPTION_REQUIRES_PARAMETER
} ArgOptionParameter_t;

/* The option structure. 
 * Element c stores the short option character, i.e. "b" for "-b".
 *   name is the long option name string, "build" for "--build".
 * requires_params is set to one of the ArgOptionParameter_t
 *   enum values to indicate whether the option requires a parameter. */
typedef struct
{
    int c;
    TCHAR * long_name;
    ArgOptionParameter_t requires_param;
} ArgOption_t;

 /* ********************************************************************
 * Function: get_arguments
 *
 * Abstract:
 *
 *  The get_arguments function was written to provide argument
 *  parsing code for multiple platforms.  Also, the code can
 *  be used under the terms of the MIT license.
 *
 *  The get_arguments function allows both short and long
 *  optional switches, and will work with the ASCII, UTF-8, and
 *  Unicode character sets.
 *
 *  Both single character and long optional argument switch
 *  named are allowed.
 *
 *  Optional arguments and positional arguments can be interspersed.
 *
 *  The benefit of allowing interspersed optional and positional
 *  arguments comes at the cost of requiring that an optional argument
 *  either does, or does not, take an additional parameter, but not both.
 *
 *  Also, optional argument names cannot start with a digit
 *  character.  This simplified parsing as a dash followed by
 *  a digit character could also be the start of a numeric
 *  positional argument.
 *
 *  Input:
 *
 *    The first two arguments are passed into the 'main' function of
 *    a C or C++ console program.
 *
 *    argc                      - The number of arguments.
 *
 *    argv                      - An array of pointers to argument strings.
 *
 *    argument_option_array_ptr - A pointer to an array of ArgOption_t
 *                                structures that specifies that attributes
 *                                of each optional argument.
 *
 *                                An example declaration for the array might be:
 *
 *                                static const ArgOption_t argument_option_array[] =
 *                                {
 *                                    { 'x', NULL, OPTION_NO_PARAMETER, },
 *                                    { 'f', NULL, OPTION_REQUIRES_PARAMETER, },
 *                                    { 'b', "build", OPTION_REQUIRES_PARAMETER, },
 *                                    { 'h', "help", OPTION_NO_PARAMETER, },
 *                                    {   0, NULL, OPTION_NO_PARAMETER }
 *                                };
 *
 *                                This would allow optional arguments of the form:
 *
 *                                -x
 *                                -f <somestring>
 *                                -b <somestring>
 *                                --build <somestring>
 *                                -h
 *                                --help
 *
 *                                A string must be supplied after the -s parameter
 *                                because OPTION_REQUIRES_PARAMETER is used.
 *                                
 *                                The final line must always be supplied as written
 *                                to terminate the data.
 *
 *                                Either a short argument name, a long
 *                                argument name, or both must be specified.
 *                                If only a long name is specified, the first
 *                                field of the ArgOption_t structure must be
 *                                set to an out-of-band integer value, which
 *                                for either ASCII or Unicode character sets
 *                                can be any value above 0x011FFFF.
 *                                 
 *
 *    arg_index_ptr               A pointer to an 'int' value that is used
 *                                to index into the argv[] array. The value
 *                                pointed to by arg_index_ptr specifies either
 *                                the index of a positional argument or the
 *                                index of the required parameter for an
 *                                optional argument that has the
 *                                OPTION_REQUIRES_PARAMETER attribute.
 *
 *  Returns:
 *
 *    An integer value that is either the option character for an
 *    optional argument, which is the first field in OptionsArg_t
 *    structure that matches the optional argument passed on the
 *    command line, or, one of the following values.
 *
 *    ARG_POSITIONAL_ARGUMENT  - Specified that argument in the argv
 *                               array, indexed by the index value
 *                               pointed to by arg_index_ptr, is a
 *                               positional argument.
 *
 *    ARG_NO_MORE_ARGUMENTS    - Specifies that there are no more
 *                               arguments to parse.
 *
 *    ARG_ERROR_INVALID_SWITCH - Invalid switch specified on the command
 *                               line.
 *
 *    ARG_ERROR_MISSING_SWITCH_ARGUMENT - A dash character for an
 *                                        optional argument was found
 *                                        but is missing required
 *                                        characters following the dash.
 *
 *  Any returned character value, represented as an integer, and
 *  the value of ARG_POSITIONAL_ARGUMENT, are always greater than
 *  zero.  ARG_NO_MORE_ARGUMENTS equals zero, and the error return
 *  values are negative numbers, so parsing should be done until
 *  the return value of this function is not greater than
 *  ARG_NO_MORE_ARGUMENTS, or zero.
 *
 ******************************************************************* */

int get_arguments(int argc,
                  TCHAR *argv[],
                  const ArgOption_t * argument_option_array_ptr,
                  int * arg_index_ptr);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* GET_ARGUMENTS_H */

文件get_arguments.c是

/* ********************************************************************
 * Header File: get_arguments.c
 * Author: Bill Hallahan
 * Date: September 26, 2013
 *
 * Copyright (C) 2013 William Hallahan
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge,
 * publish, distribute, sublicense, and/or sell copies of the Software,
 * and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 ******************************************************************* */

#include "get_arguments.h"

int get_arguments(int argc,
                  TCHAR *argv[],
                  const ArgOption_t * argument_option_array_ptr,
                  int * arg_index_ptr)
{
    int arg_length = 0;
    int option_param_type = OPTION_NO_PARAMETER;
    const ArgOption_t * arg_option_ptr = argument_option_array_ptr;
    TCHAR * argument_ptr = NULL;
    int option_character = ARG_NO_MORE_ARGUMENTS;

    /* Increment the index to point to the next argument.
     * On the first call to this function, this increment
     * skips the program name. */
    ++(*arg_index_ptr);

    /* Are there more arguments? */
    if (*arg_index_ptr < argc)
    {
        /* There are more arguments.  Get the current argument string
         * and the number of characters in the argument string. */
        argument_ptr = argv[*arg_index_ptr];
        arg_length = _tcslen(argument_ptr);

        /* Check for the dash character.  The dash character starts either
         * an optional argument or a number. */
        if (argument_ptr[0] == _T('-'))
        {
            /* Optional arguments always have at least one non-digit character
             * after the dash character. */
            if (arg_length > 1)
            {
                /* A dash followed by a digit, period, or a plus sign is not a
                 * valid switch name and is considered to be a negative number. */
                if ((_istdigit(argument_ptr[1]))
                    || (argument_ptr[1] == _T('.'))
                    || (argument_ptr[1] == _T('+')))
                {
                    option_character = ARG_POSITIONAL_ARGUMENT;
                }
                else
                {
                    /* This is an optional argument.  Long optional arguments
                     * start with two dash characters followed by at least one
                     * character.  Check for a second dash character. */
                    if ((arg_length > 2) && (argument_ptr[1] == _T('-')))
                    {
                        /* This is a long optional argument of the form "--name".
                         * Skip the second '_' character. */
                        argument_ptr += 2;

                        /* Search for the argument long name in the argument options array */
                        while (arg_option_ptr->c != _T('\0'))
                        {
                            if ((arg_option_ptr->long_name != NULL)
                                && (_tcscmp(arg_option_ptr->long_name, argument_ptr) == 0))
                            {
                                option_character = arg_option_ptr->c;
                                option_param_type = arg_option_ptr->requires_param;
                                break;
                            }

                            /* Point to the next ArgOption_t instance in the array. */
                            ++arg_option_ptr;
                        }
                    }
                    else
                    {
                        /* This is a short optional argument of the form "-n".
                         * Skip the '_' character. */
                        ++argument_ptr;

                        /* This is a short optional argument of the form "-n".
                         * Search for the argument character in the argument options array */
                        while (arg_option_ptr->c != _T('\0'))
                        {
                            if (argument_ptr[0] == arg_option_ptr->c)
                            {
                                option_character = arg_option_ptr->c;
                                option_param_type = arg_option_ptr->requires_param;
                                break;
                            }

                            /* Point to the next ArgOption_t instance in the array. */
                            ++arg_option_ptr;
                        }
                    }

                    /* Check to see if the argument option matched any ArgOption_t entry
                     * in the array pointed to by 'argument_option_array_ptr'. */
                    if (option_character != ARG_NO_MORE_ARGUMENTS)
                    {
                        /* An option switch was found.  Does the switch require an argument? */
                        if (option_param_type == OPTION_REQUIRES_PARAMETER)
                        {
                            /* Increment the index to point to the switch argument. */
                            ++(*arg_index_ptr);

                            if (*arg_index_ptr >= argc)
                            {
                                /* The option parameter is missing.  Return an error. */
                                --(*arg_index_ptr);
                                option_character = ARG_ERROR_MISSING_SWITCH_ARGUMENT;
                            }
                        }
                    }
                    else
                    {
                        /* No option matched.  Return an error. */
                        option_character = ARG_ERROR_INVALID_SWITCH;
                    }
                }        
            }
            /* A single dash character is not a valid argument. */
            else if (arg_length == 1)
            {
                option_character = ARG_ERROR_MISSING_SWITCH_ARGUMENT;
            }
            else
            {
                option_character = ARG_POSITIONAL_ARGUMENT;
            }
        }
        else
        {
            option_character = ARG_POSITIONAL_ARGUMENT;
        }
    }
    else
    {
        option_character = ARG_NO_MORE_ARGUMENTS;
    }

    return option_character;
}


platform_os.h头文件。

platform_os.h头文件由get_arguments.h文件包含,并允许代码在Windows和Linux上运行。我很久以前在Linux上测试过,但最近没有测试过,所以C库文件的“#include”可能需要调整。我将在再次测试Linux时更新本文。此代码在Windows上可与ASCII或Unicode构建正常工作。

/* ********************************************************************
 * Header File: platform_os.h
 * Author: Bill Hallahan
 * Date: September 26, 2013
 *
 * Platform and operating system specific definitions.
 *
 * Copyright (C) 2013 William Hallahan
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge,
 * publish, distribute, sublicense, and/or sell copies of the Software,
 * and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 ******************************************************************* */

#ifndef PLATFORM_OS_H
#define PLATFORM_OS_H

#ifdef WIN32
#include <tchar.h>
#ifdef UNICODE
#include <wctype.h>
#else
#include <ctype.h>

#endif /* UNICODE */
#endif /* WIN32 */

#ifdef __linux__
typedef char TCHAR;

#define SET_STDOUT_MODE
#define _T(X) X
#define _tmain main
#define _tprintf printf
#define _istdigit isdigit
#define _tcstol strtol
#define _tcstod strtod
#endif /* __linux__ */

#define FALSE (0)
#define TRUE (1)

typedef int BOOL;

#endif /* PLATFORM_OS_H */
 




我为什么编写get_arguments函数

我发现自己编写了大量的C和C++控制台程序,并且意识到大多数时候解析代码与其他程序相似。为了节省时间,我用Python编写了一个代码生成器。我发现其他解析函数受到其许可证的限制,或者其行为不符合我的要求。特别是,我希望能够混合使用可选参数和位置参数。我还希望代码能在多个平台和多种字符集上运行。

与get_argument.h头文件中的示例不同,ParseExample.c程序使用_T()宏为字符和字符串定义选项数组,以便能够使用不同的字符集进行编译。

关于ParseExample.c程序

ParseExample.c文件演示了“get_arguments”函数的一种可能用法。

ParseExample.c被设计为只有一个返回点,这极大地有助于调试,因为在第一次调试程序时只需要设置一个断点。

为了避免过度缩进或使用“goto”关键字处理错误,同时仍允许单个返回点,ParseExample使用了以下有用的结构。非零状态值表示错误。错误会导致跳出do-while语句,由于结尾的“while (FALSE);”,这实际上不是一个循环。这是一个非常实用的结构。

    do
    {
        [some code here]

        if (status != 0)
        {
            break;
        }

        [More code here]

        if (status != 0)
        {
            break;
        }

        [Even more code here]

        if (status != 0)
        {
            break;
        }
    }
    while (FALSE);

    [More code here]

    
  











ParseExample.c程序源代码

 

/* Program: ParseExample.c */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef __linux__
#include <unistd.h>
#endif
#include "get_arguments.h"
#include "platform_os.h"

/* Define the option character values for optional arguments
 * that only have a long option name. */
typedef enum
{
    OPTINT0 = 1114112
} OptChar_t;

/* Structure type used for program arguments. */
typedef struct
{
    TCHAR * stringVar;
    int intVar;
    float floatVar;
    double doubleVar;
    TCHAR * optstringVar;
    int optIntVar;
    float optFloatVar;
    double optDoubleVar;
    BOOL optBoolVar;
    BOOL optAnotherBoolVar;
} ProgramArgument_T;

/* Forward declarations. */
int executeParseExample(ProgramArgument_T * program_args_ptr);
void displayUsage();

/* Start of main program. */
int _tmain(int argc, TCHAR* argv[])
{
    int status = 0;
    int arg_index = 0;
    int positional_arg_index = 0;
    int arg_result = 0;
    TCHAR * stop_ptr = NULL;

    ProgramArgument_T program_args;

    static const ArgOption_t argument_option_array[] =
    {
        { _T('s'), NULL, OPTION_REQUIRES_PARAMETER, },
        { _T('i'), NULL, OPTION_REQUIRES_PARAMETER, },
        { _T('f'), NULL, OPTION_REQUIRES_PARAMETER, },
        { _T('d'), NULL, OPTION_REQUIRES_PARAMETER, },
        { _T('b'), _T("build"), OPTION_NO_PARAMETER, },
        { OPTINT0, _T("another"), OPTION_NO_PARAMETER, },
        { _T('h'), _T("help"), OPTION_NO_PARAMETER },
        { 0, NULL, OPTION_NO_PARAMETER }
    };

    do
    {
        /* If there are no arguments supplied then display the command to get help. */
        if (argc < 2)
        {
            _tprintf(_T("Program ParseExample [version 1.1 TODO:]\n"));
            _tprintf(_T("Copyright (C) 2013 William Hallahan.\n\n"));
            _tprintf(_T("For help, enter:\n\n"));
            _tprintf(_T("    ParseExample -h\n\n"));
            break;
        }

        /* Initialize the program argument structure. */
        program_args.stringVar = _T("");
        program_args.intVar = 0;
        program_args.floatVar = 0.0F;
        program_args.doubleVar = 0.0;
        program_args.optstringVar = _T("");
        program_args.optIntVar = 0;
        program_args.optFloatVar = 0.0F;
        program_args.optDoubleVar = 0.0;
        program_args.optBoolVar = FALSE;
        program_args.optAnotherBoolVar = TRUE;

        /* Call the get_arguments function to populate the argument variables. */
        while ((status == 0)
            && ((arg_result = get_arguments(argc,
                                            argv,
                                            &argument_option_array[0],
                                            &arg_index)) > ARG_NO_MORE_ARGUMENTS))
        {
            if (arg_result != ARG_POSITIONAL_ARGUMENT)
            {
                /* Process an optional argument. */
                switch (arg_result)
                {
                case 's':
                    {
                        program_args.optstringVar = argv[arg_index];
                    }
                    break;

                case 'i':
                    {
                        program_args.optIntVar = _tcstol(argv[arg_index], &stop_ptr, 10);
                    if (_tcslen(stop_ptr) > 0)
                    {
                        _tprintf(_T("Error in argument %s.\n"), argv[arg_index]);
                        status = -1;
                    }
                    }
                    break;

                case 'f':
                    {
                        program_args.optFloatVar = (float)_tcstod(argv[arg_index], &stop_ptr);
                    if (_tcslen(stop_ptr) > 0)
                    {
                        _tprintf(_T("Error in argument %s.\n"), argv[arg_index]);
                        status = -1;
                    }
                    }
                    break;

                case 'd':
                    {
                        program_args.optDoubleVar = _tcstod(argv[arg_index], &stop_ptr);
                    if (_tcslen(stop_ptr) > 0)
                    {
                        _tprintf(_T("Error in argument %s.\n"), argv[arg_index]);
                        status = -1;
                    }
                    }
                    break;

                case 'b':
                    {
                        program_args.optBoolVar = TRUE;
                    }
                    break;

                case OPTINT0:
                    {
                        program_args.optAnotherBoolVar = FALSE;
                    }
                    break;

                case 'h':
                    {
                        displayUsage();
                        status = 1;
                    }
                    break;

                default:
                    {
                        /* It should be impossible to reach here. */
                        _tprintf(_T("Program error.  Contact support.\n"));
                        status = 1;
                    }
                    break;
                }
            }
            else
            {
                /* Process a positional argument. */
                switch (positional_arg_index)
                {
                case 0:
                    {
                        program_args.stringVar = argv[arg_index];
                    }
                    break;

                case 1:
                    {
                        program_args.intVar = _tcstol(argv[arg_index], &stop_ptr, 10);
                    if (_tcslen(stop_ptr) > 0)
                    {
                        _tprintf(_T("Error in argument %s.\n"), argv[arg_index]);
                        status = -1;
                    }
                    }
                    break;

                case 2:
                    {
                        program_args.floatVar = (float)_tcstod(argv[arg_index], &stop_ptr);
                    if (_tcslen(stop_ptr) > 0)
                    {
                        _tprintf(_T("Error in argument %s.\n"), argv[arg_index]);
                        status = -1;
                    }
                    }
                    break;

                case 3:
                    {
                        program_args.doubleVar = _tcstod(argv[arg_index], &stop_ptr);
                    if (_tcslen(stop_ptr) > 0)
                    {
                        _tprintf(_T("Error in argument %s.\n"), argv[arg_index]);
                        status = -1;
                    }
                    }
                    break;

                default:
                   {
                        _tprintf(_T("Too many positional arguments atarting at %s.\n"), argv[arg_index]);
                        status = -1;
                         break;
                   }
                }

                /* Increment the positional argument index. */
                ++positional_arg_index;
            }
        }

        /* Check for a command line error. */
        if (status != 0)
        {
            break;
        }
        else if (arg_result == ARG_ERROR_MISSING_SWITCH_ARGUMENT)
        {
            _tprintf(_T("Error - missing switch argument for switch %s.\n"), argv[arg_index]);
            status = -1;
            break;
        }
        else if (arg_result == ARG_ERROR_INVALID_SWITCH)
        {
            _tprintf(_T("Invalid switch argument %s.\n"), argv[arg_index]);
            status = -1;
            break;
        }
        /* Were the required number of positional arguments supplied? */
        else if (positional_arg_index < 4)
        {
            _tprintf(_T("Too few arguments.\n"));
            status = -1;
            break;
        }
        else
        {
            /* Process the input data. */
            status = executeParseExample(&program_args);
        }
    }
    while (FALSE);

    return status;
}

/* Function: executeParseExample */
int executeParseExample(ProgramArgument_T * program_args_ptr)
{
    /* Display the input parameters. */
    _tprintf(_T("TCHAR * stringVar = %s\n"), program_args_ptr->stringVar);
    _tprintf(_T("int intVar = %d\n"), program_args_ptr->intVar);
    _tprintf(_T("float floatVar = %f\n"), program_args_ptr->floatVar);
    _tprintf(_T("double doubleVar = %f\n"), program_args_ptr->doubleVar);
    _tprintf(_T("TCHAR * optstringVar = %s\n"), program_args_ptr->optstringVar);
    _tprintf(_T("int optIntVar = %d\n"), program_args_ptr->optIntVar);
    _tprintf(_T("float optFloatVar = %f\n"), program_args_ptr->optFloatVar);
    _tprintf(_T("double optDoubleVar = %f\n"), program_args_ptr->optDoubleVar);
    _tprintf(_T("BOOL optBoolVar = %d\n"), program_args_ptr->optBoolVar);
    _tprintf(_T("BOOL optAnotherBoolVar = %d\n"), program_args_ptr->optAnotherBoolVar);
    return 0;
}

/* Function: displayUsage */
void displayUsage()
{
    _tprintf(_T("\n"));
    _tprintf(_T("Program ParseExample\n"));
    _tprintf(_T("Copyright (c) 2013, William H.\n\n"));
    _tprintf(_T("This program demonstrates the use of the get_arguments function.\n\n"));
    _tprintf(_T("Usage:\n\n"));
    _tprintf(_T("    ParseExample <stringVar> <intVar> <floatVar> <doubleVar> [-s optstringVar] [-i optIntVar] [-f optFloatVar] [-d optDoubleVar] [-b, --build] [--another]\n\n"));
    _tprintf(_T("Positional arguments:\n\n"));
    _tprintf(_T("stringVar       String argument\n"));
    _tprintf(_T("intVar       Integer argument\n"));
    _tprintf(_T("floatVar       Floating point argument\n"));
    _tprintf(_T("doubleVar       Double precision floating point argument\n"));
    _tprintf(_T("\nOptional arguments:\n\n"));
    _tprintf(_T("-s optstringVar        String parameter optstringVar\n"));
    _tprintf(_T("-i optIntVar        Integer parameter optIntVar\n"));
    _tprintf(_T("-f optFloatVar        Floating point parameter optFloatVar\n"));
    _tprintf(_T("-d optDoubleVar        Double precision floating point parameter optDoubleVar TODO:\n"));
    _tprintf(_T("-b, --build        If specified, optBoolVar becomes TRUE.\n"));
    _tprintf(_T("--another        If specified, optAnotherBoolVar becomes FALSE.\n"));
    _tprintf(_T("-h, --help      Display program help.\n\n"));
}





历史

2013年10月11日 - 发布了代码的第一个版本。

2013年10月11日 - 更新了文章和代码。

© . All rights reserved.