让我们说例如我们有一个函数做一些数学运算(为了参数,乘以两个数字)。它返回结果但如果有错误,则函数返回-1。
但是,-1实际上可以是有效结果(例如-1 * 1)。什么是更好的回报?我想在错误时返回INT_MAX,但是我的一些数学函数返回double并浮动,所以我想看看是否有更好的选择。
这是一个库,所以我想对错误使用相同的常量来减少混淆。
答案 0 :(得分:2)
通常的解决方案是仅使用返回值来表示成功或错误,并通过指针返回实际结果:
int multiply(int a, int b, int *result_out)
{
if (/* success... */) {
*result_out = a * b;
return 0;
} else {
return -1;
}
}
答案 1 :(得分:1)
NaN =不是数字。
您可能需要阅读此内容:How to use nan and inf in C?
https://en.wikipedia.org/wiki/NaN
并非所有函数都返回浮点值,因此无法始终使用NaN。
由于某些数学函数可以返回任意数量的类型,因此您无法真正使用返回值来指示发生了错误。
您仍然可以取消设置并设置errno
。它确实会产生副作用,即errno
的旧值将被覆盖。
在example.h中:
#include <errno.h>
/* extern int errno; */
double division(double n, double d);
在example.c中:
#include "example.h"
double division(double n, double d)
{
if (0 == d)
{
errno = EDOM;
return 0.0; /* Does not matter. */
}
else
return n/d;
}
在main.c中:
#include <stdio.h>
#include "example.h"
int main(int argc, char *argv[])
{
division(1.0, 0.0);
if (EDOM == errno)
{
fprintf(stderr, "Couldn't divide 1.0 by 0.0\n");
errno = 0; /* Reset so it won't appear that the error has
occurred even when it hasn't. */
}
division(3.14, 2.78);
if (EDOM == errno)
{
fprintf(stderr, "Couldn't divide 3.14 by 2.78.\n");
errno = 0;
}
return 0;
}
或者您可以使用自己的全局变量,如果没有发生错误,则不会取消设置。
这将允许您对这些函数进行一大堆调用,并且只检查一次错误。
在example.h中:
int error_flag = 0; /* Set to non-zero value on error. */
double division(double n, double d);
在example.c中:
#include "example.h"
double division(double n, double d)
{
if (0 == d)
{
error_flag = 1;
return 0.0;
} else
return n/d;
}
在main.c中:
#include <stdio.h>
#include "example.h"
int main(int argc, char *argv[])
{
double x;
error_flag = 0; /* External variable */
x = division(division(3.14, 1.3 - division(3.9, -3.0)), 7);
if (error_flag)
{
/* The last call to division() didn't unset error_flag. */
fprintf(stderr, "Something went wrong.\n");
return 1;
}
/* Not reached. */
printf("%f\n", x);
return 0;
}
有时。
<德尔> 或者不做任何事来处理数学错误。 如果你试图打开一个文件,很难预测结果,因为只知道文件名是不够的;你必须检查文件是否存在,如果它确实存在,你将不得不检查权限。 数学(我知道)并不困难,你只需要知道论点。考虑`f(x)= 1 / x`:你只需要知道`x`的值来确定对`f`的调用是否会失败,众所周知这个众所周知的函数是为` x!= 0` 一个班轮:`双师(双n,双d){return n / d;}` 德尔>(事实证明我错了。例如:f(a, b) = 1/(a+b)
)
答案 2 :(得分:0)
如果您正在寻找偶然发生的最不可能的整数常量,请使用INT_MIN
。它的幅度大于INT_MAX
。它还具有可复制到float
而不会丢失其值的优势,INT_MAX
将四舍五入到不同的值。
当然,只有当你需要与C兼容时才会这样。在C ++中,你真的应该使用异常。
答案 3 :(得分:-1)
标准库使用了一个名为errno
的变量来明确地实现此目的。你可以实现类似的东西。
例如,在源文件中:
int matherr;
enum {
SUCCESS,
ZERO_DIVIDE,
TOO_LARGE,
...
};
int multiply(int a, int b)
{
matherr = SUCCESS;
if (/* result too large*/) {
matherr = TOO_LARGE;
return 0;
} else {
return a*b;
}
}
int divide(int a, int b)
{
matherr = SUCCESS;
if (/* result too large*/) {
matherr = ZERO_DIVIDE;
return 0;
} else {
return a/b;
}
}
在您的标头文件中:
extern int matherr;
int multiply(int a, int b);
int divide(int a, int b);
在调用这些函数的代码中,如果任一函数返回0,则需要检查matherr
的值。
答案 4 :(得分:-2)
没有任何值适合int,float和double,并且转移函数值并不是一个好主意。
但不检查错误条件甚至故意造成错误?我的意思是,如果产品溢出,让它溢出;或者如果函数的参数超出范围,甚至无法启动计算,则调用sqrt(-1)来模拟超出范围的错误。
为什么?
因为你的函数将采用与普通表达式相同的行为,并且不会更好/不会更糟。与此同时,您不必创建新机制,用户不必学习它们,您将保持高度可移植性并符合编程语言。