Read a Percentage Value – Solution

One of the things I enjoy about coding defensive input is that I get to think about all the oddball possibilities. Users can type anything, which is something you must always anticipate. For typing in a percentage value, the door for whacky input is left wide open.

My solution to this month’s Exercise relies on two C library functions: fgets() to read input and strtof() to convert a string to a float value. The bulk of my solution is to get from one function to the other and strip out any oddball user input between.

Once the string is obtained by fgets(), I pass it along to a read_percent() function:

float read_percent(char *percent);

The function accepts a string percent as an argument and returns a float value equal to the percentage in the string. The string can contain the % and , symbols, along with the decimal separator. Any other characters that might invalidate are dealt with by the strtof() function directly.

Inside the read_percent() function, two things happen:

  1. The percent character (%) is scanned for and, if located, translated to a newline (\n).
  2. Because the % might be found at the end of input, that translation works.

  3. Any commas encountered are removed from the string. So the value 1,000 would translate to 1000, which the strtof() function can easily digest. Otherwise, a comma would truncate input, and 1,000 would be read as 1.

The code could also strip the newline (\n) from the input string, which I normally do for fgets() function input, but the strtof() function doesn’t give a rip about the newline character, so it’s good.

Here is my solution:

#include <stdio.h>
#include <stdlib.h>

#define SIZE 32

float read_percent(char *percent);

int main()
{
    char input[SIZE];
    float p;

    printf("Enter a percentage: ");
    fgets(input,SIZE,stdin);
    p = read_percent(input);
    printf("I'm working with a value of %.2f percent\n",p);

    return(0);
}

float read_percent(char *percent)
{
    int i,j;
    char new[SIZE] = "\0";

    /* strip out a percent sign */
    i = 0;
    while( *(percent+i) )
    {
        if( *(percent+i) == '%' )
            *(percent+i) = '\n';
        i++;
    }

    /* strip off commas */
    i = j = 0;
    while( *(percent+i) != '\0')
    {
        if( *(percent+i) != ',' )
        {
            *(new+j) = *(percent+i);
            j++;
        }
        i++;
    }

    return( strtof(new,NULL) );
}

The char buffer new is created and initialized at Line 24. It’s required for the comma-stripping portion of the function.

At Line 26, the code scans for the % character in the input string percent. If found, the character is replaced with a newline, \n, at Line 30. If for some reason the user types %50 instead of 50%, then the input is invalid anyway, so the value returned is 0.00, which is okay.

Lines 35 through 45 strip out any commas in the input string. Characters are read from string percent. If the character isn’t a comma (Line 39), it’s copied to string new and both offset variables, i and j, are incremented. Otherwise, only offset variable i is incremented, effectively skipping the comma character.

After the string is copied, the result is sent to the strtof() function. The result is immediately returned at Line 47.

My solution presents only one possibility. I’m sure many others exist. In fact, you could strip out both the percent and comma characters in a single loop, which would make the read_percent() function tighter. As long as your solution defensively handles a variety of different input strings, you’re good.

Leave a Reply