Hey guys, I have an integer validation problem.. i wanna validate integers for fractions where the numerator must be 0 <= num <= 20, and the denominator must be 1<= den <= 20.. and later on i want to multiply them together and simplify, but only the validation has a problem... the entire function is below:

void fractions()
{    
	int nullEnter = 0;
    int numProd, denProd, numeratorLength, intCheck0, intCheck1, intCheck2, intCheck3, intCheck4, intCheck5, intCheck6;
    int iNum1 = 0, iNum2 = 0, iDen1 = 0, iDen2 = 0, fracCheck = 0, invalid = 0, numIsZero = 0;
	char frac1[7] = "", frac2[7] = "";
	char tempNum1[4], tempNum2[4], tempNum3[4];
	char numbers[11] = "0123456789";

	printf("\nFractions\n--------------\n");
	do
	{	while(fracCheck == 0)           /*fraction 1 validation*/
        {   printf("Enter fraction 1: ");
    		fgets(frac1, 7, stdin);
    		numeratorLength = strspn(frac1, numbers);      /*length of numerator*/
    		
    		intCheck0 = atoi(&frac1[0]);
    		intCheck1 = atoi(&frac1[1]);
    		intCheck2 = atoi(&frac1[2]);     
    		intCheck3 = atoi(&frac1[3]);
    		intCheck4 = atoi(strncpy(tempNum1, &frac1[0], 2));        /*converting XX into an integer in the fraction XX/y*/
    		intCheck5 = atoi(strncpy(tempNum2, &frac1[2], 2));        /*converting YY into an integer in the fraction x/YY*/
    		intCheck6 = atoi(strncpy(tempNum3, &frac1[3], 2));        /*converting YY into an integer in the fraction xx/YY*/
    		
    		if(frac1[0] == '\n')
    		{   break;
    		}
            else if(frac1[strlen(frac1)-1] != '\n')   /*length check*/
    		{   readRestOfLine();
    		    printf("Invalid fraction.\n\n");
    		    invalid = 1;
            }
            else if((frac1[1] == '/') && (frac1[3] == '\n') && (intCheck0 != 0) && (intCheck2 != 0))     
            {   fracCheck = 1;   /*x/y check*/
                iNum1 = atoi(&frac1[0]);
		        iDen1 = atoi(&frac1[2]);
            }
            else if((frac1[2] == '/') && (frac1[4] == '\n') && (intCheck4 != 0) && (intCheck3 != 0))     
            {   fracCheck = 1;   /*xx/y check*/ 
                iNum1 = atoi(strncpy(tempNum2, &frac1[0], 2));
                iDen1 = atoi(&frac1[3]);
            }
            else if((frac1[1] == '/') && (frac1[4] == '\n') && (intCheck0 != 0) && (intCheck5 != 0))     
            {   fracCheck = 1;   /*x/yy check*/
                iNum1 = atoi(&frac1[0]);
                iDen1 = atoi(strncpy(tempNum1, &frac1[2], 2));
            }
            else if((frac1[2] == '/') && (frac1[5] == '\n') && (intCheck4 != 0) && (intCheck6 != 0))     
            {   fracCheck = 1;   /*xx/yy check*/
                iNum1 = atoi(strncpy(tempNum2, &frac1[0], 2));
                iDen1 = atoi(strncpy(tempNum3, &frac1[3], 2));
            }
            else if((frac1[0] == '0') && (frac1[1] == '/') && (frac1[3] == '\n') && (intCheck2 != 0))
            {   fracCheck = 1;   /*0/y check*/
                numIsZero = 1;
                iNum1 = 1;
                iDen1 = 2;
            }
            else if((frac1[0] == '0') && (frac1[1] == '/') && (frac1[4] == '\n') && (intCheck5 != 0))  
            {   fracCheck = 1;   /*0/yy check*/
                numIsZero = 1;
                iNum1 = 1;
                iDen1 = 2;
            }            
            else
            {   printf("Invalid fraction.\n\n");
                invalid = 1;
            }
            /*up to this point the above ensures the fraction is in one of the 4 forms and they are integers*/
            
            if((iNum1 > 20 || iDen1 == 0 || iDen1 > 20) && invalid == 0)
            {   printf("Invalid fraction.  Allowed parameters- Numerator(0-20), Denominator(1-20)\n\n");
                fracCheck = 0;
            }
            
            invalid = 0; /*re-initialize invalid*/
        }   /*end of fraction 1 validation*/
        
        if(frac1[0] == '\n')   /*check for a null enter*/
		{   break;
    	}

        while(fracCheck == 1)           /*fraction 2 validation and formatting*/
        {   printf("Enter fraction 2: ");
    		fgets(frac2, 7, stdin);
    		numeratorLength = strspn(frac2, numbers);
    		
    		intCheck0 = atoi(&frac2[0]);
    		intCheck1 = atoi(&frac2[1]);
    		intCheck2 = atoi(&frac2[2]);     
    		intCheck3 = atoi(&frac2[3]);     
    		intCheck4 = atoi(strncpy(tempNum1, &frac2[0], 2));        /*parsing the bracket(XX)/y*/
    		intCheck5 = atoi(strncpy(tempNum2, &frac2[2], 2));        /*parsing the bracket x/(YY)*/
    		intCheck6 = atoi(strncpy(tempNum3, &frac2[3], 2));        /*parsing the bracket xx/(YY)*/
    		
    		if(frac2[0] == '\n')
    		{   break;
    		}
            else if(frac2[strlen(frac2)-1] != '\n')   /*length check*/
    		{   readRestOfLine();
    		    printf("Invalid fraction.\n\n");
    		    invalid = 1;
            }
            else if((frac2[1] == '/') && (frac2[3] == '\n') && (intCheck0 != 0) && (intCheck2 != 0))     
            {   fracCheck = 2;   /*x/y check*/
                iNum2 = atoi(&frac2[0]);
		        iDen2 = atoi(&frac2[2]);
            }
            else if((frac2[2] == '/') && (frac2[4] == '\n') && (intCheck4 != 0) && (intCheck3 != 0))     
            {   fracCheck = 2;   /*xx/y check*/ 
                iNum2 = atoi(strncpy(tempNum2, &frac2[0], 2));
                iDen2 = atoi(&frac2[3]);
            }
            else if((frac2[1] == '/') && (frac2[4] == '\n') && (intCheck0 != 0) && (intCheck5 != 0))     
            {   fracCheck = 2;   /*x/yy check*/
                iNum2 = atoi(&frac2[0]);
                iDen2 = atoi(strncpy(tempNum1, &frac2[2], 2));
            }
            else if((frac2[2] == '/') && (frac2[5] == '\n') && (intCheck4 != 0) && (intCheck6 != 0))     
            {   fracCheck = 2;   /*xx/yy check*/
                iNum2 = atoi(strncpy(tempNum2, &frac2[0], 2));
                iDen2 = atoi(strncpy(tempNum3, &frac2[3], 2));
            }
            else if((frac2[0] == '0') && (frac2[1] == '/') && (frac2[3] == '\n') && (intCheck2 != 0))
            {   fracCheck = 1;   /*0/y check*/
                numIsZero = 1;
                iNum2 = 1;
                iDen2 = 2;
            }
            else if((frac2[0] == '0') && (frac2[1] == '/') && (frac2[4] == '\n') && (intCheck5 != 0))  
            {   fracCheck = 1;   /*0/yy check*/
                numIsZero = 1;
                iNum2 = 1;
                iDen2 = 2;
            }  
            else
            {   printf("Invalid fraction.\n\n");
                invalid = 1;
            }
            
            if((iNum2 > 20 || iDen2 == 0 || iDen2 > 20) && invalid == 0)
            {   printf("Invalid fraction.  Allowed parameters- Numerator(0-20), Denominator(1-20)\n\n");
                fracCheck = 1;
            }

            
            invalid = 0; /*re-initialize invalid*/
        }   /*end of fraction 2 validation and formatting*/
        
        if(frac1[0] == '\n')   /*check for a null enter*/
        {   break;
        }
        if(numIsZero == 1)     /*check for a 0 numerator*/
        {   printf("Product: 0");
            break;
        }

		numProd = iNum1*iNum2;
		iNum1 = numProd;     /*re-use num1 to store numProd and denProd*/
		denProd = iDen1*iDen2;
		iNum2 = denProd;

		while(iNum1 != iNum2)  /*exits when GCD is found, when iNum1==iNum2*/
		{	if(iNum1 > iNum2)
			{	iNum1 -= iNum2;
			}
			else
			{	iNum2 -= iNum1;
			}
		}

		numProd = numProd/iNum1;
		denProd = denProd/iNum1;
		printf("%s%i/%i", "Product: ", numProd, denProd);
	}while(nullEnter == 1);
}

I'm trying to parse the string to an int using atoi(), which should return a 0 when it is not an int. Lets say the user enters in a value: 1e/2, intCheck4 (I highlighted this in red) should return an int 0, but instead (i think) it only takes the first value and returns a 1, so it isn't validated properly. I can't validate it 1 character at a time because the numerator has to allow for a 0, and so if a user enters in a fraction: 0/2, it is a valid fraction but will not be accepted by the program.
Can anyone tell me if im doin something wrong here and/or how I should go about validating this otherwise. Thanks.

Recommended Answers

All 3 Replies

1 - don't use fgets, it's a security bug. Your program may well behave in a complete different way than you expect (dig for "buffer overflow" on the web) (Edit: this is wrong, I was thinking about gets, forget that sentence.)
2 - let's say you have read the string in a variable called fraction, you can do:

int num, den, nb_item;
nb_item = sscanf(fraction, "%d / %d", &num, &den);
if (nb_item != 2) /* error */;
if (num < 0 || num > 20) /* error */;
if (den < 1 || den > 20) /* error */;

Then you can play with den and num as you wish.
HTH.
Ah, how to read a string and avoid buffer overflow is another issue.
And some strings might also be accepted when they maybe shouldn't, like "2/3abc"

commented: Just an amasing security advice -5

> don't use fgets, it's a security bug.

Care to explain?

> don't use fgets, it's a security bug.

Care to explain?

Oops, sorry. Forget it. I was thinking about gets.
My apologies.

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.