Strings



Strings are part of the C/C++ Standard Library. In the original ANSI Standard C developed by Brian Kernighan and Dennis Ritchie "strings" were implemented as character arrays using the null terminator ('\0') to mark the end of a string.

In order to have addess to all of the string functions of ANSI Standard C you must...

       #include <string.h> // Gets only the ANSI standard C functions

Most used functions from ANSI Standard C

Sample Code

#include <cstring>
#include <iostream>

using namespace std;

int main(int argc, char **argv)
{
	char str1[64];
	char str2[32] = " With a demo of strcat().";
	//  DEMONSTRATION 1:  strcpy and strncpy
	strcpy(str1, "This is a test string.");
	cout << "\t str1 = " << str1 << endl << endl;
	// Copy a string into str1 using strncpy
	strncpy(str1, "ABCDEFGHIJ", 5);
	cout << "\t str1 = " << str1 << endl << endl;
	cout << "Note that strncpy just overwrote the first 5 characters of str1\n";
	cout << "   which were \"ABCDE\" without adding a NULL terminator, thus\n";
	cout << "   we see the rest of the old string still there so use with caution.\n\n";
	cout << "--------------------------------------------------------------\n\n";

	//  DEMONSTRATION 2:  strcat and strncat
	strcpy(str1, "This is a test string.");
	strcat(str1, str2);
	cout << "\t str1 = " << str1 << endl << endl;
	strcpy(str1, "This is a test string.");
	cout << "Calling strncat(str1, str2, 12);\n\n";
	strncat(str1, str2, 12);
	cout << "\t str1 = " << str1 << endl << endl;
	cout << "--------------------------------------------------------------\n\n";

	// DEMONSTRATION 3:  strcmp and strncmp
	strcpy(str1, "ABCD");
	strcpy(str2, "EFGH");
	cout << "\t Calling strcmp(str1, str2) = " << strcmp(str1, str2) << endl;
	cout << "\t Calling strcmp(str2, str1) = " << strcmp(str2, str1) << endl << endl;
	strcpy(str2, "ABCD");
	cout << "\t Calling strcmp(str1, str2) = " << strcmp(str1, str2) << endl << endl;
	strcpy(str1, "ABCD");
	strcpy(str2, "ABGH");
	cout << "\t Calling strncmp(str1, str2, 3) = " << strncmp(str1, str2, 3) << endl;
	cout << "\t Calling strncmp(str2, str1, 3) = " << strncmp(str2, str1, 3) << endl;
	cout << "\t Calling strncmp(str1, str2, 2) = " << strncmp(str1, str2, 2) << endl << endl;
	cout << "--------------------------------------------------------------\n\n";

	//  DEMONSTRATION 4:  strchr, strrchr, strstr, and strlen
	// Reset str1 back to original string for next demos
	strcpy(str1, "This is a test string.");
	// Demo strchr
	cout << "\t Calling strchr(str1, 's') = " << strchr(str1, 's') << endl << endl;
	cout << "Note that the returned value is a pointer to the first occurance of 's'\n";
	cout << "  in str1.  When this returned pointer is passed to cout everything in the\n";
	cout << "  string from that pointer to the null terminator is printed.\n\n";
	cout << "--------------------------------------------------------------\n\n";
	// Demo strrchr
	cout << "\t Calling strrchr(str1, 's') = " << strrchr(str1, 's') << endl << endl;
	cout << "Note that the returned value is a pointer to the last occurance of 's'\n";
	cout << "  in str1.  When this returned pointer is passed to cout everything in the\n";
	cout << "  string from that pointer to the null terminator is printed.\n\n";
	cout << "--------------------------------------------------------------\n\n";
	// Demo strstr
	cout << "\t Calling strstr(str1, \"test\") = " << strstr(str1, "test") << endl << endl;
	cout << "Note that the returned value is a pointer to the first occurance of \"test\"\n";
	cout << "  in str1.  When this returned pointer is passed to cout everything in the\n";
	cout << "  string from that pointer to the null terminator is printed.\n\n";
	cout << "--------------------------------------------------------------\n\n";
	// Demo strlen
	cout << "\t Calling strlen(str1) = " << strlen(str1) << endl;
	cout << "--------------------------------------------------------------\n\n";

	//   DEMONSTRATION 5:  strtok
	strcpy(str1, "This is a test string");
	char *tok;
	cout << "Making initial call to strtok(str1, \" .,;:\"); with str1=\"This is a test string.\"\n";
	tok = strtok(str1, " .,;:");
	cout << "\t Calling strtok(str1, \" .,;:\") = " << tok << endl << endl;
	cout << "Subsequent calls to strtok give:\n";
	while((tok = strtok(NULL, " .,;:")) != NULL)
	{
		if(tok != NULL)
			cout << "\t Calling strtok(NULL, \" .,;:\") = " << tok << endl;
	}

	return 0;
}
NOTE: If you #include <cstring> or #include <string> then there are also functions to handle Unicode strings (2 byte chars). While these are not used much now they may become a standard in the future if programs become more "internationalized".

The C++ string template

Calling this a template is perhaps a misnomer as this implies an ADT with a generic data type. The string template is for use almost exclusively with the char data type, though there are portions of it that can handle the wchar (wide char) data type for Unicode strings.

In order to have addess to all of the string functions of ANSI Standard C++ you must...

       #include <string>

Do not use <cstring> or you won’t get all the C++ functionality of the string template.

Constructors

Overloaded Operators

The following operators have been overloaded in the string template:

Functions

These abbreviations are used in the following function prototypes:

Changing the contents of a string

Getting size information on a string

Comparing two strings

Find something in the string

Getting a substring of the string

Getting a char array equivalent of the string

Strings and Iterators

Warning: You must increment a reverse_iterator to go backward through a string (rItr ++). Do not decrement it (rItr--).

Sample Code

#include <string>
#include <iostream>

using namespace std;

int main(int argc, char **argv)
{
	char dummy[32]; 

	// Demonstrate static and dynamic use of string constructors
	cout << "             Demonstration of string constructors\n";
	// Default constructor
	string s1;								
	s1 = "Test string 1";
	cout << "\nResult: s1 = " << s1 << endl << endl;

	// Iniitializer constructor
	string s2("Test string 2");					
	cout << "\nResult: s2 = " << s2 << endl << endl;

	// Dynamic creation of a string using default constructor
	string *sptr1 = new string();			
	*sptr1 = "Test string 3";
	cout << "\nResult: *sptr1 = " << *sptr1 << endl << endl;

	// Dynamic creation of a string using init constructor
	string *sptr2 = new string("Test string 4"); 
	cout << "\nResult: *sptr2 = " << *sptr2 << endl << endl;

	cout << "====================================================================\n";
	
	// Demonstrate input (cin) and output (cout) of strings
	cout << "Demonstration of overloaded << (for cout) and >> (for cin) operators\n";
	string s3;
	cout << "Enter a string (no spaces) then press Enter\n\n";
	cin >> ws;  // Clear the buffer
	cin >> s3;
	cout << "\nYou entered the string: " << s3 << endl << endl;
	cout << "Demonstration of using getline with strings\n";
	cout << "Enter a string with spaces then press Enter\n\n";
	cin >> ws;  // Clear the buffer
	getline(cin, s3);
	//	What about cin.getline(s3, '\n');  This only works with character arrays not with string
	cout << "\nYou entered the string: " << s3 << endl << endl;
	cout << "-------------------------------------------------------------------\n";
	
	// Demonstrate overloaded logical operators with strings
	cout << "     Demonstration of overloaded logical operators with strings\n";
	s1 = "Test string";
	s2 = "Test string";
	if(s1 == s2)
	   cout << "Strings are equal\n";
	else
	   cout << "Strings are not equal\n\n";
	cout << "-------------------------------------------------------------------\n";

	s1 = "Test string 1";
	s2 = "Test string 2";
	if(s1 != s2)
	   cout << "Strings are not equal\n";
	else
	   cout << "Strings are equal\n\n";
	cout << "-------------------------------------------------------------------\n";
	
	if(s1 < s2)
	   cout << "String s1 is less than s2\n";
	else
	   cout << "String s1 is greater than or equal to s2\n\n";
	cout << "-------------------------------------------------------------------\n";
	
	if(s2 > s1)
	   cout << "String s2 is greater than s1\n";
	else
	   cout << "String s2 is less than or equal to s1\n\n";
	cout << "-------------------------------------------------------------------\n";
	// Operators <=, >= have also been overloaded but are not shown here.

	// Demonstrate overloaded logical operators with strings
	cout << "     Demonstration of overloaded [] operator with strings\n";
	for(int i=0; i<(int)s1.length(); i++)
		cout << s1[i] << "  ";
	cout << endl << endl;
	cout << "====================================================================\n";

	// Demonstrate functions to change the contents of strings
	s1 = "Test string 1";
	s2 = "Test string 2";
	cout << "     Demonstration of changing the contents of a string\n";
	cout << "Executing code demonstrating append:\n\n";
	s1.append(" With this appended to it.");
	s2.append(" With this appended to it.", 5, 14);
	cout << "\nResults: \n";
	cout << "\n\ts1 = " << s1 << endl;
	cout << "\n\ts2 = " << s2 << endl;
	cout << "-------------------------------------------------------------------\n\n";

	cout << "Executing code demonstrating assign:\n\n";
	s1.assign("Test string 1");
	s2.assign("Test string 2");
	cout << "\nResults: \n";
	cout << "\n\ts1 = " << s1 << endl;
	cout << "\n\ts2 = " << s2 << endl;
	cout << "-------------------------------------------------------------------\n\n";

	s3 = "Test string 3";
	cout << "Executing code demonstrating erase:\n\n";
	s1.erase(5, 5);
	string::iterator itr = s2.begin();
	itr+=4;  // Set iterator to first space
	s2.erase(itr);
	string::iterator itrB = s3.begin();
	itrB+=5;
	string::iterator itrE = s3.begin();
	itrE+=12;
	s3.erase(itrB, itrE);
	cout << "\nResults: \n";
	cout << "\n\ts1 = " << s1 << endl;
	cout << "\n\ts2 = " << s2 << endl;
	cout << "\n\ts3 = " << s3 << endl;
	cout << "-------------------------------------------------------------------\n\n";

	s1 = "Test string 1";
	s2 = "Test string 2";
	s3 = "Test string 3";
	string s4 = "Test string 4";
	cout << "Executing code demonstrating insert:\n\n";
	s1.insert(4, "ing");
	s2.insert(4, "Ring Ring, anyone there?", 1, 3); 
	itr = s3.begin(); 
	itrB = s4.begin();
	itrE = s4.begin();
	itrE+=5;
	s3.insert(itr, itrB, itrE);
	cout << "\nResults: \n";
	cout << "\n\ts1 = " << s1 << endl;
	cout << "\n\ts2 = " << s2 << endl;
	cout << "\n\ts3 = " << s3 << endl;
	cout << "-------------------------------------------------------------------\n\n";

	s1 = "Test string 1";
	s2 = "Test string 2";
	cout << "Executing code demonstrating replace:\n\n";
	s1.replace(0, 4, "What a fun time");
	s2.replace(0, 4, "What a fun time", 0, 10);
	cout << "\nResults: \n";
	cout << "\n\ts1 = " << s1 << endl;
	cout << "\n\ts2 = " << s2 << endl;
	cout << "====================================================================\n";

	cout << "       Demonstration of getting size information on a string\n";
	s1 = "Test string 1";
	cout << "\nResults: \n";
	cout << "\tlength = " << s1.length() << endl;
	cout << "\tsize = " << s1.size() << endl;
	cout << "\tmax_size = " << s1.max_size() << endl;
	cout << "\tcapacity = " << s1.capacity() << endl;
	cout << "\tempty = " << s1.empty() << endl;
	cout << "====================================================================\n";

	cout << "            Demonstration of comparing two strings\n";
	s1 = "Test string 2 this isn't";
	s2 = "Test string 2";
	cout << "\nResults: \n";
	cout << "\ts1.compare(s2) = " << s1.compare(s2) << endl;
	cout << "\ts1.compare(0, 13, s2) = " << s1.compare(0, 13, s2) << endl;
	cout << "\ts1.compare(6, 6, s2, 6, 6) = " << s1.compare(6, 6, s2, 6, 6) << endl;
	cout << "====================================================================\n";

	cout << "               Demonstration of searching a string\n";
	s1 = "Test string 1";
	cout << "\ts1.find(\"string\", 0) = " << s1.find("string", 0) << endl;
	cout << "\ts1.rfind(\"string\", s1.length()) = " << s1.rfind("string", s1.length()) << endl;
	cout << "\ts1.find_first_of(\"abcde\", 0) = " << s1.find_first_of("abcde", 0) << endl;
	cout << "\ts1.find_last_of(\"abcde\", s1.length()) = " << s1.find_last_of("abcde", s1.length()) << endl;
	cout << "\ts1.find_first_not_of(\"abcde\", 0) = " << s1.find_first_not_of("abcde", 0) << endl;
	cout << "\ts1.find_last_not_of(\"abcde\", s1.length()) = " << s1.find_last_not_of("abcde", s1.length()) << endl;
	cout << "====================================================================\n";

	cout << "              Demonstration of getting a substring and a \n";
	cout << "                character array representing a string\n";
	cout << "\ts1.substr(5) = " << s1.substr(5) << endl;
	cout << "\ts1.substr(5, 6) = " << s1.substr(5, 6) << endl;
	cout << "\ts1.c_str() = " << s1.c_str() << endl;
	cout << "====================================================================\n";

	cout << "     Demonstration of forward and reverse iterators in a string. \n";
	for(string::iterator it=s1.begin(); it != s1.end(); it++)
		cout << *it << "  ";
	cout << endl << endl << "\t";
	for(string::reverse_iterator it=s1.rbegin(); it != s1.rend(); it++)
		cout << *it << "  ";
	cout << endl << endl;

	return 0;
}