QT strings and listen up STL Every programmer should be aware of efficiency. In school they teach you about computational efficiency, and memory efficiency, using things like Big O, Theta, and Omega to describe them mathmatically. This is all well and good, and especially required if you are going to make the most out of a computationally complex program. Another efficiency is programmer efficiency. If you have a program to write, there are multiple way to write it in the same language. The more programmer efficient method is the one that does the same thing as other methods, but takes less time to program and is easier to understand.

Now that the introduction is over with I want to look at three different string implimentations, the classical C style strings, the C++ STL (Standard Template Library) string, and the QT style string. First to mention the C style string. With C style strings you deal directly with the data, sure there are a bunch of functions, to do things like copying, comparing, and other operations, but you have to be involved with things like allocating space for the string, keeping track of the length or using a function to calculate the length.

The STL string class is a step in the right direction. As far as allocation goes, you need to allocate a string class object, but you don't need worry about how long of a string you want to put in there. It will grow as needed. Concatenating strings is easy, just use the + operator or +=, same with setting one string equal to another, use the = operator. With C strings you have to worry about if it will fit, either you know it will fit and you don't check, you check and allocate a bigger string if it doesn't, or you take your chances.

The thing that gets the cake for QT's QString is a member function they provide called sprintf. sprintf you should recall (although not from this artical so far), is a commonly used function for C strings. For the C string it takes a pointer of where to put the result, a format string, and a variable list of arguments that are data. The sprintf function reads the format string copying it to the data pointer except where there is a special sequence which instructs it to grab one of the arguments and use that before returning to the format text. The QT string's sprintf does the same thing, except the destination is the string it was called from and the string will grow as big as required to store the result. Not only can you use the STL method of concatenation, which can get tedious, you can use the sprintf method. Time for a coding example to see what I'm talking about. This builds a string and stores it using a method available to each style string, assuming the variables name, type, date, phone, and about are already defined as C style strings.

C Style String

char * cstr;
int length=snprintf(NULL, 0,
	"<h1>Table of Values</h1>\n"
	"<table>\n"
	"<tr><th>Name<th>Type<th>Date<th>Phone\n"
	"<tr><td>%s<td>%s<td>%s<td>%s\n"
	"<h2>About %s<h2>\n"
	"%s\n",
	name, type, date, phone,
	name,
	about);
cstr=(char*)malloc(length+1);
sprintf(cstr,
	"<h1>Table of Values</h1>\n"
	"<table>\n"
	"<tr><th>Name<th>Type<th>Date<th>Phone\n"
	"<tr><td>%s<td>%s<td>%s<td>%s\n"
	"<h2>About %s<h2>\n"
	"%s\n",
	name, type, date, phone,
	name,
	about);
free(cstr);

STL Style String

string stlstr="<h1>Table of Values</h1>\n"
	"<table>\n"
	"<tr><th>Name<th>Type<th>Date<th>Phone\n"
	"<tr><td>";
	stlstr+=name;
	stlstr+="<td>";
	stlstr+=type;
	stlstr+="<td>";
	stlstr+=date;
	stlstr+="<td>";
	stlstr+=phone;
	stlstr+="\n<h2>";
	stlstr+="About ";
	stlstr+=name;
	stlstr+="<h2>\n";
	stlstr+=about;
	stlstr+="\n";

QT Style String

QString qtstr;
qtstr.sprintf(
	"<h1>Table of Values</h1>\n"
	"<table>\n"
	"<tr><th>Name<th>Type<th>Date<th>Phone\n"
	"<tr><td>%s<td>%s<td>%s<td>%s\n"
	"<h2>About %s<h2>\n"
	"%s\n",
	name, type, date, phone,
	name,
	about);

In the first case I use snprintf to calculate the length of the resulting string, allocated memory then used sprintf to store the string now that I know it has space. Duplicating the format string is error prone if you update one and forget about the other. I could have saved the format string to another pointer and used it in both the snprintf and sprintf.

The STL case just seems like a lot of unnecessary typing. Not to mention that in the C string case you have a pretty good idea what is going to be printed just looking at it, where you loose all the format layout with STL.

The QString is only two statements long compared to the five for C stype, or 14 for STL and is about as clear as it can be in C or C++. That doesn't even mention that the STL method may have to allocate more memory and copy the string each time it is appended to, although I don't know how it is written. I could have done the qt string in one statement,

QString qtstr = QString().sprintf(
...
but that is slightly less readable to me, and of no added value.

Another nice thing about the QT string is what I would call a disposible string something you can't do with either the C style string or STL style. That is build a string without using any variables and pass the string to a function. Say you have a function you want to call pdb.Exec that takes a const char * for the query that you need to build with codeExample being an integer represending the example you want to view, with QString you can do the following:

pdb.Exec( QString().sprintf("select * from example
where ide='%d'", codeExample));
How's that for slick? If you are only going to use a string once, why build it and then keep it around?

Using the STL string class or the QT QString isn't free, and although I don't have any executing time on either, I did time building them, this is under Linux on Debian with the 2.95.4 compiler, with the example program listed below. Just the C version took .8 seconds to build and the executable was 4KB stripped. Compiling both C and STL took 2 seconds and was 17KB stripped. The C and QT version took 3.4 seconds and was 6.5KB stripped. At least on Linux the STL comes with the C++ development library QT is shipped separately and won't be available everywhere. If the STL string were to include just the two features I listed above for QT I would switch back, but for now it QString for me. Reference links