# Programming: Fraction Arithmetic in C++

1. Mar 25, 2012

This program has been assigned in my intro to programming course, which assumes no previous knowledge of programming. Up to this point we've only been required to write functions that accomplish specific tasks within a program. This is the first time we've been asked to design and write a full program.

1. The problem statement, all variables and given/known data

These are the requirements for the program:

a) it will handle any single-digit addition, subtraction, multiplication, and division.

b) as a result of the math, there is a potential for up to three digit results, so the program must handle this

c) as a result of the subtraction process, it is possible to arrive at a negative answer; the program must handle this

d) the program must also manage incorrect input for all four input values and the operator. This means that if any non-digit value is entered as a numerator or denominator, if a zero is entered as a denominator, or if any character other than '+', '-', '*', or '/' is entered as an operator, the user must be informed and the program must be stopped immediately without any further processing

Here are a couple screenshots showing what the TUI looks like after the calculation has been made:

My issue:
I need to do some analysis to determine precisely when the answer will be negative and when the numerator will have two or three digits. I also need to know when the denominator will have two digits. The function used to print the green digits can only print one digit at a time, so I also need to find a way to separate my digits for the answer and print them individually at the correct location on the screen.

2. Relevant equations

3. The attempt at a solution

I started writing out all the possible fraction values a user could input and discovered that a brute force method here is unreasonable, as I would have to check a few thousand different combinations to get what I'm looking for. I need a more elegant mathematical approach that will lend to a readable and efficient function.

I've reasoned that the denominator can never be larger than 81, since only single digit values are allowed as input, so I do not need to test for a three-digit denominator. However, it is possible to have up to three digits in the numerator, so I will need to test for this and adjust my output to the screen accordingly.

Last edited: Mar 25, 2012
2. Mar 25, 2012

### I like Serena

You might convert your number to a string and get its length.

3. Mar 25, 2012

Hi ILS!

Your suggestion is very clever. Thank you!

4. Mar 25, 2012

### RoshanBBQ

So you are doing
a/b - c/d

So the program probably has variables for a b c and d. To see if it is negative just say
bool isNegative = a/b - c/d < 0

5. Mar 26, 2012

Thank you both for the help! The program runs flawlessly. =]

6. Mar 26, 2012

### Staff: Mentor

Speaking of counting digits, just some random ideas that may require additional work:

number_of_digits = int(log10(abs(number)));

while (number /= 10) number_of_digits++;

7. Mar 26, 2012

### I like Serena

Yeah, the log10 version was the first I thought of, but then I thought we would have to turn it into something like:
Code (Text):

if (abs(number) < 1)
{
number_of_digits = 1;
}
else
{
number_of_digits = 1 + int(log10(abs(number)) + 0.000000001);
}

8. Mar 26, 2012

### Staff: Mentor

I am far from stating any of these approaches is better, I just wanted to show there are many ways of skinning that cat.

9. Mar 26, 2012

### rcgldr

Just a comment, are you supposed to reduce (simplify) the fractional result, or do you get bonus points for doing this?

10. Mar 27, 2012

There aren't any bonus points available in this course, unfortunately. I might write a function for reducing the result if, by some miracle, I get some spare time and can remember this assignment.

================================================

Well, I noticed a flaw in my program when doing some last minute testing to see if I could break it.

Since we are required to halt all processing if invalid input is detected, I decided to see what would happen if I just hit enter at one of the integer prompts without giving it an integer. I discovered that a zero is sent! This is problematic; we were given a fully-functional .exe so that we can see how the program is supposed to function. The example program does not do anything when the user presses <enter> without providing values, it just sits there. Oddly enough, this is the way my program behaves when prompting for the operator (which is a character), but it will always send a "zero" when I hit <enter> at the integer prompts.

Where is the zero coming from?

Last edited: Mar 27, 2012
11. Mar 27, 2012

### I like Serena

Which function(s) do you use to read input?

12. Mar 27, 2012

Here is the function's prototype:
Code (Text):
/*
name: promptForIntAt
process: prompts user for integer at the specified location, then returns it
input: x, y location, text to prompt user (string)
output/returned: one integer (int) is returned to calling function
dependencies: uses getInputString function
*/
int promptForIntAt( int xPos, int yPos, const string &promptString );

Here is the implementation:
Code (Text):
int promptForIntAt( int xPos, int yPos, const string &promptString )
{
// initialize function
string response;
bool negFlag = false;

// print prompt string

// move cursor to response point
xPos += promptString.length();
move( yPos, xPos );

// get response from user in string form
response = getInputString( xPos, yPos, "+-0123456789" );

// convert string to integer
numStringLength = response.length();
index = 0; answer = 0;

// check for negative sign, if anything entered
if( ( numStringLength > 0 ) && ( response.at( index ) == '-' ) )
{
negFlag = true;
index++;
}

// skip front end zeroes
while( ( index < numStringLength )
&& ( ( response.at( index ) == '0' )
|| ( response.at( index ) == '+' ) ) )
{
index ++;
}

// verify some number is still there
if( index >= numStringLength )
{
return 0;
}

while( index < numStringLength )
{

answer += int( response.at( index ) - '0' );

index++;
}

if( negFlag )
{
}

// return response
}

EDIT: Sorry! The following function is a dependency for the function above:

Prototype:
Code (Text):
/*
name: getInputString (supporting function)
process: allows only specified characters to be input, allows backspace
returns when ENTER key is pressed
input: x & y locations
input: string of characters allowed for input
output (to screen): shows input process by user
output (returned): string value is returned to calling function
dependencies: uses waitForInput and charInString
*/
string getInputString( int xPos, int yPos, const string &allowedChars );

Implementation:
Code (Text):
string getInputString( int xPos, int yPos, const string &allowedChars )
{
// initialize function
const char SPACE = ' ';
const char NULL_CHARACTER = '\0';
int response, index = 0;
char inputString[ MAX_INPUT_LENGTH ];

// initialize string in case nothing is entered
inputString[ 0 ] = '\0';

// repeatedly capture & process input characters
// stop when ENTER key is pressed
do
{
// place the cursor
move( yPos, xPos + index );

// get the input as an integer
response = waitForInput( FIXED_WAIT );

// accept key pad input if used
switch( response )
{
case 465:
response = '+';
break;

case 464:
response = '-';
break;

case 463:
response = '*';
break;

case 458:
response = '/';
break;
}

// if it is in the allowed list of characters,
// accept and print it
if( charInString( response, allowedChars.c_str() ) )
{
inputString[ index ] = response;
inputString[ index + 1 ] = NULL_CHARACTER;

mvaddch( yPos, xPos + index, response );

index++;
}

// if it is the backspace key, act on it
else if( response == BACKSPACE_KEY )
{
if( index >= 0 )
{
if( index > 0 )
{
index--;
}

inputString[ index ] = NULL_CHARACTER;

mvaddch( yPos, xPos + index, SPACE );
}
}
}
while( ( response != ENTER_KEY ) && ( response != KP_ENTER_KEY ) );

// return the generated string
return string( inputString );
}

Final note: These two functions are part of a header file that our professor wrote for us to use in this assignment, so these functions aren't mine and we are not allowed to modify the header file. =[

Last edited: Mar 27, 2012
13. Mar 27, 2012

### I like Serena

What is the function getInputString() supposed to do if you press Enter?

I'm guessing that if you press Enter, the function getInputString() returns an empty response.
Your function promptForIntAt() returns a zero in that case.

14. Mar 27, 2012

Would this be the NULL_CHARACTER constant I see defined in the function? If so, it has been assigned \0, so I'm still not sure why it is returning the integer zero.

We don't start "while," "for," and "do" concepts until tomorrow when we begin file I/O, so I'm having difficulty following everything in his functions.

15. Mar 27, 2012

### I like Serena

No, it's not the NULL_CHARACTER constant.

The function getInputString() returns an empty string ("") when you press Enter.
As a result the function promptForIntAt() returns the number 0 when you press Enter.

This means that with the functions of your professor you cannot distinguish between the number 0 and Enter being pressed.

To prevent your program from responding to Enter with a zero, the only option you have now, is to check for the number zero and handle that as an invalid input.

16. Mar 27, 2012