From http://www.yolinux.com/TUTORIALS/LinuxTutorialC++StringClass.html
Simple example of a program using string class and comparison with C char:
-
01
#include <string>
02
#include <iostream>
03
#include <string.h> // Required by strcpy()
04
#include <stdlib.h> // Required by malloc()
05
06
using
namespace
std;
07
08
main()
09
{
10
string SS;
// C++ STL string
11
char
CC[17];
// C character string (16 characters + NULL termination)
12
// Storage pre-allocated
13
char
*CC2;
// C character string. No storage allocated.
14
15
SS =
"This is a string"
;
16
strcpy
(CC,
"This is a string"
);
17
18
CC2 = (
char
*)
malloc
(17);
// Allocate memory for storage of string.
19
strcpy
(CC2,
"This is a string"
);
20
21
cout << SS << endl;
22
cout << CC << endl;
23
cout << CC2 << endl;
24
}
Results:
This is a string
This is a string
This is a stringThe 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.
Example of a program using many of the build-in functions of the string class:
-
01
#include <string>
02
#include <iostream>
03
04
using
namespace
std;
05
06
main()
07
{
08
string a(
"abcd efg"
);
09
string b(
"xyz ijk"
);
10
string c;
11
12
cout << a <<
" "
<< b << endl;
// Output: abcd efg xyz ijk
13
14
cout <<
"String empty: "
<< c.empty() << endl;
// String empty: 1
15
// Is string empty? Yes it is empty. (TRUE)
16
c = a + b;
// concatenation
17
cout << c << endl;
// abcd efgxyz ijk
18
cout <<
"String length: "
<< c.length() << endl;
// String length: 15
19
cout <<
"String size: "
<< c.size() << endl;
// String size: 15
20
cout <<
"String capacity: "
<< c.capacity() << endl;
// String capacity: 15
21
cout <<
"String empty: "
<< c.empty() << endl;
// String empty: 0
22
// Is string empty? No it is NOT empty. (FALSE)
23
string d = c;
24
cout << d << endl;
// abcd efgxyz ijk
25
26
// First character: a
27
cout <<
"First character: "
<< c[0] << endl;
// Strings start with index 0 just like C.
28
29
string f(
" Leading and trailing blanks "
);
30
cout <<
"String f:"
<< f << endl;
31
cout <<
"String length: "
<< f.length() << endl;
// String length: 37
32
cout <<
"String f:"
<< f.append(
"ZZZ"
) << endl;
// String f: Leading and trailing blanks ZZZ
33
cout <<
"String length: "
<< f.length() << endl;
// String length: 40
34
35
string g(
"abc abc abd abc"
);
36
cout <<
"String g: "
<< g << endl;
// String g: abc abc abd abc
37
cout <<
"Replace 12,1,/"xyz/",3: "
<< g.replace(12,1,
"xyz"
,3) << endl;
// Replace 12,1,"xyz",3: abc abc abd xyzbc
38
cout << g.replace(0,3,
"xyz"
,3) << endl;
// xyz abc abd xyzbc
39
cout << g.replace(4,3,
"xyz"
,3) << endl;
// xyz xyz abd xyzbc
40
cout << g.replace(4,3,
"ijk"
,1) << endl;
// xyz i abd xyzbc
41
cout <<
"Find: "
<< g.find(
"abd"
,1) << endl;
// Find: 6
42
cout << g.find(
"qrs"
,1) << endl;
43
44
string h(
"abc abc abd abc"
);
45
cout <<
"String h: "
<< h << endl;
46
cout <<
"Find /"abc/",0: "
<< h.find(
"abc"
,0) << endl;
// Find "abc",0: 0
47
cout <<
"Find /"abc/",1: "
<< h.find(
"abc"
,1) << endl;
// Find "abc",1: 4
48
cout <<
"Find_first_of /"abc/",0: "
<< h.find_first_of(
"abc"
,0) << endl;
// Find_first_of "abc",0: 0
49
cout <<
"Find_last_of /"abc/",0: "
<< h.find_last_of(
"abc"
,0) << endl;
// Find_last_of "abc",0: 0
50
cout <<
"Find_first_not_of /"abc/",0: "
<< h.find_first_not_of(
"abc"
,0) << endl;
// Find_first_not_of "abc",0: 3
51
cout <<
"Find_first_not_of /" /": "
<< h.find_first_not_of(
" "
) << endl;
// Find_first_not_of " ": 0
52
cout <<
"Substr 5,9: "
<< h.substr(5,9) << endl;
// Substr 5,9: bc abd ab
53
cout <<
"Compare 0,3,/"abc/": "
<< h.compare(0,3,
"abc"
) << endl;
// Compare 0,3,"abc": 0
54
cout <<
"Compare 0,3,/"abd/": "
<< h.compare(0,3,
"abd"
) << endl;
// Compare 0,3,"abd": -1
55
cout << h.assign(
"xyz"
,0,3) << endl;
// xyz
56
cout <<
"First character: "
<< h[0] << endl;
// Strings start with 0 // First character: x
57
58
59
}
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, ...)
Output: ./a.out
|
|
[Potential Pitfall]
: There have been some changes in the behavior of the string class from Red Hat 7.x to Red Hat 8.0:
- 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.
String class functions: |
- Constructors:
-
1
string sVar1(
"abc"
);
2
string sVar1(C-string-variable);
3
string sVar2(10,
" "
);
// Generate string initialized to 10 blanks.
4
string sVar3(Var1, string-index);
// Initialize with characters from string starting with index string-index.
5
string sVar4(iterator-index-begin, iterator-index-end)
-
- Destructor:
-
1
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:
-
01
string g(
"abc abc abd abc"
);
02
cout << g.replace(4,1,
"ijk"
,3) << endl;
03
04
string h(
"abc abc abd abc"
);
05
cout << h.replace(4,6,
"ijk"
,3) << endl;
06
07
string k(
"abc abc abd abc"
);
08
cout << k.replace(4,3,
"ijk"
,3) << endl;
09
10
string l(
"abc abc abd abc"
);
11
cout << k.replace(12,1,
"xyz"
,3) << endl;
Output:
-
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
- Var.replace(beginning,end-position,string-class-variable
- 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. 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. Var.insert() Insert characters 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: - 0: if equal.
- -1: Not equal. 1st non matching character in Var is less in value based on ASCII table than in compare string.
- +1: Not equal. 1st non matching character is greater in value based on ASCII table.
Where string
is another STL string or null terminated C string.Var.length() Return length of 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). 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
, position)
Var.find_first_of( string
, size_t position, size_t len )Find strings and substrings.
Where string
is another STL string or null terminated C string.
If position
= 0, than start at beginning of string.Var.find_last_of() Find strings and substrings. 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.
ANSI C++ string class iterators: |
Iterators provide the ability to access the individual characters in a string.
-
01
#include <iostream>
02
#include <string>
03
using
namespace
std;
04
05
int
main()
06
{
07
string alphabetLC=
"abcdefghijklmnopqrstuvwxyz"
;
08
09
string::const_iterator cii;
10
int
ii;
11
12
for
(cii=alphabetLC.begin(); cii!=alphabetLC.end(); cii++)
13
{
14
cout << ii++ <<
" "
<< *cii << endl;
15
}
16
}
This will print the integer position in the string followed by the letter
for all characters in the alphabet.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
ANSI C++ string class and the C standard library: |
The full use of the C standard library is available for use by utilizing the
".c_str" function return of the string class.
-
01
#include <strings.h>
02
#include <string>
03
#include <stdio.h>
04
using
namespace
std;
05
06
int
main()
07
{
08
char
*phrase1=
"phrase"
;
09
string phrase2(
"Second phrase"
);
10
char
phraseA[128];
11
char
*phraseB;
12
13
strcpy
(phraseA,phrase2.c_str());
14
phraseB =
strstr
(phrase2.c_str(),phrase1);
15
16
printf
(
"phraseA: %s/n"
,phraseA);
17
printf
(
"phraseB: %s/n"
,phraseB);
18
printf
(
"phrase2: %s/n"
,phrase2.c_str());
19
}
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. File: int2string.cpp
Compile and run:
[Potential Pitfall] |
This is used to make use of reading and parsing a string in memory. File: test.cpp
Compile and run:
|
Code snipets: |
- Read lines from standard input:
01
while
( getline(std::cin, sLine) )
02
{
03
if
( sLine.empty() );
// Ignore empty lines
04
else
05
{
06
cout << sLine[0] << sLine[1] << endl;
07
....
08
...
09
}
10
}
- Read lines from input file:
01
#define SYS_CONFIG_FILE "/etc/file.conf"
02
#include <string>
03
#include <algorithm>
04
#include <vector>
05
#include <cctype>
06
#include <iostream>
07
#include <fstream>
08
09
using
namespace
std;
10
11
string::size_type posBeginIdx, posEndIdx;
12
string::size_type ipos=0;
13
string sLine, sValue;
14
string sKeyWord;
15
const
string sDelim(
":"
);
16
17
ifstream myInputFile(SYS_CONFIG_FILE, ios::in);
18
if
( !myInputFile )
19
{
20
sError =
"File SYS_CONFIG_FILE could not be opened"
;
21
return
sError;
// ERROR
22
}
23
24
while
( getline(myInputFile,sLine) )
25
{
26
if
( sLine.empty() );
// Ignore empty lines
27
else
28
{
29
posEndIdx = sLine.find_first_of( sDelim );
30
sKeyWord = sLine.substr( ipos, posEndIdx );
// Extract word
31
posBeginIdx = posEndIdx + 1;
// Beginning of next word (after ':')
32
....
33
...
34
}
35
}
- Strip blank characters:
01
void
02
stripLeadingAndTrailingBlanks(string& StringToModify)
03
{
04
if
(StringToModify.empty())
return
;
05
06
int
startIndex = StringToModify.find_first_not_of(
" "
);
07
int
endIndex = StringToModify.find_last_not_of(
" "
);
08
string tempString = StringToModify;
09
StringToModify.erase();
10
11
StringToModify = tempString.substr(startIndex, (endIndex-startIndex+ 1) );
12
}
The String Class and Debugging in GDB: |
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.
-
01
#include <string>
02
#include <iostream>
03
04
using
namespace
std;
05
06
// Helper routine ps to print a string class variable.
07
08
void
ps(string& s){ cout << s << endl; }
09
10
int
main()
11
{
12
string a(
"String A"
);
13
string b;
14
15
b =
"String B"
;
16
17
cout <<
"Hello!"
<< endl;
18
}
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) quit
With 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
.
Tips: |
- 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
)
Links/Information: |