Hi,

This is the first time ever I post something about any programming language. Im just starting this semester with C language, so Im really new on this. This C code is a project we have for the class. We have to supply definitions for different functions. I have gone over all of them and found the program to work as expected, but for some reason the ReducedFraction function is not working. This function was given. I tried to use the function when calling any of the specified operations (+, -, *, /), but it doesn't reduce the fraction. I still need to work on a couple of operations, but that I know I can do with no problems, so if you see some of the code incomplete, I'm just leaving that part of the code for the end (specifically the switch statement). I don't expect you giving me the answer, just to get your feedback. Otherwise thank you anyways.

Here is the code:

/* Begin DO_NOT_MODIFY_REGION */

#include <stdio.h>
#include <stdlib.h>  /* Provides the abs function */
#include <string.h>
#include <ctype.h>

typedef struct fraction {
      int numerator;
      int denominator;
} Fraction;

int gcd(int x, int y);
/* Precondition: a and b must be positive */

Fraction ReduceFraction(Fraction R);

Fraction inputFraction();
/* Prompts for, inputs and returns a single fraction */


Fraction AddFractions(Fraction R1, Fraction R2);
/* Returns R1+R2 in reduced form */
Fraction SubtractFractions(Fraction R1, Fraction R2);
/* Returns R1-R2 in reduced form */
Fraction MultiplyFractions(Fraction R1, Fraction R2);
/* Returns R1*R2 in reduced form */
Fraction DivideFractions(Fraction R1, Fraction R2);
/* Precondition: in reduced form R2 must be nonzero
   Returns R1/R2 */


/* NOTE: IN THE NEXT TWO FUNCTIONS, THE LOGICAL TYPE OF THE op PARAMETER
         IS char; HOWEVER, IT IS DECLARED AS int TO AVOID SOME ARCANE
         COMPILER WARNINGS.  FUNCTIONS IN THE STANDARD LIBRARY OFTEN
         DECLARE PARAMETER OR RETURN TYPE int WHERE char WOULD BE EXPECTED */

void PrintResult(Fraction R1, Fraction R2,int op); 
/* Carries out the operation indicated by op and prints
   a string showing the two operand, the operator and the result */

void GetAndDoFractionOp(int op);
/* Prompts for two fractions
   then carries out the specified operation and prints 
   the result.  In the case of division, checks to see
   if the second fraction is zero; if so, continues 
   prompting for and inputing fractions until a nonzero
   fraction is input */

int main()
{
   char response, theOp;

   do {
      printf("\n\n-----------------------------------------");
      printf("\n\nEnter the operator you want to apply (+,-,*,/)\n");
      scanf(" %c",&theOp);
      while(getchar() != '\n');
      while( theOp != '+' && theOp != '-' && theOp != '*' && theOp != '/')
      {
	 printf("%c is not a valid operator; try again\n",theOp);
	 scanf(" %c",&theOp);
	 while(getchar() != '\n');
      }
      GetAndDoFractionOp(theOp);
      printf("Do you wish to do another (Y/N)?");
      scanf(" %c",&response);
   } while(toupper(response) == 'Y');

   printf("Normal termination\n\n");
   return 0;
}

int gcd(int x, int y)
{
   if (x%y == 0)
      return y;
   return gcd(y,x%y);
}

Fraction ReduceFraction(Fraction R)
{
   int d;
   if (R.numerator == 0)
   {
      R.denominator = 1;
      return R;
   }
   d = gcd(abs(R.numerator),abs(R.denominator));
   R.numerator /= d;
   R.denominator /= d;

   if (R.denominator < 0)
   {
      R.numerator *= -1;
      R.denominator *= -1;
   }
   return R;
}

/* End DO_NOT_MODIFY_REGION */

/* You supply the definitions for the remaining functions */

Fraction InputFraction()
/* No prompts; just input the fraction */
{
	Fraction single_frac;
	scanf("%d/%d", &single_frac.numerator, &single_frac.denominator);
	return single_frac;
}

Fraction AddFractions(Fraction R1, Fraction R2)
{
	Fraction reduced;
	printf("%d/", reduced.numerator = R1.numerator*R2.denominator+R2.numerator*R1.denominator);
	printf("%d", reduced.denominator = R1.denominator*R2.denominator);
	return reduced;
}

Fraction SubtractFractions(Fraction R1, Fraction R2)
{
	Fraction reduced;
	printf("%d/", reduced.numerator = R1.numerator*R2.denominator-R2.numerator*R1.denominator);
	printf("%d", reduced.denominator = R1.denominator*R2.denominator);
	return reduced;
}

Fraction MultiplyFractions(Fraction R1, Fraction R2)
{
	Fraction reduced;
	printf("%d/", reduced.numerator = R1.numerator*R2.numerator);
	printf("%d", reduced.denominator = R1.denominator*R2.denominator);
	return reduced;
}

Fraction DivideFractions(Fraction R1, Fraction R2)
{
	Fraction reduced;
	printf("%d/", reduced.numerator = R1.numerator*R2.denominator);
	printf("%d", reduced.denominator = R1.denominator*R2.numerator);
	return reduced;
}

void PrintResult(Fraction R1, Fraction R2, int op) /* you should use op as a char object in your code */
{	
	switch (op)
	{
		case '+':
			printf("(%d/%d) + (%d/%d) = ", R1.numerator, R1.denominator, 
					R2.numerator, R2.denominator);
			AddFractions(R1, R2);
			printf("\n");
			break;
		case '-':
			printf("(%d/%d) - (%d/%d) = ", R1.numerator, R1.denominator, 
					R2.numerator, R2.denominator);
			ReduceFraction(SubtractFractions(R1, R2));
			printf("\n");
			break;
	}
}

void GetAndDoFractionOp(int op) /* you should use op as a char object in your code */
{
	Fraction Frac1, Frac2;

	printf("Please enter the first fraction argument (n/d)\n");
	Frac1 = InputFraction();
	printf("Please enter the second fraction argument (n/d)\n");
	Frac2 = InputFraction();
	
	switch (op)
	{
		case '+':
			PrintResult(Frac1, Frac2, op);
			break;
		case '-':
			PrintResult(Frac1, Frac2, op);
			break;
	}
	
}

I'm looking at line 81 with the uninitialized variable 'd' that is used in division. Is there something special about that?

Well, the function where that variable is used (ReduceFraction(Fraction R)) was given by the professor. I just noticed that it is not initialized, but we weren't suppose to modify any of that. I assumed that the function is working as expected. After a couple of attempts using this particular function I thought the problem could come from there, hence the reason I wanted to make sure with someone more experienced than me. Do you think there is where the problem lies?

No, it becomes set on line 87.
Can you compile this with the most strict warning level?

> for some reason the ReducedFraction function is not working

Perhaps, because you never call it.

Yep. You are right. Rookie mistake. Now I got it working! Thank you both for the help!

Hello guys,

I modified the code and now I got the ReduceFraction function working properly. However, I'm trying to print the result of all the operations using the function PrintResult in a single printf. Can I do that?. Any help will be appreciate it.

Here is the new and modified code:

/* Begin DO_NOT_MODIFY_REGION */

#include <stdio.h>
#include <stdlib.h>  /* Provides the abs function */
#include <string.h>
#include <ctype.h>

typedef struct fraction {
      int numerator;
      int denominator;
} Fraction;

int gcd(int x, int y);
/* Precondition: a and b must be positive */

Fraction ReduceFraction(Fraction R);

Fraction inputFraction();
/* Prompts for, inputs and returns a single fraction */


Fraction AddFractions(Fraction R1, Fraction R2);
/* Returns R1+R2 in reduced form */
Fraction SubtractFractions(Fraction R1, Fraction R2);
/* Returns R1-R2 in reduced form */
Fraction MultiplyFractions(Fraction R1, Fraction R2);
/* Returns R1*R2 in reduced form */
Fraction DivideFractions(Fraction R1, Fraction R2);
/* Precondition: in reduced form R2 must be nonzero
   Returns R1/R2 */


/* NOTE: IN THE NEXT TWO FUNCTIONS, THE LOGICAL TYPE OF THE op PARAMETER
         IS char; HOWEVER, IT IS DECLARED AS int TO AVOID SOME ARCANE
         COMPILER WARNINGS.  FUNCTIONS IN THE STANDARD LIBRARY OFTEN
         DECLARE PARAMETER OR RETURN TYPE int WHERE char WOULD BE EXPECTED */

void PrintResult(Fraction R1, Fraction R2,int op); 
/* Carries out the operation indicated by op and prints
   a string showing the two operand, the operator and the result */

void GetAndDoFractionOp(int op);
/* Prompts for two fractions
   then carries out the specified operation and prints 
   the result.  In the case of division, checks to see
   if the second fraction is zero; if so, continues 
   prompting for and inputing fractions until a nonzero
   fraction is input */

int main()
{
   char response, theOp;

   do {
      printf("\n\n-----------------------------------------");
      printf("\n\nEnter the operator you want to apply (+,-,*,/)\n");
      scanf(" %c",&theOp);
      while(getchar() != '\n');
      while( theOp != '+' && theOp != '-' && theOp != '*' && theOp != '/')
      {
	 printf("%c is not a valid operator; try again\n",theOp);
	 scanf(" %c",&theOp);
	 while(getchar() != '\n');
      }
      GetAndDoFractionOp(theOp);
      printf("Do you wish to do another (Y/N)?");
      scanf(" %c",&response);
   } while(toupper(response) == 'Y');

   printf("Normal termination\n\n");
   return 0;
}

int gcd(int x, int y)
{
   if (x%y == 0)
      return y;
   return gcd(y,x%y);
}

Fraction ReduceFraction(Fraction R)
{
   int d;
   if (R.numerator == 0)
   {
      R.denominator = 1;
      return R;
   }
   d = gcd(abs(R.numerator),abs(R.denominator));
   R.numerator /= d;
   R.denominator /= d;

   if (R.denominator < 0)
   {
      R.numerator *= -1;
      R.denominator *= -1;
   }
   return R;
}

/* End DO_NOT_MODIFY_REGION */

/* You supply the definitions for the remaining functions */

Fraction InputFraction()
/* No prompts; just input the fraction */
{
	Fraction single_frac;
	scanf("%d/%d", &single_frac.numerator, &single_frac.denominator);
	return single_frac;
}

Fraction AddFractions(Fraction R1, Fraction R2)
{
	Fraction reduced;
	reduced.numerator = R1.numerator*R2.denominator+R2.numerator*R1.denominator;
	reduced.denominator = R1.denominator*R2.denominator;
	return ReduceFraction(reduced);
}

Fraction SubtractFractions(Fraction R1, Fraction R2)
{
	Fraction reduced;
	reduced.numerator = R1.numerator*R2.denominator-R2.numerator*R1.denominator;
	reduced.denominator = R1.denominator*R2.denominator;
	return ReduceFraction(reduced);
}

Fraction MultiplyFractions(Fraction R1, Fraction R2)
{
	Fraction reduced;
	reduced.numerator = R1.numerator*R2.numerator;
	reduced.denominator = R1.denominator*R2.denominator;
	return ReduceFraction(reduced);
}

Fraction DivideFractions(Fraction R1, Fraction R2)
{
	Fraction reduced;
	reduced.numerator = R1.numerator*R2.denominator;
	reduced.denominator = R1.denominator*R2.numerator;
	return ReduceFraction(reduced);
}

void PrintResult(Fraction R1, Fraction R2, int op) /* you should use op as a char object in your code */
{	
	printf("(%d/%d) %c (%d/%d) =\n", R1.numerator, R1.denominator, 
			op, R2.numerator, R2.denominator);	
}

void GetAndDoFractionOp(int op) /* you should use op as a char object in your code */
{
	Fraction Frac1, Frac2, result;

	printf("Please enter the first fraction argument (n/d)\n");
	Frac1 = InputFraction();
	printf("Please enter the second fraction argument (n/d)\n");
	Frac2 = InputFraction();
	
	switch (op)
	{
		case '+':
			result = AddFractions(Frac1, Frac2);
			PrintResult(Frac1, Frac2, op);
			break;
	}
	
}

What do you mean?

[Answer for interpretation 1]
Yes, as long as the parameters are the same, you can use PrintResult

[Answer for interpretation 2]
Yes, you can replace the function PrintResult with one printf (the same printf it has).

Hi,
I thought I could get the result of any of the operations using the PrintResult function, but I would need to add an additional parameter to the function PrintResult to access the final result of the fraction once I called the operator functions. Since we cannot modify the given functions, I just used a printf on the GetAndDoFractionOp function after the switch statement. It is now working as expected. Thank you for your help!

No problem.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.