【问题标题】:How to make a variable to return N/A? (c language) [duplicate]如何使变量返回 N/A? (c语言)[重复]
【发布时间】:2013-11-14 09:45:44
【问题描述】:

我有一个 c 语言代码,我有一个返回 int 值的函数。但是,如果条件不完整,我需要该函数中的一个变量来给我值 N/A(不是它在开始时初始化的大数字)。任何提示如何做到这一点?非常感谢...

【问题讨论】:

  • N/A 的值应该是多少? AFAIK int 只能是数值
  • 如果输入超过一定值返回null?
  • 您可以使用带符号的 -1 表示 unsigned int,NaN 表示浮点数,NULL 表示指针。
  • @DCoder 在这种情况下我更喜欢相反的情况(即让状态为返回值)。
  • 另一种选择可能是拥有struct retval { int value; char success; },然后定义struct retval function(void)。

标签: c


【解决方案1】:

C 中没有 N/A。最接近它的是值指针。您可以有一个函数返回一个指向 int 的指针,并在条件未满足的情况下返回 NULL。

基本上有两种可能,返回一个指向静态存储的指针,或者一个指向使用 malloc 分配的存储的指针。

int *may_fail_static(int input) {
    static int result;
    if (input == 42)
         return NULL;
    else {
        result = 3 * input;
        return &result;
    }        
}

int *may_fail_malloc(int input) {
    int *result;
    if (input == 42)
        return NULL;
    else {
        result = malloc(sizeof *result);
        if (result == NULL) {
            fprintf(stderr, "Out of memory!\n");
            exit(1);
        }
        *result = 3 * input;
        return result;
    }
}

两者都有缺点:静态版本不可重入(不是线程安全的)。 malloc 版本具有很大的分配开销,客户端必须在使用后显式释放存储空间。

这就是为什么在 C 语言中,您通常会找到此类函数:

/* Returns 0 on success, or -1 on failure */
int may_fail(int input, int *result) {
    if (input == 42)
        return -1;
    else {
        *result = 3 * input;
        return 0;
    }
}

客户可以通过以下方式使用它:

int x;
if (may_fail(42, &x) == -1) {
    fprintf(stderr, "ERROR: may_fail failed!\n");
    exit(1);
}
/* Answer value is now stored in x. Go ahead */

【讨论】:

    【解决方案2】:

    有几种方法

    1。使用代理值 AKA sentinel value

    在这种情况下,最简单的方法是您可以为 N/A 保留值,这作为正常返回值无效。常见的例子是许多库函数,它们返回读/写/某事的字节数,或 -1 表示错误。如果你有一个已知范围的有效值,那么在这个范围之外定义一些合适的值来表示 N/A。

    #include <limits.h>
    // define NA_VALUE to be smallest possible int
    #define NA_VALUE (INT_MIN)
    
    int getInt1(const char *key) {
        if (test_if_key_exits(key)) {
            return get_int_for_key(key);
        }
        else {
            return NA_VALUE;
        }
    }
    
    void testfunc1(const char *key) {
        int value = getInt1(key);
        if (value != NA_VALUE) std::cout << value;
        else std::cout << "n/a";
    }
    

    2。除返回值外,使用out参数

    一个更通用的替代方法是返回布尔值(或者可能是数字错误代码,甚至 const char* 到错误字符串或 NULL 表示成功),然后使用指针参数作为实际返回值,如下所示:

    bool getInt2(const char *key, int *result) {
        if (test_if_key_exits(key)) {
            // in case result is NULL, do not use it, just return true
            if (result) *result = get_int_for_key(key);
            return true;
        }
        else {
            return false;
        }
    }
    
    void testfunc2(const char *key) {
        int value;
        if (getInt2(key, &value))std::cout << value;
        else std::cout << "n/a";
    }
    

    您也可以将其反转,将 int 作为返回值返回,并将 out 参数用于状态。如果您希望始终返回某个值,甚至是默认值(如果没有别的),并允许 out 参数指示它是默认值,这可能会很有用。

    3。返回指向值的指针,或NULL

    第三种方法是返回一个指向值的指针,或者NULL 表示不适用,但是你问的是int 返回值,所以这可能不实用,有一些缺点。在您可以返回指向某些现有数据的指针的情况下,它最有用。 the answer of @JoSo 中解释了这种替代方法和缺点。

    【讨论】:

    • +1:代理值(也称为哨兵值)是我自己帖子的一个很好的补充。
    • @JoSo 谢谢,我想那是我想要的词,添加到答案中。
    【解决方案3】:

    我见过在 C 库中使用的四种方式:

    /*
     * return a defined unexpected value, like -1,
     * otherwise the return the result
     *
     * return -1 if failed, otherwise on success
     */
    int my_function(void) {
      return -1;
    }
    

    /*
     * the result is stored in `ret`, and the state
     * is returned
     *
     * return -1 if failed, otherwise on success
     */
    int my_function(int *ret) {
      return -1;
    }
    

    /*
     * the state is stored in an argument
     *
     * state = -1 if failed, otherwise on success
     */
    int my_function(int *state) {
      *state = -1;
      return 0;
    }
    

    /*
     * with pointers and addresses
     *
     * return NULL on failed, otherwise on success
     */
    int *my_function(void) {
      return NULL;
    }
    

    【讨论】:

      【解决方案4】:

      我同意乔的看法。您可以做的另一件事——将 errno(3) 设置为函数中的某个有意义的值,然后在外部检查它的值。

      【讨论】:

      • 我不确定篡改 errno 是否是个好主意 - 这应该保留给运行时库。
      • 这是解决方案。是的,这是一个糟糕的解决方案。可能按照其他人的建议更改设计会更好。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-12
      • 1970-01-01
      • 2021-12-11
      • 2011-05-10
      • 2018-05-23
      • 1970-01-01
      • 2015-12-27
      相关资源
      最近更新 更多