![](/img/trans.png)
[英]Is it good programming practice to use setjmp and longjmp in C?
[英]C programming good practice or not ?
我已经写了一小段代码来计算二次方程式,但是如果判别式为负,我希望它写出该二次方程式没有实际数值。 为了实现这一点,我必须调用第四个参数为0的函数,我认为我不知道为什么,这将是不好的编程习惯? 是这种情况还是我只是过于挑剔我的代码? 谢谢。 (我之所以这样问,是因为我不想在编程的“职业生涯”初期就养成不良习惯)。 这是代码。
#include <stdio.h>
#include <math.h>
#include <string.h>
double quadratic_equation(double a, double b, double c, double d);
int main(void)
{
char command[20];
int i;
printf("Enter your command: ");
fgets(command, 20, stdin);
for (i = 0; i < 20; i++) {
if (command[i] == '\n') {
command[i] = '\0';
break;
}
}
if (strcmp(command, "quadratic equation") == 0) {
double a, b, c, x;
printf("Enter A: ");
scanf("%lf", &a);
printf("Enter B: ");
scanf("%lf", &b);
printf("Enter C: ");
scanf("%lf", &c);
x = quadratic_equation(a, b, c, 0); // THIS PIECE HERE MIGHT BE BAD PRACITCE ?
if (x == 0) {
printf("There are no real numerical values to this quadratic equation.");
}
else {
printf("------------\n");
printf("x1 = %.2f\n", quadratic_equation(a, b, c, 1));
printf("x2 = %.2f", quadratic_equation(a, b, c, -1));
}
}
return 0;
}
double quadratic_equation(double a, double b, double c, double d) {
double discriminant, x, insideroot;
insideroot = ((b*b) - (4*a*c));
if (insideroot < 0) {
return 0;
}
discriminant = sqrt(insideroot);
x = (-b + (d * discriminant)) / (2 * a);
return x;
}
非常感谢您的帮助:d!
这当然是不好的做法。 由于公式a
, b
和c
的根是任意double
您确实需要某种传递。
我建议使用一个指向int的指针的参数。 如果指针为NULL
则将其忽略,否则将根据实际根是否存在将其设置为1或0:
double quadratic_equation(double a, double b, double c, int *root_exists) {
double discriminant;
discriminant = ((b*b) - (4*a*c));
if (discriminant < 0) {
if (root_exists != NULL) *root_exists = 0;
return 0.0;
}
x = (-b + sqrt(discriminant)) / (2 * a);
if (root_exists != NULL) *root_exists = 1;
return x;
}
一个更严格的方法是这样的:
typedef struct {
int num_roots;
double roots[2];
} quadratic_roots_t;
quadratic_roots_t quadratic_equation(double a, double b, double c) {
quadratic_roots_t roots;
double d;
d = b*b - 4*a*c;
if (d < 0.0) {
roots.num_roots = 0;
} else if (d == 0.0) {
roots.num_roots = 1;
roots.roots[0] = -b / (2 * a);
} else {
roots.num_roots = 2;
roots.roots[0] = (-b - sqrt(d)) / (2 * a);
roots.roots[1] = (-b + sqrt(d)) / (2 * a);
}
return roots;
}
我会说这不是一件好事。 您可以做的是这样的:
int quadratic_equation(double a, double b, double c, double *root_a, double *root_b) {
double discriminant = ((b*b) - (4*a*c));
if (discriminant < 0) {
return -1;
}
if (root_a != NULL) {
*root_a = (-b + sqrt(discriminant)) / (2 * a);
}
if (root_b != NULL) {
*root_b = (-b - sqrt(discriminant)) / (2 * a);
}
return 0;
}
然后您可以这样称呼:
double root_a;
double root_b;
int ok = quadratic_equation(a, b, c, &root_a, &root_b);
if (ok < 0) {
// It wasn't OK. Print out an error.
} else {
// It was OK. Print out the results.
}
请注意,您还应该检查函数中的其他错误情况,并为其返回-1。 例如a
为零。
考虑使用返回值指示是否一切正常,并将数组传递给函数以接收返回值:
enum QE_Status { QE_OK = 0, QE_NON_QUADRATIC, QE_COMPLEX_ROOTS, QE_NULL_POINTER };
enum QE_Status quadratic_equation(double a, double b, double c, double *r)
{
double discriminant;
if (r == 0)
return QE_NULL_POINTER;
if (a == 0.0)
return QE_NON_QUADRATIC;
discriminant = (b * b) - (4 * a * c);
if (discriminant < 0)
return QE_COMPLEX_ROOTS;
discriminant = sqrt(discriminant);
r[0] = (-b + discriminant) / (2 * a);
r[1] = (-b - discriminant) / (2 * a);
return QE_OK;
}
您可以扩展系统以处理数值不稳定性(因为b*b
几乎等于4*a*c
,或者因为a
很小,等等)。
调用代码可以是:
double a, b, c, x[2];
if (quadratic_equation(a, b, c, x))
...oops, something went wrong...
要么:
switch (quadratic_equation(a, b, c, x))
{
case QE_OK:
...print or use results in x...
break;
case QE_NON_QUADRATIC:
case QE_COMPLEX_ROOTS:
...print appropriate error message about user's data...
break;
case QE_NULL_POINTER:
...Oops - programming error...
break;
}
我肯定会称其为不好的做法,因为代码非常不清楚。
首先,您将调用该函数三次,一次应足够。
我会考虑在您的quadratic_equation()
函数中返回/填充列表,而不是一一返回根。
这也可以让您确定是否存在真正的根-如果没有,仅返回一个空列表。
总体而言,这将比您当前的解决方案优雅得多,并且无需事先检查是否有任何解决方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.