0

I've been trying to code a program that solves quadratic equations. Everything seemed fine to me, but the functions I try to go again didn't start after I'd called them. I can't understand what I made wrong.

#include <stdio.h>
#include <math.h>

int main(){
    float a, b, c, delta, x1, x2;
    char YN;
    void enter(){
        printf("Insert the value of 'a':\n");
        scanf("%f", &a);
        printf("Insert the value of 'b':\n");
        scanf("%f", &b);
        printf("Insert the value of 'c':\n");
        scanf("%f", &c);
        delta = (b*b) - (4 * a * c);
        x1 = (-b-sqrt(delta))/(2*a);
        x2 = (-b+sqrt(delta))/(2*a);
    }

    void solve(){
        if (delta > 0){
            printf("The first root of the equation is %f.", x1);
            printf("The second root of the equation is %f.", x2);
        }
        else if (x1 == x2){
            printf("The only root of the equation is %f.", x1);
        }
        else{
            printf("The equation has no real roots.");
        }
    }

    void input(){
        scanf("%c", &YN);
    }

    void check(){
        if (YN == 'Y'){
            solve();
        }
        else if (YN == 'N'){
            enter();
        }
        else {
            input();
        }
    }

    enter();
    printf("Your equation must be: %f x^2 + %f x + %f, is it correct? Type Y for yes, N for no.\n", a, b, c);
    input();
    check();
    return 0;
}

Because I thought the variables make the function not work, I tried having variables outside the solve function, but it didn't really work.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • 6
    in c - you can not have functions declared inside other functions – Daniel A. White Apr 07 '23 at 16:43
  • AFAIK some compilers allow it but is non-standard. – Weather Vane Apr 07 '23 at 16:54
  • Aside: add a space in `scanf("%c", &YN);` to make it `scanf(" %c", &YN);` and see [`scanf()` leaves the newline char in the buffer](https://stackoverflow.com/questions/5240789/scanf-leaves-the-new-line-char-in-the-buffer). – Weather Vane Apr 07 '23 at 16:56
  • You do not pass any parameters and your variable are local to the main function. You need to use parameters and better choose the purpose of functions. – 0___________ Apr 07 '23 at 16:57
  • @0___________ Since the functions are nested, they should be able to access the `main()` variables (assuming he's using a compiler that has the nested function extension -- otherwise it wouldn't even compile). – Barmar Apr 07 '23 at 16:59
  • @Barmar I am writing about C not gcc. There is no tag gcc – 0___________ Apr 07 '23 at 17:03
  • @0___________ Someone else already commented that nested functions aren't standard C. If the code is running, they're obviously using a dialect that allows it, and in that context the parameters are not needed. Of course, if you move the functions outside, they'll need to be recoded. – Barmar Apr 07 '23 at 17:08
  • @DanielA.White: You can have functions declared inside other functions in C. The C standard does not require it, but it does allow it. GCC supports them. (Also, the C standard is not binding on what C is; it is a voluntary specification.) – Eric Postpischil Apr 07 '23 at 17:28

3 Answers3

1

In standard C, you cannot define functions inside other functions. Instead, you must declare/define your functions separately outside of main().

Additionally, you can have global variables that can be accessed "globally" by all of your functions. They are not scoped to a specific function. To do this, declare them outside of your main function.

There are a few issues with this:

  1. It is not recommended to have all of your variables global. Instead of referencing global variables, learn how to use function parameters and pass by reference. You could clean this up by having your functions return values as well.
  2. In my opinion the functions you have here don't need to be in their own functions. They could be all included in your main function.

Here is an example of your code with the correct formatting:

#include <stdio.h>
#include <math.h>

// Function Declarations here
void enter();
void solve();
void input();
void check();

// Global Variables
float a, b, c, delta, x1, x2;
char YN;

int main(){
    enter();
    solve();
    input();
    check();

    enter();
    printf("Your equation must be: %f x^2 + %f x + %f, is it correct? Type Y 
       for yes, N for no.\n", a, b, c);
    input();
    check();
    return 0;
}

// Function Definitions here

void enter(){
        printf("Insert the value of 'a':\n");
        scanf("%f", &a);
        printf("Insert the value of 'b':\n");
        scanf("%f", &b);
        printf("Insert the value of 'c':\n");
        scanf("%f", &c);
        delta = (b*b) - (4 * a * c);
        x1 = (-b-sqrt(delta))/(2*a);
        x2 = (-b+sqrt(delta))/(2*a);
}

void solve(){
    if (delta > 0){
       printf("The first root of the equation is %f.", x1);
       printf("The second root of the equation is %f.", x2);
    }
    else if (x1 == x2){
       printf("The only root of the equation is %f.", x1);
    }
    else{
       printf("The equation has no real roots.");
    }
}

void input(){
    scanf("%c", &YN);
}

void check(){
    if (YN == 'Y'){
       solve();
    }
    else if (YN == 'N'){
       enter();
    }
    else {
       input();
    }
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Matthew G
  • 66
  • 5
  • 1
    *"Instead, you must have a function declaration before your main() and your function definition after main()."* ===> Not necessarily. You can have both before `main()`. – Harith Apr 07 '23 at 17:17
  • @Haris This is true, I should be more specific that is has to be outside of main(). This is just how I personally structure my C files. I will update my description. – Matthew G Apr 07 '23 at 17:19
  • 2
    “In C, you cannot declare functions inside other functions” is not a correct statement. The C standard does not specify that a C implementation must allow this, but it allows C implementations to support this. The C standard invites extensions. GCC supports it. And the C standard is not binding on what C is; it is a voluntary specification. – Eric Postpischil Apr 07 '23 at 17:24
  • @EricPostpischil I wasn't aware of this. Thanks for the knowledge! I feel like that probably isn't considered good practice though right? – Matthew G Apr 08 '23 at 19:37
  • @MatthewG: It is, or was, fine for situations when the features it provided were needed. (Nested functions can access variables in their parent functions and can [curry](https://en.m.wikipedia.org/wiki/Currying) arguments.) Nowadays there are better methods, like [blocks](https://clang.llvm.org/docs/BlockLanguageSpec.html) in Clang. – Eric Postpischil Apr 08 '23 at 20:24
1

You have plenty issues here.

  1. Nested functions.
  2. You do not use parameters and return values of functions
  3. Bad function logic (in your case only input functions make sense). Generally logic is very poor
  4. You do not check delta before taking the square root.
double getFloatValue(const char *message)
{
    double f;
    do 
    {
        printf("\n%s", message);
    }while(scanf("%lf", &f) != 1);
    return f;
}

char getChar(const char *message)
{
    int c;

    printf("%s", message);
    do
    {
        c = fgetc(stdin);
        if(c == EOF) 
        {
            c = 'N';
            break;
        }
        c = toupper((unsigned char)c);

    }
    while(!isalpha((unsigned char )c) && c != 'Y' && c != 'N');
    return c;
}

int main(){
    double a, b, c, delta, x1, x2;
    char YN;

    do 
    {
        a = getFloatValue("Enter a:");
        b = getFloatValue("Enter b:");
        c = getFloatValue("Enter c:");

        printf("\nEquation: %f * X^2 %+f * X %+f\n", a, b, c);

        delta = (b*b) - (4 * a * c);
        if(delta >= 0)
        {
            x1 = (-b-sqrt(delta))/(2*a);
            x2 = (-b+sqrt(delta))/(2*a);
            if(x1 == x2) 
            {
                printf("The only root of the equation is %f.\n", x1);
            }
            else
            {
                printf("The first root of the equation is %f.\n", x1);
                printf("The second root of the equation is %f.\n", x2);
            }
        }
        else
        {
            printf("No roots\n");
        }
    }while(getChar("Another equation? (Y/N)") == 'Y');

    return 0;
}

https://godbolt.org/z/jb74M4qWq

0___________
  • 60,014
  • 4
  • 34
  • 74
1

You have nested functions.

Although this is [somewhat] allowed with gcc, it is non-standard. The generated code is ugly/error prone.

Better to just make the vars global scope. Or, restructure your program so you don't need to do this (e.g. pass more items as parameters).


You're trying to do a "lambda" function or "closure".

One way is to have a struct that contains all the variables that were function scoped in main and pass around a pointer to that. Here's a skeletal example:

struct vars {
    float a, b, c, delta, x1, x2;
};

void
enter(struct vars *v)
{
    printf("Insert the value of 'a':\n");
    scanf("%f", &v->a);

    printf("Insert the value of 'b':\n");
    scanf("%f", &v->b);

    printf("Insert the value of 'c':\n");
    scanf("%f", &v->c);

    v->delta = (v->b * v->b) - (4 * v->a * v->c);
    v->x1 = (-v->b - sqrt(v->delta)) / (2 * v->a);
    v->x2 = (-v->b + sqrt(v->delta)) / (2 * v->a);
}

int
main(void)
{
    struct vars vars;

    enter(&vars);
    // ...

    return 0;
}

Note that: "there's no such thing as a free lunch". In languages that support lambda functions (e.g. C++, etc.) the hidden/generated code would be similar to the above.

Craig Estey
  • 30,627
  • 4
  • 24
  • 48