В вашей программе несколько проблем:
- вам следует стараться не изменять строку аргумента:
strtok()
изменяет строку, на которую указывает ее первый аргумент, что является неприятным побочным эффектом и в вашем case теряет важную информацию, такую как знак следующей константы. - вы не обрабатываете
/
array
имеет только 2 записи, вызывая неопределенное поведение для большинства уравнений, которые имеют больше терминов .
Вот модифицированная версия, которая использует strtod()
и ручной анализ:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int funk(const char *exp, double *x1, double *x2) {
double coef[3] = { 0, 0, 0 };
double d, e, a, b, c, sign, part;
int n;
const char *p = exp;
char *q;
part = 1;
for (;;) {
p += strspn(p, " \t\r\n"); // skip whitespace
if (!*p)
break;
if (*p == '=') {
p++;
if (part < 0)
return -1;
part = -1;
continue;
}
d = 1;
sign = part;
if (*p == '+') {
p++;
} else
if (*p == '-') {
sign = -1;
p++;
}
if (*p != 'x') {
d = strtod(p, &q);
if (p == q)
return -1;
p = q;
}
d *= sign;
n = 0;
if (*p == '/') {
p++;
e = strtod(p, &q);
if (p == q)
return -1;
p = q;
d /= e;
}
if (*p == 'x') {
p++;
n = 1;
if (*p == '^') {
p++;
n = strtol(p, &q, 10);
if (p == q)
return -1;
p = q;
if (n < 0 || n > 2)
return -1;
}
}
if (*p == '/') {
p++;
e = strtod(p, &q);
if (p == q)
return -1;
p = q;
d /= e;
}
coef[n] += d;
}
a = coef[2];
b = coef[1];
c = coef[0];
d = b * b - 4 * a * c;
if (a > 0 || a < 0) {
/* quadratic equation */
if (d < 0) {
return -2;
} else
if (d > 0) {
*x1 = (-b + sqrt(d)) / (2 * a);
*x2 = (-b - sqrt(d)) / (2 * a);
return 2;
} else {
*x1 = -b / (2 * a);
return 1;
}
}
if (b < 0 || b > 0) {
/* first order equation */
*x1 = 0 + -c / b;
return 1;
}
/* constant equation */
if (c > 0 || c < 0) {
return 0;
} else {
return 3;
}
}
void solve(const char *exp) {
double x1, x2;
switch (funk(exp, &x1, &x2)) {
case 0:
printf("%s -> no solution\n", exp);
break;
case 1:
printf("%s -> single root x=%g\n", exp, x1);
break;
case 2:
printf("%s -> two roots x1=%g, x2=%g\n", exp, x1, x2);
break;
case -2:
printf("%s -> two imaginary roots\n", exp);
break;
case 3:
printf("%s -> true for all x\n", exp);
break;
default:
printf("not a quadratic equation: %s\n", exp);
break;
}
}
int main(int argc, char *argv[]) {
if (argc > 1) {
for (int i = 1; i < argc; i++)
solve(argv[i]);
} else {
solve("2x^2+x/5+2=0");
solve("x^2+2x+1=0");
solve("x^2=49");
solve("x=49");
solve("x=0");
solve("2=2");
solve("1=0");
}
return 0;
}