The AnsiString class (or String, for short) that comes with C++Builder is designed to work and play well with VCL. However, the documentation for the String class is somewhat lacking--OK, it's terrible. We'll do our best to remedy that situation in this article by describing the most commonly used String class operators, constructors, and functions. (We won't deal with wide-character support functions, however.)
The String class includes constructors to let you create a String object from different data types. Table A shows the constructors and provides an example of each constructor's use.
Table A: String class constructors
|AnsiString();||Constructs an empty String object||String s;|
const char* src);
|Constructs a String
object from a char* (a character array)
|String ("This is a test");
char* buff = "Hello";
const AnsiString& src);
|Constructs a String object from another String object||String s1 = "String One";
const char* src,
unsigned char len);
|Constructs a String object from a char* with the length specified in len||String s("", 255);|
|AnsiString(char src);||Constructs a String object from a char data type||char c = '\n';
|AnsiString(int src);||Constructs a String object from an int data type||int x = 200;
|AnsiString(double src);||Constructs a String object from a double data type||double d = 24.53;
Table B: String class operators
|=||Assignment||s = "Test";|
|+||Concatentation||s = path + filename;|
|==||Equality||if (s == "Hello World")...|
|!=||Inequality||if (s != "Logon"). . .|
|<||Less than||if (s < "a")...|
|>||Greater than||if (s > "z")...|
|<=||Less than or =||if (s <= "1")...|
|>=||Greater than or =||if (s > = "10")...|
|Label1->Caption = s;|
The String class's many functions let you manipulate strings just about any way you choose. We'll describe the functions you'll probably use most often with the String class.
The AnsiCompare() function compares one string to another, using the following syntax:
int AnsiCompare(const AnsiString& rhs);The return value will be -1 if the string is less than rhs, 1 if the string is greater than rhs, and 0 if the string's contents equal rhs. You don't use this function to test for equality, but rather to sort strings. For example,
String s1 = "Adam";
int result = s1.AnsiCompare("Bob");
In this case, result will be -1 because A is less than B. You can also use the < and > operators to sort strings.
The AnsiCompareIC() function compares one string to another without regard to case sensitivity, using the following syntax:
int AnsiCompareIC(const AnsiString& rhs);
The AnsiLastChar() function uses the syntax
char* AnsiLastChar();to return the last character in a string. For example, the code
String s = "This is a test";displays t in the Label component.
Label1->Text = s.AnsiLastChar();
char* __fastcall c_str();
You must use this function any time you need a char pointer to the string's text.
For example, the Windows API function DrawText() requires a pointer to a character buffer. In such a case, you'll need to use the c_str() function as follows:
DrawText(Canvas->Handle,The c_str() function is also handy if you need to use a String object with the C-style string manipulation functions, such as strcpy().
s.c_str(), s.Length(), &rect, DT_CALCRECT);
void Delete(int index, int count);In this example,
String s = "This is a test";the label will display is a test, since the code deletes the first five characters of the original string. Remember that the string indexing is 1-based, not 0-based.
Label1->Caption = s;
void Insert(const AnsiString& str, int index);to insert the string str starting at position index. For example, if you use the code
String s = "data.txt";s will contain the text c:\myprog\data.txt after the call to Insert().
bool IsEmpty();The function returns true if the string is empty and false if the string contains text.
bool IsPathDelimiter(int index);IsPathDelimiter() could be useful for traversing a string containing a path and filename.
int LastDelimiter(const AnsiString& delimiters);You can use this function to find the last character specified in delimiters.
For instance, to extract just the path from a string containing a path and filename, you could use these lines:
String s = "c:\\myprog\\data.txt";This code finds the last backslash in the string and then deletes everything from the beginning of the string to that position.
int pos = s.LastDelimiter("\\");
int Length();The returned value will be the length of the text in the string, unless you've modified the length using the SetLength() function. The returned value doesn't include a terminating null character.
For example, you could use these lines:
String s = "Hello World";In this case, length will contain the value 11, since there are 11 actual characters in the text string.
int length = s.Length();
AnsiString LowerCase();This function converts the string to lowercase and returns the converted string. (However, it doesn't modify the text in the string object.) LowerCase() is useful for converting a string to lowercase (such as strings containing filenames) or for comparing two strings regardless of case.
For example, in the line
if (s1.LowerCase() == s2.LowerCase()) DoSomething();the code doesn't modify the text in the strings--it simply compares the strings' lowercase representations for equality. If you actually want to convert a string to lowercase you'll need to use code like the following:
String s = "TEST";
s = s.LowerCase();
int Pos(const AnsiString& subStr);It returns the position of the string passed in subStr. If the string can't be found, then Pos() returns 0. The AnsiPos() functions perform exactly the same way.
The following code finds the position of a substring within the target string:
String s = "This is a test";This code will display the text Pos: 11 in the label component. Again, remember that the string index is 1-based, not 0-based.
int p = s.Pos("test");
Label1->Caption = "Pos: " + String(p);
void SetLength(int newLength);Normally, the String class dynamically allocates space for the text in the string as needed, so there's rarely any reason to set the length yourself. For example:
String s; // length is 0If you set the length to a value less than the current length of the text in the string, then the string will be truncated.
s = "test"; // length is 4
s.SetLength(50); // length is 50
s = "new string"; // length is 10
AnsiString StringOfChar(char ch, int count);This function creates a string filled with the character ch, with a length of count. For example, the following code fills a string with 20 spaces:
AnsiString SubString(int index, int count);It returns a substring of the string object starting at index and having a length of count. For example, if you execute the code
String s = "My name is BillyBob";then the value of sub will be BillyBob.
String sub = s.SubString(12, 8);
double ToDouble();If the string can't be converted to a double, then VCL throws an EConvertError exception. Here's an example:
String s = "123.456";In order for the string to be converted, it must contain a valid floating-point number and no alpha characters.
double d = s.ToDouble();
d *= .3;
int ToInt();For example,
String s = "123";If the string can't be converted, then VCL throws an EConvertError exception.
int i = s.ToInt();
int ToIntDef(int defaultValue);If the string can't be converted, then the function returns the value supplied in defaultValue; VCL doesn't throw an exception.
AnsiString Trim();The Trim() function removes both leading and trailing spaces, TrimLeft() removes leading spaces, and TrimRight() removes only trailing spaces. These functions don't modify the text in the string object.
In this example,
String editText = Edit1->Text;Properties such as Caption, Title, and Text are String properties. As a result, you can condense the example code to a single line:
editText = editText.Trim();
String editText = Edit1->Text.Trim();
AnsiString UpperCase();the string's text isn't modified as in the example
s = s.UpperCase();
AnsiString CurrToStr(Currency value);which doesn't change the string object for which you call it, but rather formats and returns a string. For example, the lines
String s;won't modify the String object s.
c *= 1.06; // add sales tax
Label1->Caption = s.CurrToStr(c);
AnsiString CurrToStrF(Currency value, TStringFloatFormat format, int digits);It converts a currency value to a string, applies formatting, and returns the string. The lines
String s;display the text $21.15 in the label. The text is formatted for currency, including the dollar sign and two decimal places.
c *= 1.06; // add sales tax
Label1->Caption = s.CurrToStrF(c, AnsiString::sffCurrency, 2);
AnsiString FloatToStrF(The resulting string is based on the format, precision, and digits parameters. For example, the lines
long double value, TStringFloatFormat format,
int precision, int digits);
String s;format the given floating point value in scientific notation using eight-digit precision.
float f = 2219.3446237795;
Label1->Caption = s.FloatToStrF(f,
AnsiString::sffExponent, 8, 0);
AnsiString Format(const AnsiString& format,const TVarRec *args, int size);
This function works in a way similar to the sprintf() and wsprintf() functions in C++. For example, the lines
String s = Format("%s%d, %d",display the string Values: 10, 20 in the label. Notice that the OPENARRAY macro passes the values to the Format() function. This process is necessary because C++ doesn't have open arrays--however, AnsiString::Format() calls the VCL version of Format(), which takes an open array as a parameter.
OPENARRAY(TVarRec, ("Values: ", 10, 20)));
Label1->Caption = s;
The Format() function is one of the few cases in which Pascal and C++ just don't work well together. You can use one of two alternative methods for building the string from the previous example:
// example 1In my humble opinion, these methods are easier to use than the Format() function.
sprintf(buff, "Value: %d, %d", 10, 20);
String s = buff;
// example 2
String s = "Value: " + String(10) + ", " + String(20);
AnsiString FmtLoadStr(int ident, const TVarRec *args, int size);loads the string resource ident and formats it according to the value of the args parameter. See the descriptions of Format() and LoadStr() for more information.
bool IsDelimiter(const AnsiString& delimiters, int index);The function returns true if the character at index matches one of the characters in the string delimiters. Here's an example:
String s = "c:\\myprog\\data.txt";The delimiters parameter can be a string of several delimiters you want to test against. For instance, if you wanted to check to see whether the character at position 10 was a space, a minus sign, a plus sign, a comma, or a dollar sign, you'd use this code:
if (s.IsDelimiter("\\", 3)) DoSomething();
String s = "This is a string";The LoadStr() function loads a string resource using the following syntax:
bool test = s.IsDelimiter(" -+,$", 10);
AnsiString LoadStr(int ident);Of course, you must have a string table resource bound to your executable program, as does the following example:
s = s.LoadStr(100); //load string with ID of 100
// method 1I suspect that Borland put these functions into the AnsiString class at some early point in C++Builder's development, then forgot them later, when they were no longer necessary. Regardless, they're part of the AnsiString class and they're useful functions, so we've listed them here.
s = s.LoadStr(ID_STRING1);
// method 2
String s = LoadStr(ID_STRING1);
Kent Reisdorph is a editor of the C++Builder Developer's Journal as well as director of systems and services at TurboPower Software Company, and a member of TeamB, Borland's volunteer online support group. He's the author of Teach Yourself C++Builder in 21 Days and Teach Yourself C++Builder in 14 Days. You can contact Kent at email@example.com.