-2

I'm new to C language and coding and I encountered a question asking me to change the function header of:

float RealRoot_1(float a, float b, float c);
float RealRoot_2(float a,float b,float c);

to become:

void RealRoot_1(void);
void RealRoot_2(void);

I was told that it has something to do with Global Variables but I still couldn't figure it out after trying quite some time. Can anyone please explain on how to do it? Thanks a lot.

The source file is as below:

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

int main()
{
    float RealRoot_1(float a, float b, float c);   // Prototype declaration
    float RealRoot_2(float a, float b, float c);    

    // Defining Input Variables
    float x, y, z;

    // Defining Output Variables
    float Root_1, Root_2;

    printf("Please enter the factor of X^2: ");
    scanf("%f",&x);

    printf("Please enter the factor of X: ");
    scanf("%f",&y);

    printf("Please enter the free factor: ");
    scanf("%f",&z);

    Root_1 = RealRoot_1(x,y,z);
    Root_2 = RealRoot_2(x,y,z);

    printf("the First Root is: %f \n", Root_1);
    printf("the Second Root is: %f \n", Root_2);

    system("pause");
}


float RealRoot_1(float a, float b, float c)
{
    float x; 
    x = (-1*b + sqrt(pow(b,2) - 4 * a * c)) / (2 * a);

    return x;
}

float RealRoot_2(float a, float b, float c)
{
    float x; 
    x = (-1*b - sqrt(pow(b,2) - 4 * a * c)) / (2 * a);

    return x;
}
Kar Keng Chan
  • 73
  • 1
  • 8
  • 6
    I don't understand, this looks like a pretty bad idea. Just because you __can__ do something does not mean you __have__ to do it. – Sourav Ghosh Sep 06 '16 at 12:49
  • Declare prototype above the main(). – msc Sep 06 '16 at 12:51
  • 6
    Have to agree with @Sourav here, we've spent the better part of the last 40 years moving towards _more_ encapsulation. Global variables are generally a bad idea. So, yes, it _can_ be done but, in the interests of good code (and to avoid the possibility I or my children may have to maintain such monstrosities), I'm not going to tell you how :-) – paxdiablo Sep 06 '16 at 12:53
  • As pointed out by Sourav this is a bad idea, but you can do it declaring `float a, b, c, x;` at the very begin after the `includes` section, remove the declaration `float x;` inside the functions, call your functions `RealRoot_1();` and read `x` from `main` – David Ranieri Sep 06 '16 at 12:58
  • I don't know what it is that you want to know. You've already mentioned global variables. Do you know what these are? If so, then do you really not see how they could be applied to the question? If not, then don't you think learning about them might be a good place to start? – John Bollinger Sep 06 '16 at 13:00
  • 1
    @paxdiablo "Global variables are generally a bad idea." I don't know who teaches you this stuff, but to me you sound like someone who has been in a mob and has been taught the same thing as the others. Global variables can sometimes be the only solution. – machine_1 Sep 06 '16 at 13:01
  • 1
    @machine_1, hence my use of the word "generally". They have their place, as do multiple return points, `goto` and so on, but the vast majority of code should avoid them. In any case, I'm hard-pressed to come up with a scenario where they're the *only* solution. Best solution, perhaps, but not "only". – paxdiablo Sep 06 '16 at 13:03
  • @JohnBollinger I think I know what global variables are but I really didn't see how to apply it.. – Kar Keng Chan Sep 06 '16 at 13:11
  • @AlterMann I did that but it doesn't work as it returns an error "void value not ignored as it ought to be" ... also, if i changed the `RealRoot_1(x,y,z);` to `RealRoot_1();` , does it pass the values of x,y and z to the function? sorry for all the questions.. – Kar Keng Chan Sep 06 '16 at 13:19
  • @paxdiablo agree with you. But just to give you example in which globals are required and the only solution (according my little knowledges): in embedded device, using interruption - interruption handlers are totally hermetic function, except for global variables. (probably same for signal handling on linux ?) – Garf365 Sep 06 '16 at 14:05
  • Why would you transform these functions int void functions with nor parameters? What problem are you _actually_ trying to solve ? – Jabberwocky Sep 06 '16 at 14:52
  • @MichaelWalz it's actually a question from my lecturer. He didn't give any explanation on it and I could not find any answer from google. – Kar Keng Chan Sep 06 '16 at 14:55
  • @KarKengChan, OK answers below are what you need, but it's definitely a bad idea. – Jabberwocky Sep 06 '16 at 14:56
  • @MichaelWalz I see it just makes things complicated lolz – Kar Keng Chan Sep 06 '16 at 14:59
  • Using global variables has its place in life critical applications and other select usages. This example, while useful for learning, is not a good usage of global variables. – chux - Reinstate Monica Sep 06 '16 at 16:49

2 Answers2

3

This can be done by using global variables. You need to ensure that the variable names used in the function are the same as the ones used in the main code.

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

void RealRoot_1(void);   // Prototype declaration
void RealRoot_2(void);        

float x, y, z;  
float Root_1, Root_2;

int main()
{

    // Defining Output Variables

    printf("Please enter the factor of X^2: ");
    scanf("%f",&x);

    printf("Please enter the factor of X: ");
    scanf("%f",&y);

    printf("Please enter the free factor: ");
    scanf("%f",&z);

    RealRoot_1();
    RealRoot_2();

    printf("the First Root is: %f \n", Root_1);
    printf("the Second Root is: %f \n", Root_2);

    system("pause");
}


void RealRoot_1(void)
{
    Root_1 = (-1*y + sqrt(pow(y,2) - 4 * x * z)) / (2 * x);
}

void RealRoot_2(void)
{
    Root_2 = (-1*y - sqrt(pow(y,2) - 4 * x * z)) / (2 * x);
}

Please note that this is a worse way of doing things than was given in the initial problem. In the initial exercise. You are loosing modularity and using too many globals is in general a bad idea.

You can also see Are global variables bad?

Rishikesh Raje
  • 8,556
  • 2
  • 16
  • 31
2

This should be self explanatory:

float RR_a, RR_b, RR_c;
float RR_d; // store result here(like a return value)

void RealRoot_1(void); // prototypes
void RealRoot_2(void);

void main(void)
{
   printf("Please enter the factor of X^2: ");
   scanf("%f",&RR_a);

   printf("Please enter the factor of X: ");
   scanf("%f",&RR_b);

   printf("Please enter the free factor: ");
   scanf("%f",&RR_c);

   RealRoot_1();
   printf("the First Root is: %f \n", RR_d);

   RealRoot_2();
   printf("the Second Root is: %f \n", RR_d);

   system("pause");
}

void RealRoot_1(void)
{
    float x; 
    x = (-1*RR_b + sqrt(pow(RR_b,2) - 4 * RR_a * RR_c)) / (2 * RR_a);

    RR_d = x;
}

void RealRoot_2(void)
{
    float x; 
    x = (-1*RR_b - sqrt(pow(RR_b,2) - 4 * RR_a * RR_c)) / (2 * RR_a);

    RR_d = x;
}

Notice that after calling RealRoot_1 we now print the result before calling RealRoot_2. That's because the result of RealRoot_1 which is stored in RR_d is overwritten by RealRoot_2, thus it is lost. You can circumvent this by declaring a second return variable, RR_d_2 and storing the result of RealRoot_2 in it.

We do not need duplicates for RR_a, RR_b or RR_c because their values are not modified within the functions.

This way of writing functions has limitations, which will be obvious when faced with recursion or multi-threading.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
kundrata
  • 651
  • 3
  • 12
  • 24