The challenge for this month’s Exercise is to determine whether an integer, 1 to 100, is divisible by nine or contains the digit ‘9’. It seems like an easy puzzle for a C programmer to solve, but what I found interesting was crafting the output — specifically when a number both contains ‘9’ and is divisible by nine.
For my solution, which you can view in full on GitHub, I used a series of enumerated constants to determine the return value from my no_nine() function:
enum { LEGAL, DIVIDEDBY, NINE };
The three constants are LEGAL (0) for a legal value; DIVIDEDBY (1) for a value evenly-divisible by nine; and NINE (2) for a value containing the digit ‘9’.
Here is my no_nine() function:
int no_nine(int n)
{
char number[16];
int r,t;
t = LEGAL; /* it's zero */
/* is the number divisible by nine? */
if( n % 9 == 0 )
t += DIVIDEDBY;
/* convert the number into a string */
r = snprintf(number,16,"%d",n);
/* test for overflow, though the size 16 is
beyond the range of a standard int value */
if( r > 16 )
{
fprintf(stderr,"Number overflow\n");
exit(1);
}
/* does the digit 9 appear in the number? */
if( strchr(number,'9') != NULL )
t += NINE;
/* no nines found */
return(t);
}
The first assumption is that the number passed, n, is legal: t = LEGAL, which also initializes return variable t.
An if statement determines whether the value is evenly divisible by 9: if( n % 9 == 0 ). If so, the value of variable t is increased: t += DIVIDEDBY; But the function doesn’t stop there.
To check for the digit ‘9’, the snprintf() function converts int variable t into a string, number. The strchr() function then checks for the presence of the digit ‘9’ within the string:
if( strchr(number,'9') != NULL )
If a NULL is returned from the strchr() function, the string lacks a ‘9’ digit, so this function checks for a positive return value, in which case variable t is increased: t += NINE;
When the value of variable t is then returned to the main() function, its possible values are:
LEGAL (0), no nines
DIVIDEDBY (1), divisible by nine
NINE (2), contains the digit ‘9’
DIVIDEDBY+NINE (3), both divisible by nine and containing the digit ‘9’
In the main() function, the return value from no_nine() is compared in a complex if-else structure to output the proper string. Here is the code snippet, where x is the int tested and r is the return value from the no_nines() function:
if( r == LEGAL )
printf("%3d is legal\n",x);
else
{
printf("%3d is illegal - ",x);
if( r == DIVIDEDBY+NINE )
printf("divisible by 9 and contains '9'\n");
else if ( r == DIVIDEDBY )
printf("divisible by 9\n");
else
printf("contains '9'\n");
}
For me, the easy part of this Exercise was crafting the no_nines() function. Determining whether a value is divisible by 9 is cinchy when you know how to use the % operator. The only way I could figure out how to check for the digit ‘9’ is to convert the number to a string and then search for it.
In my first draft of the solution, the no_nines() function returned TRUE or FALSE, but then I wanted more detail in the output, so I devised the enum constants.
For the main() function, I tried to devise a more clever way to generate the “both” output string, but settled on the if-else contraption as it works. It would be nifty to craft a method to generate the "divisible by 9 and contains a '9'" string by combining output from the two other “illegal” conditions, but my brain was sapped. Perhaps you came up with a better solution?
Keep in mind that any programming solution for this challenge is valid, providing it generates the proper output.