Simple example of a program using string class and comparison with C char:
C++ String Class: | C character: |
---|---|
#include <string> #include <iostream> using namespace std; main() { string SS; // C++ STL string string SS2; // C++ STL string SS = "This is a string"; SS2 = SS; cout << SS << endl; cout << SS2 << endl; } |
#include <string.h> // Required by strcpy() #include <stdlib.h> // Required by malloc() #include <iostream> using namespace std; main() { char CC[17]; // C character string (16 characters + NULL termination) // Storage pre-allocated char *CC2; // C character string. No storage allocated. strcpy(CC,"This is a string"); CC2 = (char *) malloc(17); // Allocate memory for storage of string. strcpy(CC2,"This is a string"); cout << CC << endl; cout << CC2 << endl; } |
Run: ./stringtest
Results for both examples:
This is a string This is a string
The C and C++ methods of managing a character data type are both valid but we will see that the C++ string class offers more functionality and convenience. The STL string does not require memory to be pre-allocated nor allocated manually. The STL string class also provides many methods of string assignment.
- Constructors:
string sVar1("abc"); string sVar2(C-string-variable); // Null terminated char string sVar3(10," "); // Generate string initialized to 10 blanks. string sVar4(Var1, string-index); // Initialize with characters from string starting with index string-index. string sVar5(iterator-index-begin, iterator-index-end)
- Destructor:
Var.~string(); // Destructor
- Replace:
- Var.replace(beginning,end-position,string-class-variable)
- Var.replace(beginning,end-position,C-char-variable)
- Var.replace(beginning,end-position,string-class-variable,length)
- Var.replace(beginning,end-position,integer-number,single-char)
- Var.replace(beginning,end-position,new-beginning-porition,new-end-position)
Code samples:
string g("abc abc abd abc"); cout << g.replace(4,1,"ijk",3) << endl; string h("abc abc abd abc"); cout << h.replace(4,6,"ijk",3) << endl; string k("abc abc abd abc"); cout << k.replace(4,3,"ijk",3) << endl; string l("abc abc abd abc"); cout << k.replace(12,1,"xyz",3) << endl;
abc ijkbc abd abc - Beginning with the 4th index (character number 5) replace one character with 3 characters from string "ijk"
abc ijkd abc
abc ijk abd abc
abc abc abd xyzbc - Find: (also rfind(), find_first_of(), find_last_of(), find_first_not_of(), find_last_not_of())
Arguments/parameters:
- Val.find(const string& argument)
Find first occurence of argument within string Val - find(const string& argument, size_type index)
Find first occurence of argument within string Val starting search from position index. - find(const char* argument)
- find(const char* argument, size_type index)
- find(const char* argument, size_type index, size_type length)
Find first occurence of argument within string Val starting search from position index and search for length number of characters.
- Val.find(const string& argument)
STL C++ string functions:
Assuming declaration: string Var;Function/Operation | Description |
---|---|
Var = string2 Var.assign("string-to-assign") |
Assignment of value to string (operator=). When assigning a C "char" data type, first check if NULL to avoid failure/crash. i.e.: if( szVar ) sVar.assign( szVar ); where szVar is a C "char *" data type and sVar is of type "string". |
Var.swap(string2) swap(string1,string2) |
Swap with value held in string2. Function swap will exchange contents of two string class variables. |
Var += string2 Var.append() Var.push_back() |
Append string/characters to the end of the string. For string Var("abc"); the call to Var.append("xyz") will result in the string "abcxyz". |
Var.insert(size_t position, string) Var.insert(size_t position, char *) Var.insert(size_t position, string, size_t pos1, size_t len) Var.insert(size_t position, char *, size_t pos1, size_t len) |
Insert characters. position: insert before this character position. If 0 then insert before the string pos1: position of the first char of the string being inserted len: length of string to be inserted |
Var.erase() Var = "" |
Clear string variable. No arguments necessary. |
+ | Concatenate |
==, !=, <, <=, >, >= | Compare strings. |
Var.compare(string) Var.compare( size_t pos1, size_t len, string ) const; Var.compare( size_t pos1, size_t len1, const string, size_t pos2, size_t len2 ) const; |
Compare strings. Returns int:
|
Var.length() | Return memory allocated to storage of the string. No arguments necessary. The methods length(), size() and capacity() all return the same value. |
Var.size() | Return length of string. No arguments necessary. |
Var.capacity() | Return length of string + 1. Red Hat 7.x. Red Hat
8.0+ returns the number of characters without the "+1". Number of
characters that can be held without re-allocation. No arguments necessary. |
Var.max_size() | Returns a very large number. No arguments necessary. |
Var.empty() | Returns 1 if an empty string. Returns 0 if not empty. |
<< | Output stream |
>> getline() |
Input stream |
Var.c_str() | Returns C string pointer. C char string is null terminated. Do not free memory using this pointer! |
Var.data() | Returns C string pointer. C char string is NOT null terminated. Do not free memory using this pointer! |
Var[] Var.at(integer) |
Access individual characters. Return single character at specified position (integer). For Var("abc");, Var[2] returns "c". |
Var.copy(char *str,size_t len, size_t index) | str: allocated char storage to which the copy ismade len: the number of characters to copy index: the starting place in the string from which to start the copy. Counting starts from 0 returns the number of characters copied |
Var.find(string) Var.find(string, positionFirstChar) Var.find(string, positionFirstChar, len) |
Find first occurance of string or substring. Returns int position of first occurance in string. Where len is the length of the sequence to search for. Returns string::npos if not found. i.e. if(Var.find("abc") == string::npos) cout << "Not found" << endl; |
Var.rfind() | Find last occurance of string or substring. |
Var.find_first_of(string, size_t position) Var.find_first_of( char *str, size_t position) Var.find_first_of( char *str, size_t position, size_t len ) |
Find strings and substrings. Where string is another STL string and str is a null terminated C string. If position = 0, than start at beginning of string. |
Var.find_last_of(string, size_t position) Var.find_last_of( char *str, size_t position) Var.find_last_of( char *str, size_t position, size_t len ) |
Find strings and substrings. position: the last character considered. If equal to the string length, then the entire string is searched len: number of characters you are searching for |
Var.find_first_not_of() Var.find_last_not_of() |
Find strings and substrings. |
Var.replace(pos1, len1, string) Var.replace(itterator1, itterator2, const string) Var.replace(pos1, len1, string, pos2, len2) |
Replace section of string with new characters.
pos2 and len2 are given when using only a substring of string. Where string is another STL string or null terminated C string. |
Var.substr(pos, len) | Return substring of text given a start position in string object and length. |
Var.begin() Var.end() |
Iterators |
Var.rbegin() Var.rend() |
Reverse iterators |
Note that in most cases the string functions have been overloaded to accept both string class arguments and C char variables.
Iterators provide the ability to access the individual characters in a string.
#include <iostream> #include <string> using namespace std; int main() { string alphabetLC="abcdefghijklmnopqrstuvwxyz"; string::const_iterator cii; int ii; for(cii=alphabetLC.begin(); cii!=alphabetLC.end(); cii++) { cout << ii++ << " " << *cii << endl; } }
0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h ... ..
Iterator types:
- string::traits_type
- string::value_type
- string::size_type
- string::difference_type
- string::reference
- string::const_reference
- string::pointer
- string::const_pointer
- string::iterator
- string::const_iterator
- string::reverse_iterator
- string::const_reverse_iterator
- string::npos
The full use of the C standard library is available for use by utilizing the ".c_str" function return of the string class.
#include <strings.h> #include <string> #include <stdio.h> using namespace std; int main() { char *phrase1="phrase"; string phrase2("Second phrase"); char phraseA[128]; char *phraseB; strcpy(phraseA,phrase2.c_str()); phraseB = strstr(phrase2.c_str(),phrase1); printf("phraseA: %s\n",phraseA); printf("phraseB: %s\n",phraseB); printf("phrase2: %s\n",phrase2.c_str()); }
Compile and run:
[prompt]$ g++ test.cpp [prompt]$ ./a.out phraseA: Second phrase phraseB: phrase phrase2: Second phrase
In memory I/O string processing used as a data type conversion. This can also be used to make use of formatting of output in memory.
File: int2string.cpp
#include <iostream> #include <sstream> #include <string> using namespace std; string int2string(const int& number) { ostringstream oss; oss << number; return oss.str(); } main() { int number=7878; string test="SSSSS"; test += int2string(number); cout << test << endl; }
[prompt]$ g++ int2string.cpp [prompt]$ a.out SSSSS7878[Potential Pitfall]: Returned string value must be used right away without other memory being set as string destructor will free the memory associated with its contents. It is much safer for the function to return a char data type or pass the string reference as an argument.
This is used to make use of reading and parsing a string in memory. It will also allow data type conversion from a string to the type read.
File: test.cpp
#include <iostream> #include <sstream> #include <string> using namespace std; main() { string test="AAA 123 SSSSS 3.141592654"; istringstream totalSString( test ); string string1, string2; int integer1; double PI; totalSString >> string1 >> integer1 >> string2 >> PI; cout << "Individual parsed variables:" << endl; cout << "First string: " << string1 << endl; cout << "First integer: " << integer1 << endl; cout << "Value of PI: " << PI << endl; }
[prompt]$ g++ test.cpp [prompt]$ a.out Individual parsed variables: First string: AAA First integer: 123 Value of PI: 3.14159
The string function std::to_string() is part of the C++ 11 standard and converts integer and floating point values to a string. The g++ compiler will require the compile flag -std=c++11 to support C++ 11.
Function | Description |
---|---|
std::string to_string( int value ); | Returns a string given an integer |
std::string to_string( long long value ); | Returns a string given a long long |
std::string to_string( unsigned value ); | Returns a string given an unsigned |
std::string to_string( unsigned long value ); | Returns a string given an unsigned long |
std::string to_string( unsigned long long value ); | Returns a string given an unsigned long long |
std::string to_string( float value ); | Returns a string given a float |
std::string to_string( double value ); | Returns a string given a double |
std::string to_string( long double value ); | Returns a string given an long double |
#include <iostream> #include <string> #include <stdio.h> #include <string.h> #include <stdlib.h> using namespace std; main() { string test ="AAA "; int integerx = 5; double Pi = 3.14159; char ccc[5] = "CCC"; char *testc = (char *)malloc(32); // The C++ way test.append(std::to_string(integerx)); cout << test << endl; // The old C way sprintf(testc, "%s %d %s",ccc, integerx, std::to_string(Pi).c_str()); // Could have printed directly using printf() printf("%s\n",testc); // or printf("%s %d %7.5f\n",ccc, integerx, Pi); }
[prompt]$ g++ -std=c++11 test.cpp [prompt]$ a.out AAA 5 CCC 5 3.141590 CCC 5 3.14159
Example of a program using many of the build-in functions of the string class:
#include <string> #include <iostream> using namespace std; main() { string a("abcd efg"); string b("xyz ijk"); string c; cout << a << " " << b << endl; // Output: abcd efg xyz ijk cout << "String empty: " << c.empty() << endl; // String empty: 1 // Is string empty? Yes it is empty. (TRUE) c = a + b; // concatenation cout << c << endl; // abcd efgxyz ijk cout << "String length: " << c.length() << endl; // String length: 15 cout << "String size: " << c.size() << endl; // String size: 15 cout << "String capacity: " << c.capacity() << endl; // String capacity: 15 cout << "String empty: " << c.empty() << endl; // String empty: 0 // Is string empty? No it is NOT empty. (FALSE) string d = c; cout << d << endl; // abcd efgxyz ijk // First character: a cout << "First character: " << c[0] << endl; // Strings start with index 0 just like C. string f(" Leading and trailing blanks "); cout << "String f:" << f << endl; cout << "String length: " << f.length() << endl; // String length: 37 cout << "String f:" << f.append("ZZZ") << endl; // String f: Leading and trailing blanks ZZZ cout << "String length: " << f.length() << endl; // String length: 40 string g("abc abc abd abc"); cout << "String g: " << g << endl; // String g: abc abc abd abc cout << "Replace 12,1,\"xyz\",3: " << g.replace(12,1,"xyz",3) << endl; // Replace 12,1,"xyz",3: abc abc abd xyzbc cout << g.replace(0,3,"xyz",3) << endl; // xyz abc abd xyzbc cout << g.replace(4,3,"xyz",3) << endl; // xyz xyz abd xyzbc cout << g.replace(4,3,"ijk",1) << endl; // xyz i abd xyzbc cout << "Find: " << g.find("abd",1) << endl; // Find: 6 cout << g.find("qrs",1) << endl; string h("abc abc abd abc"); cout << "String h: " << h << endl; cout << "Find \"abc\",0: " << h.find("abc",0) << endl; // Find "abc",0: 0 cout << "Find \"abc\",1: " << h.find("abc",1) << endl; // Find "abc",1: 4 cout << "Find_first_of \"abc\",0: " << h.find_first_of("abc",0) << endl; // Find_first_of "abc",0: 0 cout << "Find_last_of \"abc\",0: " << h.find_last_of("abc",0) << endl; // Find_last_of "abc",0: 0 cout << "Find_first_not_of \"abc\",0: " << h.find_first_not_of("abc",0) << endl; // Find_first_not_of "abc",0: 3 cout << "Find_first_not_of \" \": " << h.find_first_not_of(" ") << endl; // Find_first_not_of " ": 0 cout << "Substr 5,9: " << h.substr(5,9) << endl; // Substr 5,9: bc abd ab cout << "Compare 0,3,\"abc\": " << h.compare(0,3,"abc") << endl; // Compare 0,3,"abc": 0 cout << "Compare 0,3,\"abd\": " << h.compare(0,3,"abd") << endl; // Compare 0,3,"abd": -1 cout << h.assign("xyz",0,3) << endl; // xyz cout << "First character: " << h[0] << endl; // Strings start with 0 // First character: x }
Compile: g++ program.cpp
[Potential Pitfall]: In Red Hat Linux versions 7.x one could omit the "using namespace std;" statement. Use of this statement is good programming practice and is required in Red Hat 8.0.
[Potential Pitfall]: Red Hat 8.0 requires the reference to "#include <iostream>". Red Hat versions 7.x used "#include <iostream.h>". (Also fstream, ...)
abcd efg xyz ijk String empty: 1 abcd efgxyz ijk String length: 15 String size: 15 String capacity: 15 String empty: 0 abcd efgxyz ijk First character: a String f: Leading and trailing blanks String length: 37 String f: Leading and trailing blanks ZZZ String length: 40 String g: abc abc abd abc Replace 12,1,"xyz",3: abc abc abd xyzbc xyz abc abd xyzbc xyz xyz abd xyzbc xyz i abd xyzbc Find: 6 4294967295 String h: abc abc abd abc Find "abc",0: 0 Find "abc",1: 4 Find_first_of "abc",0: 0 Find_last_of "abc",0: 0 Find_first_not_of "abc",0: 3 Find_first_not_of " ": 0 Substr 5,9: bc abd ab Compare 0,3,"abc": 0 Compare 0,3,"abd": -1 xyz First character: x
- The compare function arguments have changed from X.compare("string",int-1, int-2); to X.compare(int-1, int-2, "string");
- The return value of the compare function call h.compare("abc",0,3) in 7.x was 12. In Red Hat 8.0 h.compare(0,3,"abc") it is 0.
- String capacity function call "c.capacity()" is 15. The returned value in Red Hat 7.x was 16.
Code Snipets:
- Read lines from standard input:
while( getline(std::cin, sLine) ) { if( sLine.empty() ); // Ignore empty lines else { cout << sLine[0] << sLine[1] << endl; .... ... } }
- Read lines from input file:
#define SYS_CONFIG_FILE "/etc/file.conf" #include <string> #include <algorithm> #include <vector> #include <cctype> #include <iostream> #include <fstream> using namespace std; string::size_type posBeginIdx, posEndIdx; string::size_type ipos=0; string sLine, sValue; string sKeyWord; const string sDelim( ":" ); ifstream myInputFile(SYS_CONFIG_FILE, ios::in); if( !myInputFile ) { sError = "File SYS_CONFIG_FILE could not be opened"; return sError; // ERROR } while( getline(myInputFile,sLine) ) { if( sLine.empty() ); // Ignore empty lines else { posEndIdx = sLine.find_first_of( sDelim ); sKeyWord = sLine.substr( ipos, posEndIdx ); // Extract word posBeginIdx = posEndIdx + 1; // Beginning of next word (after ':') .... ... } }
- Strip blank characters:
void stripLeadingAndTrailingBlanks(string& StringToModify) { if(StringToModify.empty()) return; int startIndex = StringToModify.find_first_not_of(" "); int endIndex = StringToModify.find_last_not_of(" "); string tempString = StringToModify; StringToModify.erase(); StringToModify = tempString.substr(startIndex, (endIndex-startIndex+ 1) ); }
The first thing you will notice when using the C++ string class is that you can't de-reference any of the string class variables directly with GDB, ddd,... One must create a helper routine (for older versions of gdb) or use string class funtions (newer versions of gdb) to print out the value of the string variable.
#include <string> #include <iostream> using namespace std; // Helper routine ps to print a string class variable. void ps(string& s){ cout << s << endl; } int main() { string a("String A"); string b; b = "String B"; cout << "Hello!" << endl; }
Compile program with symbolic code for the debugger: g++ -g testprog.cpp
Start gdb debugger: gdb ./a.out
(gdb) l 1,18 - List lines 1 to 18 1 #include <string> 2 #include <iostream> 3 4 using namespace std; 5 6 // Helper routine ps to print a string class variable. 7 8 void ps(string& s){ cout << s << endl; } 9 10 int main() 11 { 12 string a("String A"); 13 string b; 14 15 b = "String B"; 16 17 cout << "Hello!" << endl; 18 } (gdb) break 17 Breakpoint 1 at 0x804893b: file testprog.cpp, line 17. (gdb) run Starting program: /home/user1/a.out Breakpoint 1, main () at testprog.cpp:17 17 cout << "Hello!" << endl; (gdb) p a - Gdb can't de-reference string class variable "a" $1 = {static npos = Cannot access memory at address 0x83a32d0 (gdb) call ps(a) String A - Call helper function ps to print string conents. (gdb) call ps(b) String B (gdb) c Continuing. Hello! Program exited normally. (gdb) quitWith newer versions of gdb, one may use built-in string class functions:
(gdb) p a.c_str() $1 = 0x8049e34 "String A" (gdb) p b.c_str() $3 = 0x8049e4c "String B" (gdb) p b.empty() $2 = false (gdb) p b.size() $4 = 8
Dereference string and wstring using GDB macro functions. See YoLinux.com GDB tutorial on dereferencing STL strings and containers.
- The string class is NOT a native data type, it is an object class and thus can not be handled like the traditional pointer to variable in gdb.
- One can pass strings by reference (i.e. argument declarations using (string& variable-name )), by value (string variable-name ), and by pointer (string *variable-name ).
- When using a reference, one may mimic the protection of a variable that passing by value enables by using (const string& variable-name )
- GNU C++ Library: String classes
- IBM AIX IString class example
- STL: basic_string - SGI STL home
- YoLinux.com: C++