簡體   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