Subscribe
RSS Feed

Archive
2007
Months
Dec

Homepage


Wed, 12 Dec 2007

Using STL for_each to build delimited lists

If you're new to using STL some of the coolness might not be immediately obvious.
Here's an example of using a function object (called a 'functor') to build a delimited list.

Here's the scenario: You've got an arbitrary list of items in an STL container class.
You need a string form of the list. So you might think you need to write a loop and deal with inserting
the separator character correctly if there are only zero, or one, elements in the list.

STL provides a template called 'for_each' that will call a function for each of the
elements of the list. At first glance that doesn't seem to be very helpful in this scenario.

Using a function class instead of a standard C style function lets you do some real magic.
You can do it with one line of code and a class. Here's an example:

      // build a list of elements
      std::vector elements;
      elements.push_back( std::string("one") );
      elements.push_back( std::string("two") );
      elements.push_back( std::string("three") );
      elements.push_back( std::string("four") );
      // convert to a pretty comma delimited list
      std::string mylist = "MyList: ";
      // build a list in one line of code!
      for_each( elements.begin(), elements.end(), ListBuilder( &mylist, std::string(",") ) );

If you're familiar with SQL here's another example:

      std::string sql = "INSERT INTO MyTable(";
      for_each( args.begin(), args.end(), ListBuilder( &sql, std::string(",") ) );
      sql += ")";

Here's the magic class that does all the work:

//---------------------------------------------------------------------------
// helper class to build delimited lists
//---------------------------------------------------------------------------
class ListBuilder
   {
   public:
      ListBuilder( std::string* List, const std::string Separator ) : List(List), S(Separator)
         {
         };
      std::string* List;
      std::string D;
      std::string S;

      void operator()( std::string& elem )
         {
            *List += D + elem;
            D = S;
         }
   };


Here's how the code works:

In place of the function there's a class instantiation:
      for_each( elements.begin(), elements.end(), ListBuilder( &mylist, std::string(",") ) );

Before the for_each code is executed the program instantiates a ListBuilder class object:
   ListBuilder( &mylist, std::string(",") )

Passed to the constructor of the object is the address of the list ("&mylist") and a string that is used
for the separator. Here's the constructor declaration:
   ListBuilder( std::string* List, const std::string Separator ) : List(List), S(Separator)

The List address is stored in the class variable "List" by the initializer ( "List(List)" ).
The Separator string is stored in the class variable "S" by the initializer ( "S(Separator)" ).

As the for_each template iterates through the list it calls the parenthesis operator of the ListBuilder
class and passes each object in the list as a parameter. Here's the operator declaration:
   void operator()( std::string& elem )

In the operator method it appends the separator and the element to the list:
            *List += D + elem;
The class variable D is the empty string on the first call to this method.
It was NOT initialized by the class constructor.
For the first element it's just appended to the list with no delimiter.
It then sets the delimiter to the separator character:
            D = S;

If the for_each template calls the operator more than once the separator is inserted
between the previous elements and the next one:
            *List += D + elem;
            
In this example:
      // build a list of elements
      std::vector elements;
      elements.push_back( std::string("one") );
      elements.push_back( std::string("two") );
      elements.push_back( std::string("three") );
      elements.push_back( std::string("four") );
      // convert to a pretty comma delimited list
      std::string mylist = "MyList: ";
      // build a list in one line of code!
      for_each( elements.begin(), elements.end(), ListBuilder( &mylist, std::string(",") ) );
            
On the first call:
   List is "one"
On the second call:
   List is "one,two"
On the third call:
   List is "one,two,three"   
etc.

I hope this tutorial has been of use to you. Function classes can be a big help when using
STL algorithms. Writing functors works for the other STL algorithms but the class operator each algorithm
template uses may differ. If you look through the documentation for the algorithm it should mention
which operator that template uses.

Jay Sprenkle


posted at: 15:41 | path: | permanent link to this entry

Mon, 26 Nov 2007

PagedGeometry v1.0 - High speed forest rendering

An add-on to the OGRE Graphics Engine, which provides highly optimized methods for rendering massive amounts of small meshes covering a possibly infinite area. This is especially well suited for dense forests and outdoor scenes, with millions of trees, bushes, grass, rocks, etc., etc.

here

This rocks!



posted at: 21:08 | path: | permanent link to this entry

Sat, 03 Nov 2007

Die roller for the Nokia PDA (or any browser)

I wanted to create a program to roll dice for my PDA. I was looking for useful things to do with it when I run RPG games. I investigated how difficult it would be to develop a native binary for the Nokia and the ARM processor and it occurred to me there was an easier way. A javascript browser would work just fine. That eliminates the need for a specialized development environment.

Javascript was interesting to learn and a lot of fun with the exception of having to put in hacks for just about every different version of browser.

I've finished the die roller application for the browser. It runs as a web page in both Firefox and Internet Exploder so you don't actually have to install anything. You can see it in action with your browser here

You can download the page and all the images here

Unzip, Copy it to your PDA, bookmark it, and you're all set.

The only bug I saw with the nokia's browser was that it wouldn't close the pull down menus after you add or remove dice. If you hit the refresh button it will reset the menus. It stores the dice you choose via a browser cookie.

posted at: 19:28 | path: | permanent link to this entry

Tue, 30 Oct 2007

Decoder Ring Theatre
If you like noir detective stories in old style radio show format you'll probably like Black Jack Justice from Decoder Ring Theatre. Drop by and give a listen!

posted at: 21:46 | path: | permanent link to this entry

Sat, 20 Oct 2007

Support the author
If you've found anything useful here please consider supporting the author. Paypal donations are gladly accepted. If you shop on Amazon you can support me through their associates program. If you purchase I get a small referral fee from Amazon. It won't cost you anything except ten extra seconds going to amazon using the link below: Shop on Amazon.com I get credit if you navigate there from this link. Thanks!

posted at: 10:53 | path: | permanent link to this entry

Fri, 12 Oct 2007

Photoshop script to add a grid of guides
This script creates a grid of guides every 100 units in the currently open document. It's a text file so you can edit the ‘100? and change it to whatever value suits you with any text editor. Save this File to your photoshop/presets/scripts directory. When you start photoshop goto the “File” menu, then “Scripts”, then choose “Guide Grid”. It will create the guides over the current image.

posted at: 23:00 | path: | permanent link to this entry

Wed, 10 Oct 2007

How to eliminate picture spam using Thunderbird

If you’re using the Mozilla Thunderbird EMail client you can use mail filters to eliminate all the dangerous picture spam. I created a mail rule to delete anything with an image in it, that is from someone I don’t know. Here are step by step instructions:

Goto the menu, hit ‘Tools’, ‘Message Filters’, then the ‘New’ button. Select the option ‘Match all of the following’ On the first line:

  1. In the first box choose ‘Body’.
  2. In the second box choose ‘contains’
  3. In the third box enter ‘Content-Type: image/gif’

This catches the embedded images. Hit the ‘+’ button next to the first line to get a second line. On the second line:

  1. In the first box choose ‘From’.
  2. In the second box choose ‘isn’t in my address book’
  3. In the third box choose ‘Personal Address Book’

If you’re in any mailing lists that send pictures you’ll have to do one more step: Hit the ‘+’ button next to the first line to get a third line. On the third line:

  1. In the first box choose ‘Reply-to’.
  2. In the second box choose ‘doesn’t contain’
  3. In the third box enter the email address of the mailing list

At the bottom of the window choose the option ‘Delete this message’. (alternately you can move it to the trash folder, then you have the option of looking in the trash folder if you want to make sure the messages are really spam). Set the check box to ‘match all of the following’.

Hit the ‘ok’ button and you’re done. Don’t forget that this email rule only applies to the account you had selected when you created it. If you have more than one you’ll have to do it for that account too. Hey Moz-dev! How about an option to copy and paste rules????

Have a good one :)

posted at: 18:26 | path: | permanent link to this entry

Tue, 09 Oct 2007

Started a blog!
I've installed the blosxom blog software on the system to make updating the site simpler. I used the nice calendar plugin as well to provide an index to older posts. They're both written in Perl.

posted at: 21:03 | path: | permanent link to this entry