Monday, January 18, 2010

sscanf Tips and Tricks

It's rare to see sscanf used for string parsing in production code. I'm not entirely sure why it's shunned, because sscanf can parse a wide variety of strings in a single line of code, and the alternatives are typically extremely verbose and complicated in comparison. Parsing character strings letter-by-letter? Yuck. I think the issue is that its powers are hard to wield, and there aren't a lot of "Beginner's Guide to Sscanf Mastery" like we have for regular expressions. Also, the language of sscanf is quirkier and less thorough than regular expressions, so lots of users give up on it early. Don't be so hasty.

Before we begin, things to know about sscanf:

• sscanf's return value is the number of matched elements. This differs from sprintf which returns the number of generated characters. The number of matches doesn't seem too useful on the surface--shouldn't it just match the number of elements in the format string? As it turns out, this value can actually be quite useful. (And if you need to know the number of characters sscanf has consumed, you can use %n for this. Note that Microsoft actually disables %n by default, contrary to the standard, because of security implications, so you need to re-enable it before calling sscanf.)

• sscanf typically requires your format string body to match the input string exactly. For instance, if your string is "You scored 1000 points!" and your format is "You scored %d points!", your number will be read in without incident. But if your format string is "YOU SCORED %d POINTS!", sscanf will give up before it reads the "1000" value, because the strings up until that point don't match up. It's even case-sensitive, and unlike regular expressions, there's no option to disable case sensitivity. To work around this limitation, you can use _strlwr if you're using Visual C++ to make your input string all lowercase. Other platforms will need to make do with a standards-compliant _strlwr equivalent, such as the inelegant but compact:
std::transform(myString, myString + strlen(myString), myString, tolower);

• sscanf treats any and all whitespace as equal. In other words, sscanf will match any whitespace with any other whitespace, in any quantity. So if your input string is "This\n is a \t\t\t test", it will match the format string "This is \n\r\t a test". No problem. If you have a need for precise whitespace matching, you can sometimes use %c and then verify the character manually, but generally sscanf isn't going to be very convenient for you. Fortunately, in most cases, you don't care about the precise type or quantity of whitespace. It's a little odd that the API is completely strict about case and completely non-strict about whitespace, but that's how it works.

• sscanf's %s specifier stops reading the string as soon as it encounters whitespace. This may be useful in some cases, but in many other cases I've found it to be unhelpful.

• One of sscanf's least-known tricks is that it can do character groups, just like regular expressions. For instance, "%[A-Za-z]" is like %s, but will stop reading as soon as it encounters any non-alphabet character. The caret inverts the effect; "%[^=:]" will keep reading and consuming any character until it finds an equal sign or colon.

(to be continued)

The Costs of Canceling Cable

A few weeks ago Mandi and I decided that we had no need to spend $100 a month to watch a few random TV shows, particularly since they were shows that can be had on iTunes or Hulu. So we bit the bullet and canceled cable. So far I've bought the following gadgets to fill in the gaps.



Scosche component A/V cable for iPod/iPhone: an inexpensive substitute for the AppleTV. 2 x $30 (I bought one cable for each TV in the house).One of the few non-Apple cables that will allow you to play video from an iPhone 3G/3GS on your HDTV. Lots of knockoff cables exist that will work with older models of iPod/iPhone, but the newest models have an encryption chip in them that the counterfeiters can't replicate yet. If the phone doesn't detect the chip, the cable won't work.

Using this cable, I can easily download a TV episode straight from iTunes (either on the computer or on the phone), then plug the phone into the TV and watch. It's not quite as elegant as the official AppleTV, and the picture quality is clearly standard-def, but frankly it's pretty slick that a pocket-sized device can be a decent AppleTV substitute at all.

INTENDED USE: Watching ABC shows like Grey's Anatomy or Private Practice, that only show up on iTunes because ABC ≅ Disney ≅ Pixar ≅ Apple. Also, I've kind of wanted to try this for a while now. It just seems convenient and useful.

QUIRKS: The cable connection to the phone is not as snug as a real Apple dock connector. Even when it's fully engaged, if you push on it, it can twist to the side and lose connection. However, once it's seated and you place the phone down, it seems to stay connected just fine.



PlayOn for Windows: in tandem with an existing DLNA device like a Playstation 3, a pretty effective Roku substitute. $19 (Regular price $40, discounted to $30 if you wait 14 days for the demo to expire, another $11 discount if you sign up for a Gamefly trial and immediately cancel.)

This is a Windows app which connects to Hulu, Netflix, Amazon, and various other websites, transcodes the video into something which your PS3 can decode, then streams the video to the PS3. It shows up in the PS3 menus automatically, lists all your episode queues as a set of hierarchical folders, and is pretty darn intuitive to use. One quirk is that using "rewind" or "fast-forward" over 802.11g is painful. I may end up putting an 802.11n router on the PS3 if I find one for a decent price.

INTENDED USE: Watching Hulu videos, and perhaps occasional Amazon VOD. Hopefully, if we stay current with Hulu, we can get a large percentage of our TV watching done at no cost. I don't think Amazon has much content that iTunes doesn't, but it's kind of nice that Amazon doesn't require you to store the video locally--my backup hard drive is already filling up fast enough--and Amazon also has occasional coupons and specials, whereas iTunes only has discounts once in a blue moon.

QUIRKS: It doesn't support some advanced features, such as closed captioning in Hulu. This will be an issue when my hard-of-hearing family members show up. But it's not the only way to stream Hulu to the TV, just the most convenient option.



Hulu Desktop: In conjunction with Rowmote Pro, a very user-friendly interface for Hulu with a working remote control. $0 for Hulu Desktop, $5 for Rowmote Pro. Unlike PlayOn, it supports closed-captioning. It also has a very stylish user interface with episode previews.

The downside is that you need to have a Mac or PC actually plugged into the TV to make this work. Since we have laptops, this is not a huge downside, but it adds an extra 3-minute impediment to getting the TV show started, and it's just one more hassle. Plus, if your laptop battery is low, better have a charger set up by the TV, since this drains battery fast. (PlayOn also drains juice remarkably quickly, but you can set the laptop wherever you want as long as you're in 802.11n range.)

INTENDED USE: Hulu, obviously, if closed-captioning is needed.



HDTV Antenna: A little fancier than the rabbit ears of old, these antennas plug into the wall to provide a signal boost, and have the juice to receive HD over-the-air content. $19 on eBay. I haven't received this yet.

I've only ordered one antenna for now. I'll probably put it in the master bedroom. If it ends up working great, I'll probably get a second one for the downstairs TV, since antennas just aren't that expensive.

INTENDED USE: Local news, sports, PBS, live events like the Tournament of Roses. I doubt we will use it a lot, but with the rain we're having right now, having access to local news or weather might actually be handy. And PBS in the morning shows a lot of great kids programming like Martha Speaks or Sesame Street that is hard to get elsewhere.




So, in other words, in my first month of jettisoning cable, I have actually spent about $100 on various products to replace it. Which isn't really a savings--it's more or less a wash. The good news is that I don't have to spend another $100 next month to buy it all again. And it's kind of fun to set up all these gadgets, in a geeky way, even though most of them compromise picture quality.