Stop Trying to Beat the House
OK, this afternoon I was testing out my market data server and I ran across a bug. It was an annoying little thing, and I deserve to have been bitten by it for trying to beat the house. And by this I mean trying to be smarter than the OS and library builders. The original method looked something like this:
/* * There are times that you might want to see the numeric * representation of the contents of this string. These methods * make that easy enough to do and take care of all the dirty * work for us. */ int CKString::intValue() { bool error = false; int retval = 0; /* * We're going to loop over each character in the String until we * get to the end. As we're going, we'll be building up * the return value. If we find a character that's not a digit * then we'll return what we have to this point, just as atoi() * would. */ for (int i = 0; i < mSize; i++) { // see if it's not a digit if (!isdigit(mString[i])) { break; } else { // accumulate the value retval = retval * 10 + (mString[i] - '0'); } } return error ? 0 : retval; }
the reason I chose to roll my own atoi() was that I was thinking that the system routine did too much and all I needed was to add up the value. How easy could that be?
I should have learned from Vegas - Never bet against the House!
The bug was the string '-1'. Clearly, I hadn't allowed for the '-'. When I added that into the code, and then added in the allowance for whitespace on the leading (left) side, I was looking at something that I realized that the system call was just as efficient, probably more so. When I realized how silly it was to try and beat the house, the new version of the method became:
int CKString::intValue() { int retval = 0; if (mSize > 0) { retval = (int) strtol(mString, NULL, 10); } return retval; }
which works just fine and is probably more efficient than I could have easily written. Lesson to self: Never try to beat the House!