Shitty variable names, unnecessary usage of pointer arithmetic, and clever tricks are WTFs.
When I saw this
WTF code that formats numbers to add commas,
I had forgotten how low-level C really is. Even after using C++ fairly regularly for the last several months.
With 500+ upvotes, the people over at
the reddit thread regarding the WTF
apparently think the
real WTF is the post, not the code.
nice_code, stupid_submitter - in which TheDailyWTF jumps the shark by ridiculing perfectly good code.
Let's forgive the misuse of the wornout phrase and get to whether or not looking at the code
should result in utterance of WTFs.
It goes something like this:
- Setup, in which we use globally shared memory
- Negate the number if it is negative, for no reason I can think of, and set a reminder flag.
- Set buffer to point to the final spot. Move it back one, dereference it, and insert the null string terminator there.
- Move the buffer backwards. Dereference the pointer and set the value there to the character '0'. Add the remainder of the number divided by ten to that, since '1' is 1 away from '0', and so forth.
- Divide the number by 10 so we can get to the next digit.
- If we've done the loop 3 times, move the buffer pointer back one location and insert a comma.
- Repeat starting at step 4 until the number is 0.
- Cleanup - if the front character is a comma, remove it by moving the buffer pointer forward.
- Cleanup - Move the buffer pointer backwards and insert our '-' if the negative flag has been set.
I felt like that required too much brain power to follow for doing something so simple. So I decided to make my
own version. I thought I'd try the following:
- Copy the number to a string.
- Starting at the end, copy each character to another string, inserting a comma every 3rd time.
A thousand times simpler than the convoluted mess of
nice_num
. Here's that attempt, in C:
char* commadify(long num, char* result) {
int input_len = num_digits(num);
char* input_number = malloc( input_len * sizeof(char) );
sprintf(input_number, "%ld", num);
int number_of_commas = (input_len-1) / 3;
int result_len = input_len + number_of_commas;
int input_index = input_len-1;
int result_index, count=0;
for (result_index=result_len-1; result_index>=0; result_index--) {
if( count == 3 ) {
result[result_index] = ',';
result_index --;
count = 0;
}
result[result_index] = input_number[input_index];
input_index --;
count++;
}
free(input_number);
return result;
}
I think it's clearer - but not by much. Certainly the variable names are better because you don't first
have to first understand what's going on to know what they are for. I think moving the pointer
arithmetic back into the more-familiar array notation helps understandability. And removing the trick of
knowing that the ASCII codes for '1' is 1 more than for '0' ... for '9' is 9 more than 0 means less thinking.
On the negative side, the
commadify
code is slower than nice_num, most of which is caused by using
malloc
instead of having preallocated memory. Removing those two instances
and using preallocated memory shaves a couple of tenths of a second off of the one-million-runs loop. But
you have to compensate with more code that keeps track of the start position.
So what's the verdict?
I don't think we're reacting to the WTFs I mentioned above when we see the
nice_num
code.
I think we're reacting to
C itself.
We're so used to very high level languages
that common tricks and things you'd know as a C programmer are the WTFs to us.
This kind of stuff isn't outside the realm of what a strong programmer should know. It isn't even
close to the border. The truth is our low-level skills are out of practice and we should probably get some.
What do you think?
Code with main program and comparison with nice_num is available at my github repository,
miscellany/commadify.
Update: Thanks to Dave Kirby's comment, I've fixed memory leaks and updated the code in this post and at the repository. Link to repo originally was to the specific commit - so I've changed that to link to master instead.
Hey! Why don't you make your life easier and subscribe to the full post
or short blurb RSS feed? I'm so confident you'll love my smelly pasta plate
wisdom that I'm offering a no-strings-attached, lifetime money back guarantee!
Leave a comment
There are no comments for this entry yet.
Leave a comment