Você está na página 1de 29

C++ standart Template Library

Some of the STL functions used in case of Vectors in C++ Sort() Count Push_back() Begin() End() Empty() Min_element(start,end) Max_element(start,end) Find(start,end,key) : if not found returns end Accumulate(start,end,init) : adds with initial value as init. Accumulate(Start,end,init,minus<int>()): subtracts the vector

Algorithm

Description and Example of use

find

Finds the first occurence of a given value, and returns an iterator to it. If the value is not found in the sequence, it returns end. if (find (marks.begin(), marks.end(), 0) == marks.end()) { // 0 is not found in the sequence }

replace

Replaces all the occurences of a given value with another one. replace (names.begin(), names.end(), "", "not valid");

reverse

Reverses the order of the elements in the sequence. sort (values.begin(), values.end()); reverse (values.begin(), values.end()); // the sequence is now sorted in descendant order

random_shuffle

Reorders the sequence randomly, such that every possible permutation is equally probable.

random_shuffle (cards.begin(), cards.end());

An important detail to notice: these algorithms may be used with strings, to iterate over the characters of the string. For instance, if you want to replace all of the spaces with underscores, you could simply do: replace (str.begin(), str.end(), ' ', '_'); In some cases, however, it may be better to use the built-in string facilities (for instance, why using the find algorithm with strings, if we have the find method as part of the string manipulation facilities?)

Example code
#include #include #include #include <iostream> <vector> <string> <algorithm>

#include <numeric> using namespace std; int main() { vector<string> student_names; vector<double> student_marks;

do { string name; cout << "Enter student name (Enter to finish): "; getline (cin, name); // Now that we have the name from the user, // append it at the end of the vector if valid if (name != "") { student_names.push_back (name); } } while (name != "");

// sort them alphabetically sort (student_names.begin(), student_names.end()); // Now enter grades for each student student_marks.resize (student_names.size()); vector<string>::iterator s; vector<double>::iterator m; for (s = student_names.begin(), m = student_marks.begin(); s != student_names.end(); ++s, ++m) { do { cout << "Enter marks (0 to 100) for " << *s << ": "; cin >> *m; if (*m < 0 || *m > 100) { cout << "Error: marks must be between 0 and 100" << endl; } } while (*m < 0 || *m > 100); } if (! students_marks.empty()) // equivalent to student_marks.size() != 0 { cout << "There are " << count (student_marks.begin(), student_marks.end(), 100) << " students that got highest mark!" << endl; cout << "Lowest mark: " << *min_element (student_marks.begin(), student_marks.end()) << "\nHighest mark: " << *max_element (student_marks.begin(), student_marks.end()) << endl; cout << "Average: " << accumulate (student_marks.begin(), student_marks.end(), 0) / student_marks.size() << endl; } return 0; }

STL list: list: Linked list of variables, struct or objects. Insert/remove anywhere. Two examples are given: 1. The first STL example is for data type int 2. The second for a list of class instances. They are used to show a simple example and a more complex real world application. 1. Lets start with a simple example of a program using STL for a linked list:
01 // Standard Template Library example 02 03 #include <iostream> 04 #include <list> 05 using namespace std; 06 07 // Simple example uses type int 08 09 main() 10 { 11 12 13 list<int> L; L.push_back(0); // Insert a new element at the end // Insert a new element at the // Insert "2" before position of first // (Place before second argument) L.push_back(5); L.push_back(6); list<int>::iterator i; for(i=L.begin(); i != L.end(); ++i) cout << *i << " "; cout << endl; return 0;

L.push_front(0); beginning L.insert(++L.begin(),2); 14 argument 15 16 17 18 19 20 21 22 23 24 }

Compile: g++ Run: ./a.out

example1.cpp

Output: 0

2 0 5 6

[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 and later. [Potential Pitfall]: Red Hat 8.0 and later requires the reference to "#include <iostream>". Red Hat versions 7.x used "#include <iostream.h>".

2. The STL tutorials and texts seem to give simple examples which do not apply to the real world. The following example is for a doubly linked list. Since we are using a class and we are not using defined built-in C++ types we have included the following:

To make this example more complete, a copy constructor has been included although the compiler will generate a member-wise one automatically if needed. This has the same functionality as the assignment operator (=). The assignment (=) operator must be specified so that sort routines can assign a new order to the members of the list. The "less than" (<) operator must be specified so that sort routines can determine if one class instance is "less than" another. The "equals to" (==) operator must be specified so that sort routines can determine if one class instance is "equals to" another.
001 // Standard Template Library example using a class. 002 003 #include <iostream> 004 #include <list> 005 using namespace std; 006 007 // The List STL template requires overloading operators =, == and <. 008 009 class AAA 010 { 011 012 013 014 015 016 public: int x; int y; float z; friend ostream &operator<<(ostream &, const AAA &);

017 018 019 020 021 022 023 024 }; 025 026 AAA::AAA() 027 { 028 029 030 031 } 032 033 AAA::AAA(const AAA &copyin) value. 034 { 035 036 037 038 } 039 040 ostream &operator<<(ostream &output, const AAA &aaa) 041 { 042 043 044 } 045 046 AAA& AAA::operator=(const AAA &rhs) 047 { 048 049 050 051 052 } 053 054 int AAA::operator==(const AAA &rhs) const 055 { 056 057 if( this->x != rhs.x) return 0; if( this->y != rhs.y) return 0; this->x = rhs.x; this->y = rhs.y; this->z = rhs.z; return *this; output << aaa.x << ' ' << aaa.y << ' ' << aaa.z << endl; return output; x = copyin.x; y = copyin.y; z = copyin.z; // Copy constructor to handle pass by x = 0; y = 0; z = 0; // Constructor AAA(); AAA(const AAA &); ~AAA(){}; AAA &operator=(const AAA &rhs); int operator==(const AAA &rhs) const; int operator<(const AAA &rhs) const;

058 059 060 } 061

if( this->z != rhs.z) return 0; return 1;

062 // This function is required for built-in STL list functions like sort 063 int AAA::operator<(const AAA &rhs) const 064 { 065 066 067 068 069 } 070 071 main() 072 { 073 074 075 076 077 078 079 080 081 Ablob.x=5; L.push_back(Ablob); 082 member-wise 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 for(i=L.begin(); i != L.end(); ++i) cout << *i << " "; // print for(i=L.begin(); i != L.end(); ++i) cout << (*i).x << " "; // print member cout << endl; list<AAA>::iterator i; Ablob.x=3; Ablob.y=7; Ablob.z=7.2355; L.push_back(Ablob); Ablob.z=3.2355; L.push_back(Ablob); // Object passed by value. Uses default // copy constructor Ablob.x=7; Ablob.y=2; Ablob.z=4.2355; L.push_back(Ablob); // Insert a new element at the end list<AAA> L; AAA Ablob ; if( this->x == rhs.x && this->y == rhs.y && this->z < rhs.z) return 1; if( this->x == rhs.x && this->y < rhs.y) return 1; if( this->x < rhs.x ) return 1; return 0;

with overloaded operator 098 cout << endl; 099 100 101 cout << "Sorted: " << endl; L.sort(); for(i=L.begin(); i != L.end(); ++i) cout << *i << " "; // print 102 with overloaded operator 103 104 105 106 } return 0; cout << endl;

Output:
7 5 5 3 7 2 4.2355 5 2 4.2355 5 2 3.2355 3 7 7.2355 Sorted: 3 7 7.2355 5 2 3.2355 5 2 4.2355 7 2 4.2355

STL vector vs list function comparison:


Function destructor empty() size() resize() capacity() reserve() erase() clear() operator= vector list yes yes yes yes yes no no yes yes yes yes yes yes yes yes yes yes yes yes yes

constructor yes

max_size() yes

operator< operator[] at() front() back()

yes yes yes yes yes

yes yes no no yes yes yes yes yes yes yes yes yes yes yes yes yes yes yes yes

operator== yes

push_back() yes pop_back() yes assign() insert() swap() yes yes yes

push_front() no pop_front() no merge() remove() reverse() sort() splice() unique() no no no no no no

remove_if() no

String class example: Simple example of a program using string class and comparison with C char:
01 #include <string> 02 #include <iostream> 03 #include <string.h> 04 #include <stdlib.h> 05 06 using namespace std; 07 08 main() 09 { // Required by strcpy() // Required by malloc()

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 }

string SS; char CC[17]; termination) char *CC2;

// C++ STL string // C character string (16 characters + NULL // Storage pre-allocated // C character string. No storage allocated.

SS = "This is a string"; strcpy(CC,"This is a string");

CC2 = (char *) malloc(17); string.

// Allocate memory for storage of

strcpy(CC2,"This is a string"); cout << SS << endl; cout << CC << endl; cout << CC2 << endl;

Results:
This is a string 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. 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 09 10 11 12 cout << a << " " << b << endl; efg xyz ijk // Output: abcd string a("abcd efg"); string b("xyz ijk"); string c;

13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 string g("abc abc abd abc"); cout << "String g: " << g << endl; abc abd abc // String g: abc string f(" Leading and trailing blanks "); cout << "String f:" << f << endl; cout << "String length: " << f.length() << endl; length: 37 cout << "String f:" << f.append("ZZZ") << endl; Leading and trailing blanks ZZZ cout << "String length: " << f.length() << endl; length: 40 // String // String f: // String // First character: a cout << "First character: " << c[0] << endl; with index 0 just like C. // Strings start ijk cout << "String empty: " 1 // Is string empty? Yes it is empty. (TRUE) c = a + b; concatenation cout << c << endl; ijk cout << "String length: " 15 cout << "String size: " 15 cout << "String capacity: " << c.capacity() << endl; // String capacity: 15 cout << "String empty: " 0 // Is string empty? No it is NOT empty. (FALSE) string d = c; cout << d << endl; // abcd efgxyz << c.empty() << endl; // String empty: << c.size() << endl; // String size: << c.length() << endl; // String length: // // abcd efgxyz << c.empty() << endl; // String empty:

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; xyzbc cout << g.replace(4,3,"xyz",3) << endl; xyzbc // xyz abc abd // xyz xyz abd

40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58

cout << g.replace(4,3,"ijk",1) << endl; xyzbc cout << "Find: " << g.find("abd",1) << endl; cout << g.find("qrs",1) << endl; string h("abc abc abd abc"); cout << "String h: " << h << endl;

// xyz i abd // Find: 6

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; bc abd ab // Substr 5,9:

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

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

ZZZ

[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,
"string");

int-2,

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: o Var.replace(beginning,end-position,string-class-variable) o Var.replace(beginning,end-position,C-char-variable) o Var.replace(beginning,end-position,string-class-variable,length) o Var.replace(beginning,end-position,integer-number,single-char) o Var.replace(beginning,end-position,new-beginningporition,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

Find: (also rfind(), find_first_of(), find_last_of(), find_first_not_of(), find_last_not_of()) Arguments/parameters:


o Val.find(const string& argument)

Find first occurence of argument within string

Val

o o o

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.

STL C++ string functions:

Assuming declaration: string


Function/Operation

Var;

Description 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". Swap with value held in string2. Function swap will exchange contents of two string class variables. Append string/characters. Insert characters Clear string variable. No arguments necessary. Concatenate Compare strings. Compare strings. Returns int:

Var = string2 Var.assign("string-to-assign")

Var.swap(string2) swap(string1,string2) Var += string2 Var.append() Var.push_back() Var.insert() Var.erase() Var = "" + ==, !=, <, <=, >, >= Var.compare(string) Var.compare( size_t pos1, size_t len, string ) const; Var.compare( size_t pos1, size_t len1, conststring, size_t pos2, size_t len2 ) const;

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() andcapacity() all return the same value. Return length of string. No arguments necessary. 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. Returns a very large number. No arguments necessary. Returns 1 if an empty string. Returns 0 if not empty. Output stream Input stream Returns C string pointer. C char string is null terminated. Do not free memory using this pointer! Returns C string pointer. C char string is NOT null terminated. Do not free memory using this pointer! Access individual characters. Return single character at specified position (integer). Find first occurance of string or substring. Returns int position of first occurance in string. Wherelen 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.size() Var.capacity()

Var.max_size() Var.empty() << >> getline() Var.c_str()

Var.data()

Var[] Var.at(integer) Var.find(string) Var.find(string, positionFirstChar) Var.find(string, positionFirstChar, len)

Var.rfind() Var.find_first_of(string, position) Var.find_first_of( string, size_t position, size_t len ) Var.find_last_of() Var.find_first_not_of() Var.find_last_not_of() Var.replace(pos1, len1, string) Var.replace(itterator1, itterator2, const string)

Find last occurance of string or substring. Find strings and substrings. Where string is another STL string or null terminated C string. If position = 0, than start at beginning of string. Find strings and substrings. Find strings and substrings. Replace section of string with new characters. pos2 and len2 are given when using only a

Var.replace(pos1, len1, string, pos2, len2) Var.substr(pos, len) Var.begin() Var.end() Var.rbegin() Var.rend()

substring of string. Where string is another STL string or null terminated C string. Return substring of text given a start position in string object and length. Iterators 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 08 09 10 11 12 13 14 15 16 } } for(cii=alphabetLC.begin(); cii!=alphabetLC.end(); cii++) { cout << ii++ << " " << *cii << endl; string::const_iterator cii; int ii; string alphabetLC="abcdefghijklmnopqrstuvwxyz";

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 09 10 11 12 13 14 15 16 17 18 19 } printf("phraseA: %s\n",phraseA); printf("phraseB: %s\n",phraseB); printf("phrase2: %s\n",phrase2.c_str()); strcpy(phraseA,phrase2.c_str()); phraseB = strstr(phrase2.c_str(),phrase1); char *phrase1="phrase"; string phrase2("Second phrase"); char phraseA[128]; char *phraseB;

Compile and run:


[prompt]$ g++ test.cpp [prompt]$ ./a.out phraseA: Second phrase phraseB: phrase phrase2: Second phrase

Using ostringstream and an internal write:


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
01 #include <iostream> 02 #include <sstream> 03 #include <string> 04 using namespace std; 05 06 string int2string(const int& number) 07 { 08 09 10 11 } 12 13 main() 14 { 15 16 17 18 19 } int number=7878; string test="SSSSS"; ostringstream oss; oss << number; return oss.str();

Using istringstream and an internal read:


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
01 #include <iostream> 02 #include <sstream> 03 #include <string> 04 using namespace std; 05 06 main() 07 { 08 09 string test="AAA 123 SSSSS 3.141592654";

istringstream totalSString( test ); 10 string string1, string2; 11 12 13 14 15 16 17 18 19 cout << "Individual parsed variables:" << endl; cout << "First string: string1 << endl; " << totalSString >> string1 >> integer1 >> string2 >> PI; int integer1;

double PI;

test += int2string(number); cout << test << endl;

Compile and run:


[prompt]$ g++ int2string.cpp [prompt]$ a.out SSSSS7878

cout << "First integer: " << integer1 << endl; cout << "Value of PI: << endl; " <<

[Potential Pitfall]: Returned string value must be used right away without other memory being set as string destructor will Compile and run:

PI 20 }

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.

[prompt]$ g++ test.cpp [prompt]$ a.out Individual parsed variables: First string: AAA First integer: 123 Value of PI: 3.14159

Code snipets:

Read lines from standard input:


01 while( getline(std::cin, sLine) ) 02 { 03 04 05 06 07 08 09 10 } } if( sLine.empty() ); else { cout << sLine[0] << sLine[1] << endl; .... ... // Ignore empty lines

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 14 string 15 const string 16 17 ifstream myInputFile(SYS_CONFIG_FILE, ios::in); 18 if( !myInputFile ) 19 { sLine, sValue; sKeyWord; sDelim( ":" );

20 21 22 } 23

sError = "File SYS_CONFIG_FILE could not be opened"; return sError; // ERROR

24 while( getline(myInputFile,sLine) ) 25 { 26 27 28 29 30 31 if( sLine.empty() ); else { posEndIdx = sLine.find_first_of( sDelim ); sKeyWord = sLine.substr( ipos, posEndIdx ); // Extract word // Ignore empty lines

posBeginIdx = posEndIdx + 1; // Beginning of next word (after ':') 32 .... 33 34 35 } ... }

Strip blank characters:


01 void 02 stripLeadingAndTrailingBlanks(string& StringToModify) 03 { 04 05 06 07 08 09 10 StringToModify = tempString.substr(startIndex, (endIndex-startIndex+ 1) ); 12 } 11 int startIndex = StringToModify.find_first_not_of(" "); int endIndex = StringToModify.find_last_not_of(" "); string tempString = StringToModify; StringToModify.erase(); if(StringToModify.empty()) return;

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 13 14 15 16 17 18 } cout << "Hello!" << endl; b = "String B"; string a("String A"); string b;

Compile program with symbolic code for the debugger: g++ Start gdb debugger: gdb
./a.out

-g testprog.cpp

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

C++ STL MAP and multiMAP: Description, use and examples of C++ STL "pair", "map" and "multimap" associative containers. The STL associative container class is a variable

sized container which supports retrieval of an element value given a search key.

STL pair: A container which holds two values. The data types may or may not be different. STL map: Associative key-value pair held in balanced binary tree structure. Each key is unique. STL multimap: Same as an STL map except that duplicate keys are allowed.

Example: STL map: Sparse array example: (why hold space for thousands of elements when all we have is five)
01 #include <string.h> 02 #include <iostream> 03 #include <map> 04 #include <utility> 05 06 using namespace std; 07 08 int main() 09 { 10 11 12 13 14 15 16 17 18 19 20 21 22 23 for( map<int,string>::iterator ii=Employees.begin(); ii!=Employees.end(); ++ii) cout << "Map size: " << Employees.size() << endl; cout << "Employees[3374]=" << Employees[3374] << endl << endl; // 1) Assignment using array index notation Employees[5234] = "Mike C."; Employees[3374] = "Charlie M."; Employees[1923] = "David D."; Employees[7582] = "John A."; Employees[5328] = "Peter Q."; map<int, string> Employees;

24 25 26 27 }

{ cout << (*ii).first << ": " << (*ii).second << endl; }

Compile: g++ Run: ./a.out

testMap.cpp

Employees[3374]=Charlie M. Map size: 5 1923: David D. 3374: Charlie M. 5234: Mike C. 5328: Peter Q. 7582: John A.

Example using a "string" as an array index:


01 #include <string.h> 02 #include <iostream> 03 #include <map> 04 #include <utility> 05 06 using namespace std; 07 08 int main() 09 { 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 cout << "Map size: " << Employees.size() << endl; // 4) Assignment using member function insert() and "make_pair()" Employees.insert(std::make_pair("Peter Q.",5328)); // 3) Assignment using member function insert() and "value_type()" Employees.insert(map<string,int>::value_type("John A.",7582)); // 2) Assignment using member function insert() and STL pair Employees.insert(std::pair<string,int>("David D.",1923)); // 1) Assignment using array index notation Employees["Mike C."] = 5234; Employees["Charlie M."] = 3374; // Examples of assigning Map container contents map<string, int> Employees;

28 for( map<string, int>::iterator ii=Employees.begin(); ii!=Employees.end(); ++ii) 30 { 29 31 32 33 } } cout << (*ii).first << ": " << (*ii).second << endl;

Compile: g++ Run: ./a.out

testMap.cpp

Map size: 5 Charlie M.: 3374 David D.: 1923 John A.: 7582 Mike C.: 5234 Peter Q.: 5328

Note: The fully defined STL map defines a comparison operator in the map declaration so that the indexes can be ordered. This is used to provide a default comparison operator for the data type. In the above example, the key type is an integer and the C++ "equals" (=) and "less than" operator (<) can operate on an integer so the example works. The use of the STL algorithm std::less<> can be specified explicitly as in the following declaration:
std::map<int, string, std::less< int > >

If defining your own class as the index (first value), C++ will not know how to perform the comparison, thus you will have to provide an operator to perform this function. The first element in a map can be a class or even another STL container such as a pair. If using a class, the class must provide an overloaded "equals" (=) and "less than" operator (<). Thus using "char" instead of "string" requires the use of a comparison function:
01 #include <string.h> 02 #include <iostream> 03 #include <map> 04 #include <utility> 05 06 using namespace std; 07 08 struct cmp_str

09 { 10 11 12 13 } 14 }; 15 16 int main() 17 { 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 for( map<char *, int, cmp_str>::iterator ii=Employees.begin(); ii!=Employees.end(); ++ii) 38 { 37 39 40 41 } } cout << (*ii).first << ": " << (*ii).second << endl; cout << "Map size: " << Employees.size() << endl; // 4) Assignment using member function insert() and "make_pair()" Employees.insert(std::make_pair((char *)"Peter Q.",5328)); // 3) Assignment using member function insert() and "value_type()" Employees.insert(map<char *,int>::value_type("John A.",7582)); // 2) Assignment using member function insert() and STL pair Employees.insert(std::pair<char *,int>("David D.",1923)); // 1) Assignment using array index notation Employees["Mike C."] = 5234; Employees["Charlie M."] = 3374; // Examples of assigning Map container contents map<char *, int, cmp_str> Employees; bool operator()(char const *a, char const *b) { return std::strcmp(a, b) < 0;

Compile: g++ Run: ./a.out

testMap.cpp

Map size: 5 Charlie M.: 3374 David D.: 1923 John A.: 7582 Mike C.: 5234 Peter Q.: 5328

SGI Map Documentation:

map

Example: STL multimap: The STL multipmap allows duplicate keys.


01 #include <string.h> 02 #include <iostream> 03 #include <map> 04 #include <utility> 05 06 using namespace std; 07 08 int main() 09 { 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 { cout << " endl; [" << (*it).first << ", " << (*it).second << "]" << cout << "Elements in m: " << endl; for (multimap<string, int>::iterator it = m.begin(); it != m.end(); ++it) cout << "Number of elements with key a: " << m.count("a") << endl; cout << "Number of elements with key b: " << m.count("b") << endl; cout << "Number of elements with key c: " << m.count("c") << endl; m.insert(pair<string, int>("a", 1)); m.insert(pair<string, int>("c", 2)); m.insert(pair<string, int>("b", 3)); m.insert(pair<string, int>("b", 4)); m.insert(pair<string, int>("a", 5)); m.insert(pair<string, int>("b", 6)); multimap<string, int> m; // Compare (<) function not required since it is built into string class. // else declaration would comparison function in multimap definition. // i.e. multimap<string, int, compare> m;

33 34 35 36

} pair<multimap<string, int>::iterator, multimap<string, int>::iterator> ppp;

// equal_range(b) returns pair<iterator,iterator> representing the range 38 // of element with key b 37 39 40 41 42 43 44 45 46 47 // Loop through range of maps of key "b" cout << endl << "Range of \"b\" elements:" << endl; for (multimap<string, int>::iterator it2 = ppp.first; it2 != ppp.second; ++it2) { cout << " [" << (*it2).first << ", " << (*it2).second << "]" << ppp = m.equal_range("b");

endl; 48 } 49 50 // Can't do this (??) 51 // 52 // 53 54 55 } m.clear(); cout << ppp.first << endl; cout << ppp.second << endl;

Compile: g++ Run: ./a.out

testMultimap.cpp

Number of elements with key a: 2 Number of elements with key b: 3 Number of elements with key c: 1 Elements in m: [a, 1] [a, 5] [b, 3] [b, 4] [b, 6] [c, 2] Range [b, [b, [b, of "b" elements: 3] 4] 6]

Você também pode gostar