Klassen string stl F - 1 Det finns en ny typ för att hantera strängar, standardtypen string För att använda denna typ måste man inkludera headerfilen string, utan.h! Några operationer i string. s och s2 är av typen string och x är antingen av typen string eller ett vanligt teckenfält (char -fält) ==================================================================== s = x tilldelning s==x s!=x s<x jämförelse s+x ger ny string sammansatt av s och x s[k] indexering utan indexkontroll s.at(k) indexering med indexkontroll s.substr(k,n) ger en del av s, början i k och längden n s.length() ger längden av s s += x lägger till x av s s.remove(k,n) tar bort n tecken ur s med början i pos k s.insert(k,s2,k2,n) skjuter in n tecken i s med början i k kopierar från k2 i s2 s.replace(k,n,x) ersätter n tecken i s med början i k med innehållet i x s.replace(k,n,s2,k2,n2) ersätter n tecken i s med början i k med n2 tecken ur s2 med början i k2 cout << s skriver ut s cin >> s läser in s, slutar vid första blanktecken getline(cin, s) läser in hel rad till s Ett exempel med string stl F - 2 #include <string> string firstname; string lastname; string adress; Vad heter du? Zeke Varg Hej Zeke Varg Adress? Ensliga Skogen Namn: Zeke Varg Adress: Ensliga Skogen Din adress är mindre än ditt namn Antal tecken i namnet 9 cout << "Vad heter du? "; cin >> firstname >> lastname; cout << "Hej " << firstname << ' ' << lastname << endl; string namn = firstname; namn += " "; namn += lastname; cout << "Adress? "; cin >> ws; //Läser bort blanktecken getline(cin, adress); //Inläsning av en hel rad cout <<"\nnamn: "<< namn<< "\nadress: " << adress << endl; if (namn <= adress) cout << "Ditt namn är inte större än din adress"; else cout << "Din adress är mindre än ditt namn" << endl; cout <<"Antal tecken i namnet " <<namn.length() <<endl;
Ett exempel med string och dess iterator stl F - 3 #include <string> Vad heter du? Zeke Varg Zeke Varg ZEKE VARG string namn; cout << "Vad heter du? "; cin >> ws; getline(cin, namn); string::iterator i; for (i = namn.begin(); i!= namn.end(); i++) cout << *i; cout << endl; for (i = namn.begin(); i!= namn.end(); i++) if ( *i > 'Z' && *i!= ' ') *i -= 'a' - 'A'; for (i = namn.begin(); i!= namn.end(); i++) cout << *i; cout << endl; stl F - 4 Definition av namnrymder En namnrymd är en konstruktion som till formen påminner om en klass Konstruktionen inleds med det reserverade ordet namespace följt av namnrymdens namn, därefter kommer ett block som kan innehålla ett antal godtyckliga deklarationer #ifndef _special_ #define _special_ namespace specialare const int size = 100; void swap(double &a, double &b) double temp = a; a = b; b = temp; #endif
stl F - 5 Användning av namnrymder Variabler och funktioners synlighet är normalt begränsade till namnrymdens block. Det finns tre olika sätt att få tillgång till något som är deklarerat i en namnrymd Explicit namngivning Ge det fullständiga namnet vid varje användning namnrymdensnamn::namn Användningsdeklaration Deklarera en viss identifierare på den aktuella platsen using namnrymdensnamn::namn; Användningsdirektiv Gör hela namnrymden öppen using namespace namnrymndensnamn; Exempel med användning av namnrymder stl F - 6 ** EXEMPEL 1 ******************************* #include <iostream.h> #include "special.h" const int size = 6; double vek[size] = 0,1,2,3,4,5; for (int i=1; i<size/2; i++) specialare::swap(vek[i-1], vek[size-i]); for (int i=0; i<size; i++) cout << vek[i] << endl; ** EXEMPEL 2 ******************************* #include <iostream.h> #include "special.h" using specialare::swap; const int size = 6; double vek[size] = 0,1,2,3,4,5; for (int i=1; i<size/2; i++) swap(vek[i-1], vek[size-i]); for (int i=0; i<size; i++) cout << vek[i] << endl;
stl F - 7 Standard Template Library, STL I C++ har nyligen ett bibliotek adderas benämt Standrard Template Library Det biblioteket innehåller klasser och funktioner som täcker de vanligaste härledda datastrukturerna såsom stackar, köer och listor. I bibloteket finns även stöd för iteratorer och det förekommer även olika typer av generella algoritmer som kan tillämpas på datastrukturerna. STL, container klasser stl F - 8 I Standard Template Library förekommer det olika typer av datastrukturer: Container klass Beskrivning ==================================================================== Sequence Containers vector Snabb insättning och radering i slutet av vektorn, direkt access till alla element deque Dubbeländad kö. Snabb insättning och radering i början och slutet. Direkt access till alla element list dubbellänkad lista, snabb insättning och radering av element i hela listan Associative Containers set snabb sökning, inga dubbletter tillåtna multiset se set, dubletter tillåtna map ett till ett mappning, inga dubbletter tillåtna, snabb sökning med hjälp av söknyckel multimap se map, dubletter tillåtna Container Adapters stack Sist in Först ut kö Först in Först ut priority_queue Högst prioriterat element är alltid först ---------------------------------------------------------- Sequence och Associative Containers ingår i First-class containers
En klass som används i exemplen stl F - 9 #ifndef _person_ #define _person_ #include <cstring> class Person friend ostream & operator<<(ostream &ut, const Person & individ); public: Person(const char * = 0, int alder = 0); bool operator<(const Person &individ)const return age < individ.age; bool operator>(const Person &individ)const return age > individ.age; bool operator==(const Person &individ)const return age == individ.age; bool operator!=(const Person &individ)const return age!= individ.age; private: char name[80]; int age; ; ostream & operator<<(ostream &ut, const Person & individ) ut << "Namn: " << individ.name << "\tålder: " << individ.age << " år" << endl; return ut; Person::Person(const char *namn, int alder) if (namn!= 0) strcpy(name, namn); age = alder; #endif Exempel på tillämpning av en stack stl F - 10 #include <stack> #include "person.h" Person anna("anna", 10); Person beda("beda", 20); Person cesar("cesar", 30); Person david("david", 40); Person erik("erik", 50); stack< Person* > stacken; stacken.push(&anna); stacken.push(&beda); stacken.push(&cesar); stacken.push(&david); stacken.push(&erik); while(!stacken.empty()) cout << *stacken.top(); stacken.pop(); Namn: Erik ålder: 50 år Namn: David ålder: 40 år Namn: Cesar ålder: 30 år Namn: Beda ålder: 20 år Namn: Anna ålder: 10 år
Exempel på tillämpning av en kö stl F - 11 #include <queue> #include "person.h" Person anna("anna", 10); Person beda("beda", 20); Person cesar("cesar", 30); Person david("david", 40); Person erik("erik", 50); queue<person *> thequeue; thequeue.push(&anna); thequeue.push(&beda); thequeue.push(&cesar); thequeue.push(&david); thequeue.push(&erik); while (!thequeue.empty()) cout << *thequeue.front(); thequeue.pop(); Namn: Anna ålder: 10 år Namn: Beda ålder: 20 år Namn: Cesar ålder: 30 år Namn: David ålder: 40 år Namn: Erik ålder: 50 år STL, medlemsfunktioner stl F - 12 #include <queue> #include "person.h" priority_queue<person> thequeue; typedef priority_queue<person>::value_type post; Person anna("anna", 20); Person cesar("cesar", 37); thequeue.push(anna); thequeue.push(person("beda", 5)); thequeue.push(post(cesar)); thequeue.push(post("david", 4)); thequeue.push(post("erik", 5)); while (!thequeue.empty()) cout << thequeue.top(); thequeue.pop(); Namn: Erik ålder: 5 år
STL, medlemsfunktioner stl F - 13 Några medlemsfunktioner som förekommer i containerklasserna är: Medlemsfunktion Beskrivning ==================================================================== Förekommer i samtliga containers empty Returnerar true om om det finns några element i containern i annat fall false max_size returnerar maximalt antal element som kan som kan förekomma i containern size Returnerar aktuellt antal element operator= Tilldelar en container en annan container Dessa funktioner förekommer ej i priority_queues operator< samtliga logiska operatorer är operator<= överlagrade vilket gör det möjligt att osv. jämföra en container mot en annan Dessa funktioner förekommer endast i first-class containers begin returnerar en iterator som refererar till första elementet i containern end returnerar en iterator som refererar till första positionen efter sista elementet! rbegin Dessa båda funktioner är avsedda att rend användas tillsammans med en reverse_iterator erase Raderar ett eller flera element i containern clear Raderar samtliga element i containern ---------------------------------------------------------- Ett exempel med vector stl F - 14 #include <vector> Size: 5 Capacity: 5 double tal = 0.5; vector<double> datavek(5); vector<double>::size_type i; cout << "Size: " << datavek.size() << endl; cout << "Capacity: " << datavek.capacity() << endl << endl; for (i=0; i<7; i++) datavek[i] = tal++; cout << "Size: " << datavek.size() << endl; cout << "Capacity: " << datavek.capacity() << endl << endl; tal = 5.5; for (i=5; i<7; i++) datavek.push_back(tal++); Size: 5 Capacity: 5 Size: 7 Capacity: 10 datavek: 0.5 datavek: 1.5 datavek: 2.5 datavek: 3.5 datavek: 4.5 datavek: 5.5 datavek: 6.5 it: 0.5 it: 1.5 it: 2.5 it: 3.5 it: 4.5 it: 5.5 it: 6.5 cout << "Size: " << datavek.size() << endl; cout << "Capacity: " << datavek.capacity() << endl << endl; for (i=0; i<datavek.size(); i++) cout << "datavek: " << datavek[i] << endl; vector<double>::const_iterator it; for (it = datavek.begin(); it!=datavek.end(); it++) cout << "it: " << *it << endl;
STL, typedef stl F - 15 Med hjälp av containerklassernas typdefinitioner är det möjligt att deklarera variabler som refererar eller pekar på element i containern: typedef Beskrivning ==================================================================== value_type Den typ som är lagrad i containern reference En referens till den typ av element som är lagrade const_reference En konstant deklarerad referens till elementen... pointer En pekare till elementen... iterator En iterator som pekar på elementen const_iterator En konstantdeklarerad iterator reverse_iterator En iterator för omvänd traversering av elementen const_reverse_iterator difference_type Den typ som erhålls när man subtraherar två iteratorer från varandra, som refererar till samma container size_type Den typ somanvänds för att räkna element i containern och indexera sig igenom en sequence container ---------------------------------------------------------- Olika typer av iteratorer stl F - 16 input output forward bidirectional random access --------------------------------------------------- Secuence containers vector random access dequeue random access list bidirectional Associative containers set bidirectional map bidirectional Container adapters stack no iterators supported queue no iterators supported priority_queue no iterators supported
Typer av iteratorer och deras operatorer stl F - 17 Alla iteratorer ++p, p++ Input Iteratorer som enbart kan läsa *p, p=p1, p==p1, p!=p1 Output Iteratorer som enbart kan skriva *p, p=p1 Forward Iteratorer som kan gå framåt Dessa operatorer har den funktionalitet som finns för de föregående typerna Bidirectional Iteratorer som kan röra sig i båda riktningarna Dessa operatorer har den funktionalitet som finns för de föregående typerna samt --p, p-- Random access Iteratorer som kan röra sig i godtyckligt Dessa operatorer har den funktionalitet som finns för de föregående typerna samt p+=i, p-=i, p+i, p-i, p[i], p<=p1, p>p1, p>=p1 Exemplet med vektorn, nu med en utskrift-iterator stl F - 18 #include <vector> #include <algorithm> double tal =0.5; vector<double> datavek; vector<double>::size_type i; dataveks storlek: 0 dataveks storlek: 10 datavek[6]: 6.5 data[6]: 6.5 Innehållet med utströmiteratorn 0.5 1.5 2.5 3.5 4.5 5.5 6.5 cout << "dataveks storlek: " << datavek.capacity() << endl; for (i=0; i<7; i++) datavek.push_back(tal++); cout << "dataveks storlek: " << datavek.capacity() << endl; cout << "datavek[6]: " << datavek[6] << endl; vector<double>::const_iterator data = datavek.begin(); cout << "data[6]: " << data[6] << endl; ostream_iterator<double> ut(cout, " "); cout << "Innehållet med utström-iteratorn" << endl; copy(datavek.begin(), datavek.end(), ut);
Exempel på tillämpning av en lista, del 1 stl F - 19 #include <list> #include "person.h" Före insert av erik pekar iteratorn på: Efter insert av erik pekar iteratorn på: list<person> listan; listan.push_front(person("anna", 20)); listan.push_front(person("beda", 5)); listan.push_back(person("cesar", 37)); listan.push_back(person("david", 4)); list<person>::iterator i = listan.begin(); while (i!= listan.end()) cout << *i++; i = listan.begin(); i++; i++; cout << endl << "Före insert av erik pekar iteratorn på: " << endl << *i; listan.insert(i,person("erik", 5)); cout << "Efter insert av erik pekar iteratorn på: " << endl << *i; Exempel på tillämpning av en lista, del 2 stl F - 20 Hela listan skrivs ut igen Namn: Erik ålder: 5 år Hela listan skrivs ut efter att den tredje personen har raderats cout << endl << "Hela listan skrivs ut igen" << endl; for (i = listan.begin(); i!= listan.end(); i++) cout << *i; i = listan.begin(); i++; i++; listan.erase(i); cout << endl << "Hela listan skrivs ut efter att den tredje" << " personen har raderats" << endl; for (i = listan.begin(); i!= listan.end(); i++) cout << *i;
Exempel på tillämpning av en lista, del 3 stl F - 21 Hela listan skrivs ut efter att den har sorterats Hela listan skrivs ut efter att alla noder har raderats listan.sort(); cout << endl << "Hela listan skrivs ut efter att den har" << "sorterats" << endl; for (i = listan.begin(); i!= listan.end(); i++) cout << *i; listan.clear(); cout << endl << "Hela listan skrivs ut efter att alla" << " noder har raderats" << endl; for (i = listan.begin(); i!= listan.end(); i++) cout << *i; Containertypen map stl F - 22 #include <map> #include <string> Namn: Anka Kajsa telefonnummer: 89732 Namn: Anka Kalle telefonnummer: 13131 Namn: Pigg Mimmi telefonnummer: 34578 Namn: Pigg Musse telefonnummer: 12345 Kalle Anka har telefonnummer: 13131 map<string, int> telefonlista; typedef map<string, int>::value_type post; telefonlista.insert(post("pigg Musse", 12345)); telefonlista.insert(post("anka Kalle", 13131)); telefonlista.insert(post("pigg Mimmi", 34578)); telefonlista.insert(post("anka Kajsa", 89732)); map<string, int>::const_iterator it; for (it=telefonlista.begin(); it!= telefonlista.end(); it++) cout << "Namn: " << it->first << "\ttelefonnummer: " << it->second << endl; //Returnerar defaultvärdet för integer dvs 0, om inte posten //med den sökta stränen finns. if (telefonlista["anka Kalle"]) cout << "Kalle Anka har telefonnummer: " << telefonlista["anka Kalle"] << endl;
Ett exempel med tillämpningar av några algoritmer, del 1 stl F - 23 #include <list> #include <vector> #include <algorithm> #include "person.h" Namn: Erik ålder: 5 år Personen med åldern 37 år hittades, vector<person> vektorn; vektorn.push_back(person("anna", 20)); vektorn.push_back(person("beda", 5)); vektorn.push_back(person("cesar", 37)); vektorn.push_back(person("david", 4)); vektorn.push_back(person("erik", 5)); Person individer[5]; list<person> listan(individer, individer+5); //KOPIERING copy(vektorn.begin(), vektorn.end(), listan.begin()); ostream_iterator<person> screen_pers(cout); copy(listan.begin(), listan.end(), screen_pers); //SÖKNING list<person>::iterator i = find(listan.begin(), listan.end(), Person("knas", 37)); if (i!= listan.end()) cout << "Personen med åldern 37 år hittades,\n" << *i << endl; else cout << "Någon person med åldern 37 år finns inte i listan" << endl; Ett exempel med tillämpningar av några algoritmer, del 2 stl F - 24 Namn: Erik ålder: 5 år 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, //SORTERING sort(vektorn.begin(), vektorn.end()); copy(vektorn.begin(), vektorn.end(), screen_pers); //ETT VANLIGT FÄLT MED HELTAL int heltal[] = 8, 3, 1, 6, 9, 0, 7, 4, 5, 2; const int antal = sizeof(heltal)/sizeof(int); //ALGORITMER TILLÄMPADE PÅ VANLIGA FÄLT sort(heltal, heltal+antal); ostream_iterator<int> screen_int(cout, ", "); copy(heltal, heltal+antal, screen_int); cout << endl; //INITIERA EN CONTAINER MED ETT VANLIGT FÄLT vector<int> talen(heltal, heltal+antal); copy(talen.begin(), talen.end(), screen_int); cout << endl;