[英]Why is my function not returning null pointer?
I have a problem with visual code, everything works fine on the online compiler, but while trying it on stm32 nucleo it doesn't return NULL
, where is the problem?我的可视化代码有问题,在线编译器上一切正常,但是在 stm32 核上尝试时,它不返回NULL
,问题出在哪里? It cannot break the while
loop.它不能打破while
循环。
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
int funk(char *skai) {
char delim[] = "+-=";
int i = 0;
float x, d = 0;
char *array[2];
char *ptr = strtok(skai, delim);
while (ptr != NULL) {
array[i++] = ptr;
ptr = strtok(NULL, delim); // <---- doesnt return null, endless loop
}
int a = atoi(array[0]);
float b = atof(array[1]);
int c = atoi(array[2]);
if (c != 0) {
d = b * b - 4 * a * c;
if (d > 0) {
float root1 = (-b + sqrt(d)) / (2 * a);
float root2 = (-b - sqrt(d)) / (2 * a);
if (root1 > root2) {
x = root1;
} else {
x = root2;
}
} else {
x = -b / (2 * a);
}
} else {
x = b / a;
} //printf("%0.3f\n", x);
return x;
}
int main(void) {
char rxd[20] = "2x^2+x/5+2=0";
funk(rxd);
}
Given skai
pointing to an array of char
containing “2x+2=0”, a sequence of calls to strtok
with delimiters “+-=” is expected to return first a pointer to (the first character of) “2x”, then “2”, then “0”, then a null pointer.给定skai
指向包含“2x+2=0”的char
数组,使用分隔符“+-=”对strtok
的调用序列预计首先返回指向“2x”(第一个字符)的指针,然后“ 2”,然后是“0”,然后是空指针。 The code as written attempts to store these values in array[0]
, array[1]
, and array[2]
.编写的代码尝试将这些值存储在array[0]
、 array[1]
和array[2]
。 However, array
has no element 2 since it was defined with only two elements.但是, array
没有元素 2,因为它只定义了两个元素。 So the program overflows the array, and the resulting behavior of the program is not defined by the C standard.所以程序溢出了数组,程序的结果行为并没有被 C 标准定义。 It may be the program is then overwriting memory in such a way as to cause strtok
to misbehave.可能是程序然后以导致strtok
行为不端的方式覆盖内存。
Change the definition of array
to be larger, and, inside the loop calling strtok
, monitor the value of i
: If it reaches the limit of the array size, print an error message and terminate the function (or the entire program).将array
的定义更改为更大,并在调用strtok
的循环内监视i
的值:如果达到数组大小的限制,则打印错误消息并终止函数(或整个程序)。
Your program has multiple problems:您的程序有多个问题:
strtok()
modifies the string pointed to by its first argument, which is a nasty side effect and in your case loses important information such as the sign of the next constant.您应该尽量不要修改参数字符串: strtok()
修改其第一个参数指向的字符串,这是一个令人讨厌的副作用,并且在您的情况下会丢失重要信息,例如下一个常量的符号。/
你不处理/
array
has just 2 entries, causing undefined behavior for most equations that have more terms. array
只有 2 个条目,导致大多数具有更多项的方程的未定义行为。 Here is a modified version that uses strtod()
and manual parsing:这是使用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;
}
Array too small - by two.阵列太小 - 两个。 *1 *1
I made array[]
much larger and added printf("%d '%s'\\n", i, ptr)
我使array[]
大得多并添加了printf("%d '%s'\\n", i, ptr)
char *array[20];
char *ptr = strtok(skai, delim);
while (ptr != NULL) {
printf("%d '%s'\n", i, ptr);
array[i++] = ptr;
ptr = strtok(NULL, delim); // <---- doesnt return null, endless loop
}
The output was输出是
0 '2x^2'
1 'x/5'
2 '2'
3 '0'
So apparently array[]
needed to be at least array[4]
.所以显然array[]
至少需要是array[4]
。
Recommend to add protection when parsing or use a different approach.建议在解析时添加保护或使用不同的方法。
if (i+1 >= sizeof array/sizeof array[0]) {
// Handle/report error somehow
}
array[i++] = ptr;
Aside: If using float
variables, might as well use float
functions.旁白:如果使用float
变量,不妨使用float
函数。
// float root1 = (-b + sqrt(d)) / (2 * a);
// ---------------------v
float root1 = (-b + sqrtf(d)) / (2 * a);
*1 *1
Post had changed from "2x+2=0"
to "2x^2+x/5+2=0"
帖子已从"2x+2=0"
更改为"2x^2+x/5+2=0"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.