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.