Home

Strings

        

Fundamentals of Strings

 

Null-Terminated Strings

 

A string is a group of printable letters or symbols. The symbol can be used as a single character or some symbols can be combined to produce a word or a sentence. The symbols are aligned in the computer memory in a consecutive manner so the last symbol is the null character. Here is an example: M a t h e m a t i c s \0 Such a value is called a null-terminated string because the last symbol is the null-terminated character "\0".

When allocating space for such a string, the space must be provided as the number of its characters + 1. Like most other variables, to use a string, you can first declare a variable that would hold it. To declare a string variable, you can use the char data type and create an array of symbols. Here are two examples: char StrName[20]; char *Sentence; The easiest way to initialize one of these variables is to give it a value when the variable is declared. Once it has been initialized, such a variable can be used in any function that can take advantage of it. Here is an example:

void CExoView::OnDraw(CDC* pDC)
{
    char *StrName = "Euzhan Palcy";

    pDC->TextOut(20, 22, StrName, 12);
}

When a string variable has been initialized, the string the variable holds is called its value. In the example above, Euzhan Palcy is the string value, or simply the value, of the StrName variable. When writing applications for Microsoft Windows, you can also declare a string using the CHAR data type. Here is an example:

void CExoView::OnDraw(CDC* pDC)
{
    CHAR *StrName = "Euzhan Palcy";

    pDC->TextOut(20, 22, StrName, 12);
}

If you are writing for an international audience and involve unicode in your application, you can declare the string using the TCHAR data type:

void CExoView::OnDraw(CDC* pDC)
{
    TCHAR *StrName = "Euzhan Palcy";

    pDC->TextOut(20, 22, StrName, 12);
}

Alternatively, you can use _TCHAR to declare such a variable. Normally, to initialize a null-terminated string variable for an international audience, you should use the _T, the TEXT or the _TEXT macros. Here is an example:

void CExoView::OnDraw(CDC* pDC)
{
    char *StrName = _T("Euzhan Palcy");

    pDC->TextOut(20, 22, StrName, 12);
}

You can also initialize a string variable with a value that spans various lines. To do this, when creating the string, end each line with a double-quote and start the other with another double-quotes. Here is an example:

void CExerciseDlg::OnMsgBox() 
{
	// TODO: Add your control notification handler code here
	char Sentence[] = "The name you entered is not in our records.\n"
		              "If you think there is a mistake, please contact HR.\n"
		              "You can also send an email to humanres@functionx.com";
	MessageBox(Sentence);
}
 

The Standard string Class

The Standard Template Library (STL) provides a class that can be used for string manipulation. This class is called basic_string and it was type-defined as string. To use this class, on top of the file where you will need access to it, include the string library and call the std namespace. To do this, you would type:

#include string
using namespace std;

Therefore, to declare a variable using the STL's string class, use one of its constructors. For example, you can use the default constructor as follows:

string FirstName;

To initialize a string variable, you can provide its value between parentheses. Here is an example:

string FullName("Jules Andong"ť);

The STL's string class is not natively supported in MFC applications. Therefore, in order to use it, you must convert its value to a null-terminated string. To allow this, the string class provides the c_str() member function. Its syntax is:

const E *c_str() const;

Here is an example:

void CExoView::OnDraw(CDC* pDC)
{
	string StrName("Central African Republic");

	pDC->TextOut(20, 22, StrName.c_str(), 24);
}

The Length of a String The length of a string is the number of characters that the string contains. To get the length of a string declared using the char, the CHAR, the TCHAR, the _TCHAR or one of the Win32 API's data types, you can use the strlen() function. Its syntax is:

size_t strlen(const char *String);

This function returns the number of characters of the String argument. Here is an example:

void CExoView::OnDraw(CDC* pDC)
{
	char StrName[] = "Euzhan Palcy";
	int Len = strlen(StrName);

	pDC->TextOut(20, 22, StrName, Len);
}

To get the length of a string declared using the string class, call the length() member function. Its syntax is:

size_type length() const;

You can also get the same result by calling the size() method whose syntax is:

size_type size() const;

Here is an example:

void CExoView::OnDraw(CDC* pDC)
{
	string StrName("Central African Republic");

	int Len = StrName.length();
	pDC->TextOut(20, 22, StrName.c_str(), Len);
}

String Formatting

Formatting a string consists of telling the compiler how to adjust, before using such as displaying, the string. Imagine you declare a null-terminated string as follows:

char Represents[20];

To format a null-terminated string, you can call the sprintf() function. Its syntax is:

int sprintf(char* Buffer, const char* S, Arguments...);

This function takes at least two arguments but can take as manu as necessary. The first argument, Buffer, is a null-terminated string variable:

char Represents[20];
sprintf(Represents,

To display a value as part of the Buffer variable, provide the second argument starting it with a double-quote followed by a string if any, followed by the % sign, followed by one of the following characters: Character Type of Data Used for c char A single character d int Any signed decimal integer (int, short) i int Any signed decimal integer (int, short) o Signed Integers An unsigned octal integer u Unsigned Any unsigned decimal integer (unsigned, unsigned int) x Unsigned Any unsigned lowercase hexadecimal integer (abcdef) X Unsigned Any unsigned uppercase hexadecimal integer (ABCDEF) e double Scientific representation of a signed value used to display the lowercase exponent E double Scientific representation of a signed value used to display the uppercase exponent f double Representation of a floating point number with a specific number of characters to the right of the separator g double Representation of a number using either the e or the f format G double Representation of a number using either the E or the f format s String String representation S String String representation An example would be:

char Represents[20];
sprintf(Represents, "%f", );

If you want to display your own, unformatted words as part of the new string, you can type anything before the % operator or after the formatting character:

char Represents[20];
sprintf(Represents, "The number is %f", );

If you are formatting a floating point number, you can specify the number of digits to appear as the separator. To do this, type a period on the right side of the % symbol followed by a number. For example, to produce a number with a precision of 4 digits, you would type:

sprintf(Represents, "The number is %.4f", );

To create a longer or more advanced string, you can add as many combinations of % and characters as necessary. The % symbol used in the S argument is used as a place holder, informing the compiler that an external value will be needed for that position. To specify a value for a place holder, provide it as a third argument. Here is an example:

void CExerciseDlg::OnDraw(CDC* pDC)
{
	CExerciseDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	char Represents[20];
	double Number = 125.55;
	sprintf(Represents, "The number is %.4f", Number);
}

If you created more than one combination of % and character, you can provide a value for each, separated by a comma. Here is an example:

void CExerciseDlg::OnDraw(CDC* pDC)
{
	CExerciseDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	char FirstName[] = "Ferdinand";
	char LastName[]  = "Coly";
	char FullName[40];
	
	sprintf(FullName, "Full Name: %s %s", FirstName, LastName); 
}

After formatting the string, the Buffer argument holds the new string. You can then use it as you see fit. For example, you can pass it to another function such as displaying it on a view as follows:

void CExerciseDlg::OnDraw(CDC* pDC)
{
	CExerciseDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	char FirstName[] = "Ferdinand";
	char LastName[]  = "Coly";
	char FullName[40];
	
	sprintf(FullName, "Full Name: %s %s", FirstName, LastName);
	int Len = strlen(FullName);

	pDC->TextOut(20, 20, FullName, Len); 
}

Operations of Strings String Copy Copying a string is equivalent to assigning all of its characters to another string. After copying, both strings would have the same value. To copy a null-terminated string, you can use the strcpy() function. Its syntax is:

char *strcpy(char *strDestination, const char *strSource);

The strDestination argument is the target string. The strSource argument holds the value of the string that needs to be copied. During execution, the strSource value would be assigned to the strDestination variable. After execution, this function returns another string that has the same value as strDestination. Here is an example:

void CExerciseDlg::OnDraw(CDC* pDC)
{
	CExerciseDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	char Artist[] = _T("Arsene Wendt");
	char Producer[40];

	strcpy(Producer, Artist);

	int Len = strlen(Producer);	
	pDC->TextOut(20, 20, Producer, Len);
}

To make a copy of a string variable, you can use the assignment operator. The primary technique applied to this operator can be used to initialize a string variable declared using the default constructor. Here is an example:

void CCView1View::OnDraw(CDC* pDC)
{
	CCView1Doc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	string StrName = "Central African Republic";

	int Len = StrName.length();
	pDC->TextOut(20, 22, StrName.c_str(), Len);
}

Using the assignment operator, you can copy one string variable into another. To do this, simply assign one variable to another. Here is an example:

void CExerciseDlg::OnDraw(CDC* pDC)
{
	CExerciseDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	string Artist = _T("Arsene Wendt");
	string Producer;

	Producer = Artist;

	int Len = Producer.length();
	pDC->TextOut(20, 20, Producer.c_str(), Len);
}

Besides the assignment operator, to copy a string variable or to assign the value of one string to another, you can also use the string::assign() method to assign a string. It is provides in various syntaxes as follows:

basic_string& assign(const E *s);
basic_string& assign(const E *s, size_type n);
basic_string& assign(const basic_string& str, size_type pos, size_type n);
basic_string& assign(const basic_string& str);
basic_string& assign(size_type n, E c);
basic_string& assign(const_iterator first, const_iterator last);

Here is an example:

void CExerciseDlg::OnDraw(CDC* pDC)
{
	CExerciseDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	string Artist = _T("Arsene Wendt");
	string Producer;

	Producer.assign(Artist);

	int Len = Producer.length();
	
	pDC->TextOut(20, 20, Producer.c_str(), Len);
}

String Concatenation

String concatenation consists of adding one string to another. To add one null-terminated string to another, you can use the strcat() function. Its syntax is:

char *strcat(char *Destination, const char *Source);

The strcat() function takes two arguments. The second argument, Source, is the string to add to the right side of the first string, Destination. Here is an example:

void CExerciseDlg::OnMsgBox() 
{
	// TODO: Add your control notification handler code here
	static char Msg[] = "This application has performed an illegal operation ";
	strcat(Msg, "and it will be shut down");
	strcat(Msg, "\nDo you want to save the last changes you made to the current file?");
	const char Title[] = "Application Global Error";
	UINT Option = MB_YESNO | MB_ICONSTOP;

	::MessageBox(NULL, Msg, Title, Option);
}

Like the strcat() function, the strncat() function is used to append one string to another. The difference is that, while the strcat() considers all characters of the source string, the strncat() function allows you to specify the number of characters from the source string that you want to append to the destination string. This means that, if the source string has 12 characters, you can decide to append only a set number of its characters. The syntax of the strncat() function is:

char* strncat(char* Destination, const char* Source, int Number);

Besides the same arguments as the strcat() function, the Number argument is used to specify the number of characters considered from Source. To perform the concatenation, the compiler would count Number characters from left to right of the Source string. These characters would be added to the right of the Destination string. Here is an example:

void CExerciseDlg::OnDraw(CDC* pDC)
{
	CExerciseDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	char Make[]     = "Ford ";
	int LengthMake  = strlen(Make);
    	char Model[]    = "Explorer";
	int LengthModel = strlen(Model);

    	char *Car = strncat(Make, Model, 3);
	int LengthCar = strlen(Car);
    
	pDC->TextOut(10, 20, Make, LengthMake);
	pDC->TextOut(10, 40, Model, LengthModel);
	pDC->TextOut(10, 60, Car, LengthCar);
}

The string class provides its own mechanism to add two strings. It uses the addition operator. To do this, simply add one string value or variable to another string value or variable and assign the result to the target string variable. Here is an example:

void CExerciseDlg::OnDraw(CDC* pDC)
{
	CExerciseDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	string Make  = "Ford ";
    	string Model = "Explorer";

    	string Car = Make + Model;
	int LengthCar = Car.length();
    
	int LengthMake  = Make.length();
	int LengthModel = Model.length();

	pDC->TextOut(10, 10, Make.c_str(), LengthMake);
	pDC->TextOut(10, 30, Model.c_str(), LengthModel);
	pDC->TextOut(10, 50, Car.c_str(), LengthCar);
}

Alternatively, to add two strings, you can call the append() method. It comes in various versions as follows:

basic_string& append(const E *s);
basic_string& append(const E *s, size_type n);
basic_string& append(const basic_string& str,
    size_type pos, size_type n);
basic_string& append(const basic_string& str);
basic_string& append(size_type n, E c);
basic_string& append(const_iterator first, const_iterator last);

In the following example, we use the first versions that takes a string variable as argument and add the value of that argument to the right side of the string variable that called it. After this version executes, it modifies the value of the string that made the call:

void CExerciseDlg::OnDraw(CDC* pDC)
{
	CExerciseDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	string Make  = "Ford ";
    	string Model = "Explorer";

    	string Car = Make.append(Model);
	int LengthCar = Car.length();
    
	int LengthMake  = Make.length();
	int LengthModel = Model.length();

	pDC->TextOut(10, 10, Make.c_str(), LengthMake);
	pDC->TextOut(10, 30, Model.c_str(), LengthModel);
	pDC->TextOut(10, 50, Car.c_str(), LengthCar);
}

If you want to append only a specific number of characters, use the second version of the append() method. The Characters of a String Access to Characters As mentioned earlier, the characters of a null-terminated string are stored in an array. To access an individual character of a null-terminated string, use the square brackets operator. For example, if you had declared and initialized a string using

char FirstName[] = _T("Arsene");

you can access the third character using FirstName[2]; The strchr() function looks for the first occurrence of a certain character in a null-terminated string. Its syntax is:

char* strchr(const char* S, char c);

This function takes two arguments. The second argument, c, specifies what character to look for in the first argument, S, which is a string. If character c appears in string S, the function would return a new string whose value starts at the first occurrence of c in S. If the character c does not appear in the string S, then the function would return NULL. The strrchr() function examines a string starting at the end (right side) of the string and looks for the first occurrence of a certain character. Its syntax is:

char* strrchr(const char* S, char c);

The first argument is the string that needs to be examined. The function will scan string S from right to left. Once it finds the first appearance of the character c in the string, it would return a new string whose value starts at that first occurrence. If the character c does not appear in the string S, then the function would return NULL. Sub-Strings The strstr() function looks for the first occurrence of a sub-string in another string and returns a new string as the remaining string. Its syntax is:

char* strstr(const char* Main, const char *Sub);

The first argument of the function is the main string that would be examined. The function would look for the second argument, the Sub string appearance in the Main string. If the Sub string is part of the Main string, then the function would return a string whose value starts at the first appearance of Sub and make it a new string. If Sub is not part of the Main string, the function would return a NULL value.

The CString Class

 

Introduction

The MFC library provides its own data types and a class for string manipulation. The class is called CString. To declare a string with the CString class, you can use one of its constructors. To initialize a string when declaring it, you can pass a string to one of the following constructors:

CString(const unsigned char* psz);
CString(LPCWSTR lpsz);
CString(LPCSTR lpsz);

These constructors take a null-terminated string as argument. Once the variable has been declared, an amount of memory space is assigned for its use. If for any reason the memory or enough memory could not be allocated, an exception would occur. If the space allocated for the variable is higher than necessary, at any time, you can reduce it by calling the CString::FreeExtra() method. Its syntax is:

void FreeExtra();

String Initialization

To declare and initialize a CString variable, you can use one of the above constructors. Here is an example:

void CExerciseDlg::OnDraw(CDC* pDC)
{
	CExerciseDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	CString Term("Information Superhighway");

	pDC->TextOut(20, 20, Term);
}

The above constructors mainly allow you to supply a null-terminated string as the initial value of the variable. In fact, you can first declare a null-terminated C string and pass it as argument to the constructor to initialize the string. Here is an example:

void CExerciseDlg::OnDraw(CDC* pDC)
{
	CExerciseDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	const char *Ville("Antananarivo");
	CString Capital(Ville);

	pDC->TextOut(10, 20, Ville);
	pDC->TextOut(10, 40, Capital);
}

You can also create a string using the String Table and specifying its value. To initialize a CString variable for such a string, call the CString::LoadString() method. Its syntax is:

BOOL LoadString(UINT nID);

The nID argument is the identifier of the item created in the String Table The String and its Length After initializing a string, it assumes a length that represents its number of characters. To get the length of a string, you can call the CString::GetLength() method whose syntax is:

int GetLength( ) const;

However you have declared and initialized the CString variable using one of the above constructors, if you want to retrieve the value stored in the variable, you can call the CString::GetBuffer() method. Its syntax is:

LPTSTR GetBuffer(int nMinBufLength);

The nMinBufLength argument specifies the minimum number of characters to consider from the string. Here is an example:

void CExerciseDlg::OnDraw(CDC* pDC)
{
	CExerciseDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	CString Country("Cote d'Ivoire");
	const char *Area = Country.GetBuffer(2);

	pDC->TextOut(10, 10, Country);
	pDC->TextOut(10, 30, Area);
}

If you want to specify the number of characters to consider when retrieving the buffer, use the CString::GetBufferSetLength() method. Its syntax is:

LPTSTR GetBufferSetLength(int nNewLength);

The nNewLength argument specifies the new length of the buffer. To declare a CString variable that has a single character, use the following constructor:

CString(TCHAR ch, int nRepeat = 1);

The character can be included between single-quotes. Here is an example:

void CExoView::OnDraw(CDC* pDC)
{
	CExoDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	CString Letter('A');

	pDC->TextOut(20, 22, Letter);
}

If you want the character to be repeated more than once, you can pass a second argument as nRepeat that holds the number of times that the ch character must be repeated. Here is an example:

void CExerciseDlg::OnDraw(CDC* pDC)
{
	CExerciseDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	CString Letter('A');
	pDC->TextOut(20, 20, Letter);

	CString Character('$', 25);
	pDC->TextOut(20, 40, Character);
}
 

 

 
 
 
 

Working with Individual Characters

 

Character Indexing

The characters or symbols that compose a CString variable are stored in an array of characters. To get to the character or symbol at a specific position, you can use the square brackets, the same way you would proceed for an array. This is possible because the square bracket operator is loaded for the CString class:

TCHAR operator []( int nIndex ) const;

Like an array, the characters of a CString value are stored in a 0-based index, meaning the first character is at index 0, the second at 2, etc. Imagine you have a string declared and initialized as:

CString Capital(“Antananarivo”);

To get the 5th character of this string, you could write:

CString Fifth = Capital[4];

Here si an example:

void CExerciseDlg::OnDraw(CDC* pDC)
{
	CExerciseDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	CString Capital("Antananarivo");
	CString Fifth = Capital[4];

	pDC->TextOut(10, 20, Capital);
	pDC->TextOut(10, 40, Fifth);
}

Besides the square brackets, to access the character stored at a certain position in a string, you can call the GetAt(). Its syntax is:

TCHAR GetAt( int nIndex ) const;

Here is an example of using it:

void CExerciseDlg::OnDraw(CDC* pDC)
{
	CExerciseDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	CString Capital("Antananarivo");
	CString Fifth = Capital.GetAt(4);

	pDC->TextOut(10, 20, Capital);
	pDC->TextOut(10, 40, Fifth);
}

Character Insertion

As stated already, a CString value is in fact an array of characters. This allows you to locate a position in the string and change its character. To do this, you can use the SetAt() method. Its syntax is:

void SetAt(int nIndex, TCHAR ch);

Here is an example:

#include afxwin.h
#include iostream
using namespace std;

int main()
{
	CString Object("Wall");

	cout  "Object: " << (LPCTSTR)Object << endl;
	Object.SetAt(1, 'e');
	cout << "Name:   " << (LPCTSTR)Object << endl;

	return 0;
}

Finding a Character

Scanning a string consists of visiting or examining each one of its characters. One of the reasons you would do this is to look for a particular character that may be part of the string. To scan a string for a character, you can call the CString::Find() method. It is overloaded as follows:

int Find(TCHAR ch) const;
int Find(TCHAR ch, int nStart) const;

To look for a single character in the string, pass a character value or variable as argument. In this case, the string would be examined from the most left character to the right. If you want the scanning to start at a certain position instead of from the most left character, besides the character to look for, pass a second argument as nStart. If the character is found in the string, this method returns the position of its first occurrence. If you want the get the last occurrence of the character, call the ReverseFind() instead. Its syntax is:

int ReverseFind(TCHAR ch) const;

These two versions of the Find() method are used to find a particular character in a string. Alternatively, you can specify a group of characters and try to find, at least, any one of them in the string. This operation is performed using the FindOneOf() method. Its syntax is:

int FindOneOf(LPCTSTR lpszCharSet) const;

The lpszCharSet argument is passed as a string which is a group of characters in any order. If the compiler finds any character of the lpszCharSet argument in the string, it returns its position. If none of the lpszCharSet characters is in the string, this method returns –1.

Character Identification

Every time the user types a character in a text-based control, this is referred to as a keystroke. When performing data entry, even if the user presses two keys simultaneously (to enter an uppercase letter or to type a special character), only one character is entered at a time. You can find out what character the user had entered in your application using appropriate functions. Some functions are used to categorize the types of characters on the keyboard. The functions used for these validations are as follows:

Function Meaning
int isalpha(int c); Returns true if c is an alphabetic character. Otherwise, returns false
int islower(int c); Returns true if c is an alphabetic character in lowercase. Otherwise, returns false
int isupper(int c); Returns true if c is an alphabetic character in uppercase. Otherwise, returns false
int isdigit(int c); Returns true if c is a digit. Otherwise, returns false
int isxdigit(int c); Returns true if c is a hexadecimal digit. c must be one of the following 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, A, B, C, D, E, or F. Otherwise, returns false
int isalnum(int c); Returns true is c is between 0 and 9 or if c is between a and z or if c is between A and Z. Otherwise, returns false
int isascii(int c); Returns true if c is an ASCII character. Otherwise, returns false
int ispunct(int c); Returns true if c is a punctuation character. Otherwise, returns false
int isprint(int c); Returns true if c is a printable character. Otherwise, returns false
int isgraph(int c); Returns true if c is a printable character and is not an empty space
int isspace(int c); Returns true if c is an empty space

Removing Characters

Besides the CString::SetAt() method, you can also use the Replace() method to replace a character of the string with another character. The syntax of the Replace() method is:

int Replace(TCHAR chOld, TCHAR chNew);

The Replace() method replaces each occurrence of the chOld argument. Whenever it finds it, it replaces it with the chNew character. Sub Strings Introduction A sub string is a character or a group of characters that is part of another string. Therefore, to create a string, you must first have a string as basis. When declaring and initializing a CString variable, although you can provide as many characters as possible, you may want the variable to actually hold only part of the string value. Based on this, to create a sub string when declaring a CString variable, you can use the following constructor:

CString(LPCTSTR lpch, int nLength);

When using this constructor, provide the whole string as a the null-terminated lpch string. To specify the number of characters for the sub string variable, provide an integer value for the nLength argument. Here is an example:

void CExerciseDlg::OnDraw(CDC* pDC)
{
	CExerciseDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	CString CofV = "Commonwealth of Virginia";
	CString Sub(CofV, 12);

	pDC->TextOut(10, 20, Sub);
}

As you may realize from this constructor, its sub string is built from the left side of the string and starts counting characters towards the right. Once it reaches the nLength number of characters, it creates the new string and ignores the characters beyond nLength. If the string has already been initialized and you want to create a sub string made of some characters from its left side, you can call the CString::Left() method. Its syntax is:

CString Left(int nCount) const;

This method starts counting characters from the left to nCount characters and returns a new string made of those nCount characters. Here is an example:

void CExerciseDlg::OnDraw(CDC* pDC)
{
	CExerciseDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	CString Common = "Commonwealth of Virginia";
	CString Sub = Common.Left(12);

	pDC->TextOut(10, 20, Sub);
}

As the Left() method considers the characters from the left position, if you want the characters of the end of a string, you can call the CString::Right() to create a new string. Its syntax is:

CString Right(int nCount) const;

Here is an example:

void CExerciseDlg::OnDraw(CDC* pDC)
{
	CExerciseDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	CString Common = "Commonwealth of Virginia";
	CString Sub = Common.Right(8);

	pDC->TextOut(10, 20, Sub);
}

Alternatively, you can create a sub string using any range of characters from a string. To do this, call the CString::Mid() method whose syntaxes are:

CString Mid(int nFirst) const;
CString Mid(int nFirst, int nCount) const;

To create the sub string start from any character in the string, use the first version whose nFirst argument specifies where the new string would start. In this case, the method would return a string made of characters from the nFirst position to the last character of the string. To create a sub string using a specific number of characters, use the second version. The nFirst argument specifies where the new string would start. The nCount argument is the number of characters that would be used from the main string to create the new string. Finding a Sub String To scan a string for a group of characters, you can call the following versions of the CString::Find() method:

int Find(LPCTSTR lpszSub) const;
int Find(LPCTSTR pstr, int nStart) const;

To find a sub string in a string, pass the desired sub string as the lpszSub argument. As done with the single character, you can specify the position to start looking by providing a second argument as nStart and use the fourth version of this method. If the sub string is found, this method returns the position of its first character in the string. If the character or the sub string is not found, the method returns –1. Character and String Removal Besides the CString(LPCTSTR lpch, int nLength) constructor, the Left(), the Mid(), and the Right() method, another technique you can use to create a sub string consists of deleting characters from an existing string. This can be done by calling the CString::Delete() method. Its syntax is:

int Delete(int nIndex, int nCount = 1);

The nIndex argument specifies the first character of the range. If you pass only this argument, only the character at position nIndex will be deleted. If you want to delete more than one character, pass the desired number as the nCount argument. If the value of nCount is higher than the remaining number of characters from nIndex position, all characters to the right will be deleted. If you want to remove all occurrences of a particular character in a string, you can call the Remove() method. Its syntax is:

int CString::Remove(TCHAR ch);

This method scans the string looking for the ch character. Whenever it finds it, it deletes it. This operation is performed using case sensitivity. This means that only the exact match with case of ch would be deleted. Replacing String Occurrences Besides the CString::SetAt() method, you can also use the Replace() method to replace a character of the string with another character. The syntaxes of the Replace() method are:

int Replace(TCHAR chOld, TCHAR chNew);
int Replace(LPCTSTR lpszOld, LPCTSTR lpszNew);

The Replace() method replaces each occurrence of the chOld argument. Whenever it finds it, it replaces it with the chNew character. Here is an example:

void CExerciseDlg::OnMsgBox() 
{
	// TODO: Add your control notification handler code here
	CString Msg("The name you entered is not in our records.\n"
		     "If you think there is a mistake, please contact HR.\n"
		     "You can also send an email to humanres@functionx.com");
	Msg.Replace("HR", "Human Resources");
	Msg.Replace(".com", ".net");

	MessageBox(Msg, "Failed Logon Attempt");
}

String Formatting

The sprintf() function we reviewed earlier is provided by the C/C++ language. The CString class provides its own function for formatting a string. This is done using the CString::Format() whose syntax are:

void Format(LPCTSTR lpszFormat, ...);
void Format(UINT nFormatID, ...);

The lpFormat argument follows the exact same rules as the second argument to the sprintf() function seen earlier. The nFormatID argument is an identifier that can have been created using the String Table The third and subsequent arguments follow the same rules as the … argument of the sprintf() function. There are many examples of the CString::Format() method in our lessons. While the sprintf() function and the CString::Format() methods follow the order of the %Character combinations to format a message, the CString class provides a method that can also be used to format a string but it allows you to list the parameters if the order of your choice. Here is an example:

void CExerciseDlg::OnMsgBox() 
{
	// TODO: Add your control notification handler code here
	const char *DeptToContat = "Human Resources";
	const char  EmailContact[] = "humanres@functionx.net";
	const int   StartShift = 8;
	const int   EndShift   = 6;
	CString Msg;
	
	Msg.Format("The name you entered is not in our records.\n"
		     "If you think there is a mistake, please contact %s "
		     "every week day from %d AM to %d PM.\n"
		     "You can also send an email to %s",
		     DeptToContat, StartShift, EndShift, EmailContact);

	MessageBox(Msg, "Failed Logon Attempt");
}

Operations on Strings About Constructing a String

The constructors we have used so far were meant to initialize a string when declaring it. Normally, if you do not have an initial value when declaring the string variable, you can use the default constructor:

CString();

The default constructor is used to declare an empty string that can be initialized later on. If the variable already contains a value but you want it to be empty, you can call the CString::Empty() method. Its syntax is:

void Empty();

This method removes all characters, if there are any, from a string variable and restores the memory it was using. If you think the string contains empty spaces to its left side and you think this could compromise an operation on the string, to remove such empty spaces, call the TrimLeft() method whose syntax is:

void TrimLeft();

To remove empty spaces from the right side of a string, call the TrimRight() method. Its syntax is:

void TrimRight();

If at one time you want to find out whether a string is empty or not, call the CString::IsEmpty() method. Its syntax is:

BOOL IsEmpty() const

This method returns TRUE if the string is empty. Otherwise, it returns FALSE. String Assignment We saw earlier that you can declare an empty CString variable using the default constructor. To initialize it, you can assign it a string value of your choice. Here is an example:

void CExoView::OnDraw(CDC* pDC)
{
	CExoDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	CString Term = "Information Superhighway";

	pDC->TextOut(20, 22, Term);
}

String Copy

Making a copy of a string consists of providing its value to another string. If you already have a CString initialized and you want to copy its value into another CString variable, you can use the following constructor:

CString(const CString& stringSrc);

This constructor is used to declare a CString variable and provide it with the value of another CString variable. Here is an example:

void CExerciseDlg::OnDraw(CDC* pDC)
{
	CExerciseDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	CString Term = "Information Superhighway";
	CString Description(Term);

	pDC->TextOut(20, 22, Description);

}

Strings and Their Cases

In US English, the following alphabetical letters are referred to as lowercase a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z. Their equivalents in uppercase are A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z. The digits 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, and the other characters are considered “as is”. To convert a lowercase CString variable to uppercase, you can call the MakeUpper() method. Its syntax is:

void MakeUpper();

When executed, this method would examine each character of the string. If a character is a lowercase letter, it would be converted to uppercase. If a character is already in uppercase, it be left in uppercase. If the character is not a letter, it would be left intact. On the other hand, to convert the characters of a string to lowercase, call the MakeLower() method. Its syntax is:

void MakeLower();

If a character is an uppercase letter, it would be converted to lowercase. If a character is already in lowercase, it be left in lowercase. The digits and other characters are left “as is”.

String Comparisons

 

Case Sensitivity

String comparison consists of finding out whether the values of two strings are identical or not. Toperform such a comparison, the CString class provides the Collate() method. Its syntax is:

int Collate(LPCTSTR lpsz) const;

The string that called this method is compared with the lpsx argument, character by character and with regards to the case of each combination of characters. To perform the comparison, this method refers to the Regional Settings of Control Panel on the user's computer concerning the numeric, the date, the time, and the currency systems used. The comparison starts with the left character for most Latin languages, including US English:

  • If the character at the first position ([0]) of the string (the string that called this method) has the same ANSI value as the first character at position [0] of the other string (the lpsz argument), the method skips this position and continues the comparison with the next position of characters. If all characters of the corresponding positions of both strings are exactly the same as set on the ANSI map, this method returns 0, meaning the strings are equal
  • If a character at one position x has an ANSI value higher than the corresponding character at the same position x on the other string, the method returns a positive value and stops the comparison
  • If a character at one position x has an ANSI value lower than the corresponding character at the same position x on the other string, the method returns a negative value and stops the comparison Here is an example:
void CExerciseDlg::OnDraw(CDC* pDC)
{
	CExerciseDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	CString CS = "Charles Stanley";
	CString AS = "charles Stanley";

	int Result = CS.Collate(AS);

	if( Result > 0 )
		pDC->TextOut(10, 20, "Charles Stanley is Higher than charles Stanley");
	else if( Result == 0 )
		pDC->TextOut(10, 20, "Charles Stanley and charles Stanley are equal");
	else // if( Result < 0 )
		pDC->TextOut(10, 20, "Charles Stanley is Lower than charles Stanley");
}

Besides the Collate() method, the CString class provides the Compare() method to perform a case-sensitive comparison of characters of two strings. Its syntax is:

int Compare(LPCTSTR lpsz) const;

This method compares the character at a position x to the character at the same position x of the other, lpsz, string. The approach used to perform the comparisons is the same with the difference that the Compare() method does not refer the user's Regional Settings.

Case Insensitivity

As seen above, the Collate() method considers the cases of characters during comparison and refers to the Regional Settings of the user. If you just want a simple comparison to find if two strings are identical regardless of the cases of their characters, you can call the CString::CollateNoCase() method. Its syntax is:

int CollateNoCase(LPCTSTR lpsz) const;

This member function considers that the alphabet is made of characters of a single case, implying that the character a is exactly the same as the character A. The other symbols and digits are considered “as is”. It proceeds as follows:

  • The character at a position x of one string is compared with the corresponding character at the same position on the other string. If both characters are the same, the comparison continues with the next character. If all characters at the same positions on both strings are the same and the strings have the same length, this method returns 0, indicating that the strings are identical:
void CExerciseDlg::OnDraw(CDC* pDC)
{
	CExerciseDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	CString CS = "Charles Stanley";
	CString AS = "charles Stanley";

	int Result = CS.CollateNoCase(AS);

	if( Result > 0 )
		pDC->TextOut(10, 20, "Charles Stanley is Higher than charles Stanley");
	else if( Result == 0 )
		pDC->TextOut(10, 20, "Charles Stanley and charles Stanley are equal");
	else // if( Result < 0 )
		pDC->TextOut(10, 20, "Charles Stanley is Lower than charles Stanley");
}
  • If a character at one position x has an ordered value higher than the corresponding character at the same position x on the other string, the method returns a positive value and stops the comparison
  • If a character at one position x has an ordered value lower than the corresponding character at the same position x on the other string, the method returns a negative value and stops the comparison

Here is an example:

void CExerciseDlg::OnDraw(CDC* pDC)
{
	CExerciseDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	CString YS = "Jeremy Stanley";
	CString IS = "Jeremie Andy";

	int Result = YS.CollateNoCase(IS);

	if( Result > 0 )
		pDC->TextOut(10, 20, "Jeremy Stanley is Higher than Jeremie Stanley");
	else if( Result == 0 )
		pDC->TextOut(10, 20, "Jeremy Stanley and Jeremie Stanley are equal");
	else // if( Result < 0 )
		pDC->TextOut(10, 20, "Jeremy Stanley is Lower than Jeremie Stanley");
}

Alternatively, to perform case-insensitive string comparison on CString variables, you can use the CompareNoCase() method. Its syntax is:

int CompareNoCase(LPCTSTR lpsz) const;

The CompareNoCase() method does not refer to the user's Regional Settings when performing its comparison. Besides the CollateNoCase() and the CompareNoCase() methods, the CString class provides an easier and probably more familiar means of performing value comparisons. Character insensitive comparisons on CString variables can be performed using Boolean operators ==, !=, <, <=, >, >=. Any of these operators can be applied on two CString variables or a combination of a CString and a null-terminated string variables. The operators are overloaded as follows:

BOOL operator ==( const CString& s1, const CString& s2 );
BOOL operator ==( const CString& s1, LPCTSTR s2 );
BOOL operator ==( LPCTSTR s1, const CString& s2 );
BOOL operator !=( const CString& s1, const CString& s2 );
BOOL operator !=( const CString& s1, LPCTSTR s2 );
BOOL operator !=( LPCTSTR s1, const CString& s2 );
BOOL operator <( const CString& s1, const CString& s2 );
BOOL operator <( const CString& s1, LPCTSTR s2 );
BOOL operator <( LPCTSTR s1, const CString& s2 );
BOOL operator >( const CString& s1, const CString& s2 );
BOOL operator >( const CString& s1, LPCTSTR s2 );
BOOL operator >( LPCTSTR s1, const CString& s2 );
BOOL operator <=( const CString& s1, const CString& s2 );
BOOL operator <=( const CString& s1, LPCTSTR s2 );
BOOL operator <=( LPCTSTR s1, const CString& s2 );
BOOL operator >=( const CString& s1, const CString& s2 );
BOOL operator >=( const CString& s1, LPCTSTR s2 );
BOOL operator >=( LPCTSTR s1, const CString& s2 );

These operators work exactly as you are used to dealing with conditional statements except that the operands must be string values.

 
 
   
 

Home