Skip to content
Snippets Groups Projects
Commit ba88d6fb authored by Eric Elfving's avatar Eric Elfving
Browse files

Filer från STL-föreläsning 2

parent f3e1d137
No related branches found
No related tags found
No related merge requests found
...@@ -5,6 +5,7 @@ Detta repo fylls på med exempelkod från föreläsningarna. ...@@ -5,6 +5,7 @@ Detta repo fylls på med exempelkod från föreläsningarna.
| Fil / Katalog | Beskrivning | Datum | | Fil / Katalog | Beskrivning | Datum |
| ------------- | ----------- | ----- | | ------------- | ----------- | ----- |
| STL-Intro | Visar ett litet exempel löst på flera olika sätt för att introducera standardbiblioteket | 2018-03-19 | | STL-Intro | Visar ett litet exempel löst på flera olika sätt för att introducera standardbiblioteket | 2018-03-19 |
| STL-examples | Korta exempel för att visa på delar av standardbiblioteket | 2018-03-26 |
| ptr.cc | Kort exempel på smartpekare (i form av ```unique_ptr```) | 2018-03-20 | | ptr.cc | Kort exempel på smartpekare (i form av ```unique_ptr```) | 2018-03-20 |
| sum.cc | En enkel mallfunktion för att addera två värden av någon typ | 2018-03-20| | sum.cc | En enkel mallfunktion för att addera två värden av någon typ | 2018-03-20|
| push.cc | En mallfunktion som anropar ```push_back``` på någon angiven container | 2018-03-20 | | push.cc | En mallfunktion som anropar ```push_back``` på någon angiven container | 2018-03-20 |
......
# STL Exempel
## Från föreläsningen 2018-03-26
Ett flertal korta exempel för att visa på delar av standardbiblioteket.
| Fil | Beskrivning |
| ---- | ----------- |
| [copy.cc](copy.cc) | Olika sätt att kopiera innehållet från en vector till en annan. Använder catch. |
| [stream_iterators.cc](stream_iterators.cc) | Strömiteratorer för att koppla strömmar till algoritmer |
| [insert_sorted.cc](insert_sorted.cc) | Läs heltal och stoppa in sorterat i en vector. Tre olika lösningar givna. |
| [insert_sorted_multiset.cc](insert_sorted_multiset.cc) | Samma problem som ovan löst med en annan container |
| [count_chars.cc](count_chars.cc) | Räkna förekomsten av tecken och skriv ut dem sorterat i bokstavsordning. Löses med ```vector<pair<char,int>>``` |
| [count_chars_map.cc](count_chars_map.cc) | Löser ovanstående problem med en map. |
| [str.cc](str.cc) | Litet exempel för att visa på att ```string``` har egna strängrelaterade medlemsfunktioner som jobbar med index. |
This diff is collapsed.
// Olika sett att kopiera innehållet från en vector till en annan
#include "catch.hpp"
#include <vector>
using namespace std;
// Funktion för att undersöka om innehållet är samma
bool same_content(vector<int> const & v1, vector<int> const & v2)
{
if ( v1.size() != v2.size() )
return false;
// algoritmlösning
return std::equal(begin(v1), end(v1), begin(v2));
// egen loop
/* for ( vector<int>::size_type idx{}; idx < v1.size(); ++idx )
{
if ( v1[idx] != v2[idx] )
return false;
}
return true;
*/
}
TEST_CASE("copy")
{
vector<int> v {1,2,3,4,5};
SECTION("Kopieringskonstruktor")
{
// bör föredras om vi har samma typ och ska skapa en ny kopia
vector<int> v2{v};
CHECK(same_content(v,v2));
}
/* två versioner som använder copy. copy ser ut ungefär såhär:
template <typename It1, typename It2>
void copy(It1 start, It1 stop, It2 dest)
{
while ( start != stop )
{
*dest = *start;
++start;
++dest;
}
}
copy kommer alltså alltid anta att intervallet som börjar med
dest alltid är minst lika stort som antalet element i [start, stop).
*/
SECTION("preallocated vector")
{
// copy kommer inte modifera v2s storlek. Vi måste se till att
// v2 är nog stor
vector<int> v2;
v2.resize(v.size());
copy(begin(v), end(v), begin(v2));
CHECK(same_content(v,v2));
}
SECTION("back_insert_iterator")
{
// alternativt använder vi en speciell iterator (back_insert_iterator)
// som anropar push_back när vi försöker tilldela den ett värde
vector<int> v2;
copy(begin(v), end(v), back_inserter(v2));
CHECK(same_content(v,v2));
}
SECTION("iterator")
{
// initiering med iterator. Fördelen med denna variant är att
// det inte måste vara samma typ. Kopieringskonstruktorn kräver
// att du kopierar från ett objekt av samma typ, denna
// konstruktor godkänner vilken Input-iterator som helst så
// länge typen på de värden de refererar till är korrekt.
vector<int> v2 { begin(v), end(v) };
CHECK(same_content(v,v2));
}
}
// program som använder en vector för att räkna förekomsten av tecken
// i en text och skriver ut dem i bokstavsordning
#include <iterator>
#include <algorithm>
#include <iostream>
#include <vector>
#include <utility>
#include <cctype>
using namespace std;
int main()
{
vector<pair<char, int>> characters;
for ( char c; cin.get(c); )
{
c = tolower(c);
// lower_bound hittar första elementet som är större eller
// lika med det vi söker efter (c). I detta anrop måste vi
// skicka med ett lambda som jämför eftersom vectorn inte
// innehåller char
auto it { lower_bound(begin(characters), end(characters), c,
[](pair<char,int> p, char c) { return p.first < c; })};
// om vi inte hittade något värde är it samma som end, annars
// vill vi antingen stoppa in ett nytt pair eller öka räknaren
if ( it == characters.end() || it->first != c )
{
characters.insert(it, make_pair(c, 1));
}
else
{
it->second++;
}
}
for ( auto p: characters )
{
cout << p.first << ": " << p.second << '\n';
}
}
// samma som count_chars.cc fast använder map som datastruktur
#include <algorithm>
#include <iostream>
#include <map>
#include <cctype>
/* ASDSAFSAFS */
using namespace std;
int main()
{
map<char,int> characters;
for ( char c; cin.get(c); )
{
c = tolower(c);
// map::operator[](key) kommer antingen ge en referens till
// värdet som är kopplat till den angivna nyckeln eller skapa
// ett default-initierat värde kopplat till nyckeln och returnera en referns till det.
// Eftersom vi får en referens kan vi öka det heltalet.
characters[c]++;
}
for ( auto p: characters )
{
cout << p.first << ": " << p.second << '\n';
}
}
// Sätt in ett värde sorterat i en vector
#include <algorithm>
#include <iostream>
#include <vector>
#include <iterator>
using namespace std;
size_t find_position(vector<int> const & v, int val)
{
for ( size_t pos{}; pos < v.size(); ++pos )
{
if ( v[pos] >= val )
return pos;
}
return v.size();
}
int main()
{
vector<int> values;
for ( int i; cin >> i; )
{
/* tre sätt att hitta rätt position och stoppa in */
// Enkel loop i en funktion
{
auto pos = find_position(values, i);
// insert kräver iterator... använd att vi har RandomAccess
auto it = begin(values) + pos;
values.insert(it, i);
}
// find_if. Använder linjärsökning (dvs stegar ett element i
// taget tills den hittar rätt position). lambda-uttrycket
// tar endast emot ett värde i taget från find_if (det
// algorimen undersöker för tillfället) och vi måste därför
// binda "i" i capture-delen (hakparenteserna).
{
auto pos = find_if(begin(values), end(values),
[i](int val) {
return val >= i;
});
values.insert(pos, i);
}
// lower_bound används på en sorterad mängd för att hitta
// första värdet som är större eller lika med det sökta.
// Använder binärsökning (halverar sökmängden varje iteration)
// detta är både effektivare, mer läsbart och säkrare!
{
auto pos { lower_bound(begin(values), end(values), i) };
values.insert(pos, i);
}
}
if ( is_sorted(begin(values), end(values) ) )
{
cout << "Sorterad" << endl;
}
}
// insert_sorted med ett multiset. Ett multiset håller alltid
// värden sorterade och till skillnad från std::set sparar den
// alla värden, inte endast unika.
#include <algorithm>
#include <iostream>
#include <set>
#include <iterator>
using namespace std;
int main()
{
multiset<int> values { istream_iterator<int>{cin},
istream_iterator<int> {} };
cout << values.size();
copy(begin(values), end(values),
ostream_iterator<int>{cout,"\n"});
if ( is_sorted(begin(values), end(values) ) )
{
cout << "Sorterad" << endl;
}
}
// kort exempel för att visa på att string har några egna medlemsfunktioner
// som är mer specifika än de generella algoritmerna.
#include <string>
#include <iostream>
using namespace std;
int main()
{
string s {"dlöjfdsö5f kdsl()d-%3saf" };
string const paren {"(){}[]"};
// find_first_of hittar första tecknet i s som finns i paren.
// returnerar indexet för detta tecken
auto pos = s.find_first_of(paren);
// om inget tecken hittades sätts pos till ett speciellt värde
// som är ett statiskt värdet i string, string::npos.
if ( pos != string::npos )
{
cout << "Tecken " << s[pos]
<< " fanns på index " << pos << endl;
}
}
// kort program som läser in ett valfritt antal tal, sorterar dem
// och skriver ut talen i stigande ordning.
#include <algorithm>
#include <iostream>
#include <vector>
#include <iterator>
using namespace std;
int main()
{
// en istream_iterator kopplar en ström till en iterator så att
// värden läses in formaterat (med >>) internt i iteratorn när
// den stegas. Vid avreferering får man det senast lästa värdet.
// En istream_iterator som inte är kopplad till en ström jämförs
// lika med en iterator som nått slutet (eller fått någon annan
// felflagga satt) i sin ström. Här läser vi alltså in alla värden
// i cin och lagrar dem direkt i values.
vector<int> values { istream_iterator<int>{cin},
istream_iterator<int>{} };
sort(begin(values), end(values));
cout << values.size();
// På samma sätt finns ostream_iterator för att skriva ut saker på
// en ström. Det andra argumentet är en delimiter, dvs en sträng
// som skrivs ut efter varje värde.
copy(begin(values), end(values),
ostream_iterator<int>{cout,"\n"});
}
#define CATCH_CONFIG_RUNNER
#include "catch.hpp"
int main(int argc, char* argv[])
{
return Catch::Session{}.run(argc, argv);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment