【问题标题】:How can I return Error sign in C function?如何在 C 函数中返回错误符号?
【发布时间】:2020-07-05 10:10:57
【问题描述】:

我学习 C 中的数据结构,并使用 C 中的结构学习多项式的一部分。

我正在实现一个函数Coef(polynomial, exponent)。这是一个函数,返回参数exponent对应的系数。

这是我的代码:

typedef struct polynomial{
    int degree;
    float coef[MAX_DEGREE];
}Polynomial;

typedef int coefficient;
typedef int Exponent;

coefficient Coef(Polynomial* poly,int expon){
    if(poly->coef[MAX_DEGREE - expon]){ // because array stored coefficient in descending order of exponent
        return poly->coef[expon];
    }
    else{
        return Error
    }
}

else 语句中,如果多项式没有指数与参数指数匹配的项,我想返回一个错误。

但是函数的返回类型是coefficient(即int),它可以是任意数字。

如何返回错误?

【问题讨论】:

  • I want to return Error sign 什么是“错误标志”?你想“通知你的函数的调用者发生了错误”? the long question不用担心,很短。
  • 这能回答你的问题吗? Error handling in C code
  • 我理解您想问的问题,但这可以通过一个更简单、更集中的示例来更好地解释。您的 costum 函数和您的解释性“错误”返回值没有必要说明,这里是混乱的根源。

标签: c error-handling


【解决方案1】:

您可以使用enumsEnumeration 并编写一个返回此枚举的函数。 Enumeration 是 C 语言中用户定义的数据类型。它用于为整数常量分配名称,使程序易于阅读和维护。关键字“enum”用于声明枚举。

标准情况下需要返回的值(无错误)通过指针取消引用p_ret返回,调用者需要将其传递给foo函数。

typedef enum{
  E_ERROR = 0,
  E_INVALID_ENTRY,
  E_SUCCESS
  /*
  ADD error codes as neccessary
 */

}E_RET;


E_RET foo(Polynomial* poly,int expon, float* p_ret)
{
    if(poly->coef[MAX_DEGREE - expon] )
    { 
     /********************************
     because array stored coefficient
     in descending order of exponent
     *********************************/
        *p_ret = poly->coef[expon];
        return E_SUCCESS;
    }
    else
    {
        return E_ERROR;
    }
}

调用者

这里说明你应该如何调用函数:

Polynomial poly;
float ret;

E_RET return_stat = foo(&poly, 1, &ret)
/* check for return status */
if(return_stat != E_SUCCESS)
{
    /*something wrong! envoke error handling*/
    abort();
}

【讨论】:

  • @KamilCuk - 我的回答是建议使用enum c 功能。我没有修复他的功能逻辑。这不是他要求的。
  • @wovano 当然可以,但在编辑之前 ;) 我想我只是删除了我的 cmets,因为它们不再相关
【解决方案2】:

欢迎来到错误处理的世界。所以基本上你想要返回一个 optional 值 - 如果值有效并且你想要返回值,或者该值无效并且想要返回错误条件。

可以将其包装在一个结构中,但不要:

struct coef_or_err {
  int err;
  coefficient coef;
};
struct coef_or_err function() {
    if (poly->coef[MAX_DEGREE - expon]){
       return (struct coef_or_err){ .err = 0, .coef = poly->coef[expon] };
    } else {
       return (struct coef_or_err){ .err = 1 };
    }
}

但是对于所有可能的情况,很多类型和不同的结构,容易维护这样的代码是不能忍受的。所以在 C 中通过指针传递附加参数是很典型的。要么传递一个指向 int 的指针,这将是一个非零错误代码,或者最喜欢在成功时返回一个 int0 并通过指针获取所有其他参数:

int Coef(Polynomial* poly, int expon, coefficient *coef) {
    if (!poly->coef[MAX_DEGREE - expon]) {
       return -1; // or some error code, maybe ENOENT from errno.h
    }
    *coef = poly->coef[expon];
    return 0;
}
// example user call
int main() {
   coefficient coef;
   if (!Coef(some_poly, 15, &coef)) {
      // handle error
      abort();
   }
   // use coef
}

在许多地方都可以找到此类错误处理的示例。另一种类型的错误处理是使用全局变量,要么存储在对象中,要么......全局,但请不要(errnowhy global variables are bad):

coefficient Coef(Polynomial* poly, int expon) {
    if (!poly->coef[MAX_DEGREE - expon]) {
       poly->err = 1;
       return 0;
    }
    return poly->coef[expon];
}
int Coef_is_err(Polynomial* poly){
   return poly->err;
}
void Coef_clear_err(Polynomial* poly){
   poly->err = 0;
}
int main() {
   coefficient coef = Coef(some_poly, 15);
   if (Coef_is_err(some_poly)) abort();
   // use coef
}

最突出的例子是来自标准库的ferror(FILE*)。这样的代码在 I/O 操作的情况下更有用,例如aio_error() from posix

还有一种方法是使用越界值来传递错误,通常在类型可以表示更多值然后对含义有效时使用。例如,返回某事计数的函数必须返回正数或零 - 负数将是错误。

【讨论】:

  • 为什么你不只使用enum?为什么我们需要为错误代码声明一个结构?
  • 字面意思是You can wrap it in a structure, but don't:,然后我解释为什么这样的代码在实际代码库中不可行。有时仍然使用可选值的这种实现。 why we need to declare astructure for error code? 在返回语句中将值与附加信息一起返回。
【解决方案3】:
  1. 您可以将结果存储在一个单独的值中,通过指针传递
  2. 您可以在成功的情况下返回一个指向结果的指针,在失败的情况下返回一个 NULL 指针,因为用于存储结果的值是在函数范围之外声明的
  3. 使用全局变量存储错误代码,在函数调用后检查。还建议通过“g_”前缀强调所讨论的变量是全局的。 警告:仅在没有两个线程可以运行的环境中可行 在使用的函数之后访问有问题的全局变量 全局变量已被调用,但尚未执行对全局变量的检查。

【讨论】:

  • 或者只是将返回的coefficient 设为指针并返回NULLreturn &poly->coef[expon];
  • 在 c 中使用全局变量是危险的,并试图阻止它们。全局变量被用作最后的选择。这种情况可以轻松处理,无需使用全局变量。
  • @Adam 使用全局变量通常是危险的,并且可能导致一些不需要的行为,因为所有可能的错误检查只能在链接时完成,但是,如果您使用一个全局值来存储最后执行的函数错误代码,并强调这确实是一个带有“g_”前缀的全局值,那么我认为这几乎没有伤害
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-25
  • 1970-01-01
  • 2015-12-28
  • 1970-01-01
  • 1970-01-01
  • 2014-07-13
相关资源
最近更新 更多