繁体   English   中英

为什么我的函数不返回空指针?

[英]Why is my function not returning null pointer?

我的可视化代码有问题,在线编译器上一切正常,但是在 stm32 核上尝试时,它不返回NULL ,问题出在哪里? 它不能打破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);
}

给定skai指向包含“2x+2=0”的char数组,使用分隔符“+-=”对strtok的调用序列预计首先返回指向“2x”(第一个字符)的指针,然后“ 2”,然后是“0”,然后是空指针。 编写的代码尝试将这些值存储在array[0]array[1]array[2] 但是, array没有元素 2,因为它只定义了两个元素。 所以程序溢出了数组,程序的结果行为并没有被 C 标准定义。 可能是程序然后以导致strtok行为不端的方式覆盖内存。

array的定义更改为更大,并在调用strtok的循环内监视i的值:如果达到数组大小的限制,则打印错误消息并终止函数(或整个程序)。

您的程序有多个问题:

  • 您应该尽量不要修改参数字符串: strtok()修改其第一个参数指向的字符串,这是一个令人讨厌的副作用,并且在您的情况下会丢失重要信息,例如下一个常量的符号。
  • 你不处理/
  • 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;
}

阵列太小 - 两个。 *1

我使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
}

输出是

0 '2x^2'
1 'x/5'
2 '2'
3 '0'

所以显然array[]至少需要是array[4]

建议在解析时添加保护或使用不同的方法。

if (i+1 >= sizeof array/sizeof array[0]) {
  // Handle/report error somehow
}
array[i++] = ptr;

旁白:如果使用float变量,不妨使用float函数。

// float root1 = (-b + sqrt(d)) / (2 * a);
// ---------------------v
float root1 = (-b + sqrtf(d)) / (2 * a);

*1

帖子已从"2x+2=0"更改为"2x^2+x/5+2=0"

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM