August 1997

An AnsiString class reference

by Kent Reisdorph

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.)

Constructors

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
ConstructorDescriptionExample
AnsiString();Constructs an empty String objectString s;
AnsiString(
const char* src);
Constructs a String
object from a char* (a character array)
String ("This is a test");
char* buff = "Hello";
String s2(buff);
AnsiString(
const AnsiString& src);
Constructs a String object from another String objectString s1 = "String One";
String s2(s1);
AnsiString(
const char* src,
unsigned char len);
Constructs a String object from a char* with the length specified in lenString s("", 255);
AnsiString(char src);Constructs a String object from a char data typechar c = '\n';
String lf(c);
AnsiString(int src);Constructs a String object from an int data typeint x = 200;
String s(x);
AnsiString(double src);Constructs a String object from a double data typedouble d = 24.53;
String s(d);

Operators

Table B shows the String operators and gives an example of each. These operators let you perform operations on strings using common-sense syntax rather than relying on cryptic function names.

Table B: String class operators
Operator Description Example
= 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")...
[ ] Index
Label1->Caption = s[10];

Primary functions

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.

AnsiCompare()

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.

AnsiCompareIC()

The AnsiCompareIC() function compares one string to another without regard to case sensitivity, using the following syntax:

int AnsiCompareIC(const AnsiString& rhs);

AnsiLastChar()

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";
Label1->Text = s.AnsiLastChar();
displays t in the Label component.

c_str()

The c_str() function returns a pointer to the character array used to hold the string's text. It uses this syntax:
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,
s.c_str(), s.Length(), &rect, DT_CALCRECT);
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().

Delete()

The Delete() function deletes count characters from the string beginning at index. The function's syntax is as follows:
void Delete(int index, int count);
In this example,
String s = "This is a test";
s.Delete(1, 5);
Label1->Caption = s;
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.

Insert()

The Insert() function uses the syntax
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.Insert("c:\\myprog\\", 1);
s will contain the text c:\myprog\data.txt after the call to Insert().

IsEmpty()

The IsEmpty() function has this syntax:
bool IsEmpty();
The function returns true if the string is empty and false if the string contains text.

IsPathDelimiter()

The IsPathDelimiter() function returns true if the character at the specified index is a backslash and false if it isn't. The function's syntax is as follows:
bool IsPathDelimiter(int index);
IsPathDelimiter() could be useful for traversing a string containing a path and filename.

LastDelimiter()

The LastDelimiter() function uses the following syntax:
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";
int pos = s.LastDelimiter("\\");
s.Delete(1, pos);
This code finds the last backslash in the string and then deletes everything from the beginning of the string to that position.

Length()

The Length() function returns the number of characters in the string. Its syntax is:
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";
int length = s.Length();
In this case, length will contain the value 11, since there are 11 actual characters in the text string.

LowerCase()

The LowerCase() function uses the syntax
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();

Pos()

The Pos() function uses the following syntax:
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";
int p = s.Pos("test");
Label1->Caption = "Pos: " + String(p);
This code will display the text Pos: 11 in the label component. Again, remember that the string index is 1-based, not 0-based.

SetLength()

You can use the SetLength() function to set the length of the buffer holding the string object's text. Its syntax is as follows:
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 0
s = "test"; // length is 4
s.SetLength(50); // length is 50
s = "new string"; // length is 10
If you set the length to a value less than the current length of the text in the string, then the string will be truncated.

StringOfChar()

The StringOfChar() function has the following syntax:
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:

String s; s = s.StringOfChar(' ', 20); SubString()

The SubString() function uses this syntax:
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";
String sub = s.SubString(12, 8);
then the value of sub will be BillyBob.

ToDouble()

The ToDouble() function converts a string to a double and returns the result. The syntax is simply
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";
double d = s.ToDouble();
d *= .3;
In order for the string to be converted, it must contain a valid floating-point number and no alpha characters.

ToInt()

The ToInt() function converts a string to an integer value and returns the result. The syntax is as follows:
int ToInt();
For example,
String s = "123";
int i = s.ToInt();
If the string can't be converted, then VCL throws an EConvertError exception.

ToIntDef()

The ToIntDef() function converts a string to an integer value and returns the result. Its syntax is
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.

Trim(), TrimLeft(), TrimRight()

The three Trim functions trim blank spaces from a string object and return the result, using the following syntaxes:
AnsiString Trim();
AnsiString TrimLeft();
AnsiString TrimRight();
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;
editText = editText.Trim();
Properties such as Caption, Title, and Text are String properties. As a result, you can condense the example code to a single line:
String editText = Edit1->Text.Trim();

UpperCase()

The UpperCase() function converts a string to upper- case and returns the result. In the syntax
AnsiString UpperCase();
the string's text isn't modified as in the example
s = s.UpperCase();

Other functions

Now, let's take a look at some useful utility functions. You may use these functions from time to time in your work with the String class.

CurrToStr()

The CurrToStr() function converts a currency value to a string and returns the string. The function uses the syntax
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;
Currency c(19.95);
c *= 1.06; // add sales tax
Label1->Caption = s.CurrToStr(c);
won't modify the String object s.

CurrToStrF()

The CurrToStrF() function uses this syntax:
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;
Currency c(19.95);
c *= 1.06; // add sales tax
Label1->Caption = s.CurrToStrF(c, AnsiString::sffCurrency, 2);
display the text $21.15 in the label. The text is formatted for currency, including the dollar sign and two decimal places.

FloatToStrF()

The FloatToStrF() function formats and returns a floating point number, using this syntax:
AnsiString FloatToStrF(
long double value, TStringFloatFormat format, 
int precision, int digits);
The resulting string is based on the format, precision, and digits parameters. For example, the lines
String s;
float f = 2219.3446237795;
Label1->Caption = s.FloatToStrF(f, 
AnsiString::sffExponent, 8, 0);
format the given floating point value in scientific notation using eight-digit precision.

Format()

The Format() function builds a string using a format string and the supplied arguments. The syntax is as follows:

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",
OPENARRAY(TVarRec, ("Values: ", 10, 20)));
Label1->Caption = s;
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.

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 1
char buff[20];
sprintf(buff, "Value: %d, %d", 10, 20);
String s = buff;

// example 2
String s = "Value: " + String(10) + ", " + String(20);
In my humble opinion, these methods are easier to use than the Format() function.

FmtLoadStr()

The FmtLoadStr() function is a combination of the Format() and LoadStr() functions. The syntax
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.

IsDelimiter()

The IsDelimiter() function uses this syntax:
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";
if (s.IsDelimiter("\\", 3)) DoSomething();
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:
String s = "This is a string";
bool test = s.IsDelimiter(" -+,$", 10);
LoadStr()
The LoadStr() function loads a string resource using the following syntax:
AnsiString LoadStr(int ident);
Of course, you must have a string table resource bound to your executable program, as does the following example:
String s;
s = s.LoadStr(100); //load string with ID of 100

Poor class design?

Note that the CurrToStr(), CurrToStrF(), FloatToStrF(), Format(), FormatFloat(), FrmtLoadString(), and LoadStr() functions really don't belong in the AnsiString class at all. They don't operate on the string object for which you call them, nor do they use the string object in any way. In addition, these functions are provided as standalone functions in the VCL Sysutils unit. It's always easier to use the standalone version of these functions rather than the AnsiString version, as shown in these two examples:
// method 1
String s;
s = s.LoadStr(ID_STRING1);

// method 2
String s = LoadStr(ID_STRING1);
I 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.

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 editor@bridgespublishing.com.