• 比atoi()函数更健壮的一类包装函数


    今天介绍两个函数用以代替库函数atoi()atol()strtol()函数,原因是它能提供比库函数更好的错误检查机制。

    int getInt(const char *arg, int flags, const char *name);
    
    long getLong(const char *arg, int flags, const char *name);
    • arg指向待转的数字字符串,flags有固定的几个宏值,代表待转换数字字符串的进制情况,name指向待转字符的说明字符串,用于发生错误时添加到错误消息中。
    • flags可以用或的形式指定多个值,它们可以控制函数转换的进制、范围等。

    flags可取以下值:GN_NONNEG、GN_GT_0 、GN_ANY_BASE、 GN_BASE_8、 GN_BASE_16

    • 其头文件命名为get_num.h:
    /*
    FUNC_NAME: get_num.h
    FUNC_DESC: Header file for get_num.c.
    */
    #ifndef GET_NUM_H
    #define GET_NUM_H
    
    #define GN_NONNEG       01      /* Value must be >= 0 */
    #define GN_GT_0         02      /* Value must be > 0 */
    
                                    /* By default, integers are decimal */
    #define GN_ANY_BASE   0100      /* Can use any base - like strtol(3) */
    #define GN_BASE_8     0200      /* Value is expressed in octal */
    #define GN_BASE_16    0400      /* Value is expressed in hexadecimal */
    
    long getLong(const char *arg, int flags, const char *name);
    
    int getInt(const char *arg, int flags, const char *name);
    
    #endif
    • 函数实现为get_num.c:
    /*
    FUNC_NAME: get_num.h
    FUNC_DESC: Functions to process numeric command-line arguments.
    */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <limits.h>
    #include <errno.h>
    #include "get_num.h"
    
    /* Print a diagnostic message that contains a function name ('fname'),
       the value of a command-line argument ('arg'), the name of that
       command-line argument ('name'), and a diagnostic error message ('msg'). */
    
    static void gnFail(const char *fname, const char *msg, const char *arg, const char *name)
    {
        fprintf(stderr, "%s error", fname);
        if (name != NULL)
            fprintf(stderr, " (in %s)", name);
        fprintf(stderr, ": %s
    ", msg);
        if (arg != NULL && *arg != '')
            fprintf(stderr, "        offending text: %s
    ", arg);
    
        exit(EXIT_FAILURE);
    }
    
    /* Convert a numeric command-line argument ('arg') into a long integer,
       returned as the function result. 'flags' is a bit mask of flags controlling
       how the conversion is done and what diagnostic checks are performed on the
       numeric result; see get_num.h for details.
    
       'fname' is the name of our caller, and 'name' is the name associated with
       the command-line argument 'arg'. 'fname' and 'name' are used to print a
       diagnostic message in case an error is detected when processing 'arg'. */
    
    static long getNum(const char *fname, const char *arg, int flags, const char *name)
    {
        long res;
        char *endptr;
        int base;
    
        if (arg == NULL || *arg == '')
            gnFail(fname, "null or empty string", arg, name);
    
        base = (flags & GN_ANY_BASE) ? 0 : (flags & GN_BASE_8) ? 8 :
                            (flags & GN_BASE_16) ? 16 : 10;
    
        errno = 0;
        res = strtol(arg, &endptr, base);
        if (errno != 0)
            gnFail(fname, "strtol() failed", arg, name);
    
        if (*endptr != '')
            gnFail(fname, "nonnumeric characters", arg, name);
    
        if ((flags & GN_NONNEG) && res < 0)
            gnFail(fname, "negative value not allowed", arg, name);
    
        if ((flags & GN_GT_0) && res <= 0)
            gnFail(fname, "value must be > 0", arg, name);
    
        return res;
    }
    
    /* Convert a numeric command-line argument string to a long integer. See the
       comments for getNum() for a description of the arguments to this function. */
    
    long
    getLong(const char *arg, int flags, const char *name)
    {
        return getNum("getLong", arg, flags, name);
    }
    
    /* Convert a numeric command-line argument string to an integer. See the
       comments for getNum() for a description of the arguments to this function. */
    
    int
    getInt(const char *arg, int flags, const char *name)
    {
        long res;
    
        res = getNum("getInt", arg, flags, name);
    
        if (res > INT_MAX || res < INT_MIN)
            gnFail("getInt", "integer out of range", arg, name);
    
        return (int) res;
    }
  • 相关阅读:
    【20220502】连岳摘抄
    【20220423】家是孩子最重要的教育场所
    【20220425】连岳摘抄
    【20220430】连岳摘抄
    【20220427】二宝让我们省吃俭用
    【20220503】连岳摘抄
    工作感受月记202205月
    Appium实现百词斩
    Appium自动微信读书打卡
    删除ssh 连接缓存
  • 原文地址:https://www.cnblogs.com/leon1124/p/14039678.html
Copyright © 2020-2023  润新知