CD5250 - Objektorienterad programutveckling med C++, 5 poäng, period 4, 2001

STL-introduktion

intro

STL är en förkortning av standard template library. Det är ett antal klasser som erbjuder funktionalitet för att lösa vanliga problem som programmerare ställs inför. Dessa klasser underlättar implementationsdelen vid skapande av program. Istället för att implementera länkade listor, stackar m.m. för varje enskilt program, så har skaparna av STL gjort ett antal klasser som oftast är tillräckligt generella för att kunna återanvändas i alla program som använder sig av de vanligaste algoritmerna. Dessa klasser har dessutom fördelen att vara effektiva och väl testade. STL gör att programmeraren kan koncentrera sig på att välja bra datastrukturer istället för att bekymra sig om hur han/hon skall implementera dessa.

Som namnet antyder så är STL baserat på templates. Templates tas upp grundligare först en bit in på kursen, därför kommer vi inte att gå in på så mycket detaljer om de olika delarna i STL. Vi kommer här att gå igenom ett antal exempel på hur man använder STL i enklare fall. Där STL skall användas i labbarna kommer dess deklarationer finnas beskrivna i labbuppgiften. Det krävs dock en del studerande för att få en förståelse för hur STL fungerar och skall användas och det är därför viktigt att förstå de nedan följande exemplen.

A. string

Stränghantering är väldigt krångligt i C, man måste allokera minne, avallokera dessa korrekt, krångligt att skapa sammanfogade strängar, skicka char-pekare o.s.v. I STL finns klassen string som hanterar alla möjliga önskvärda funktioner som rör strängar.

Det är mycket enkelt att hantera strängar med STL. Här nedan följer ett utdrag av delar av gränssnittet för string-klassen, efteråt följer några enkla strängexempel.

I dessa exempel så är s, x och y string-objekt, dessutom är k och n heltal (int)
s = x Kopierar innehållet i sträng s till sträng x
s += x Lägger till x i slutet av s
s = x + y Tilldelning av den sammanslagna strängen x+y. Varken x eller y påverkas av denna operation
s == x, s != x Likhetsjämförelser. Jämför sträng s med sträng x
s.append(x) Lägger till x i slutet av s (samma som "+=")
s[k] Returnerar den bokstav (char) som finns på position k i strängen s (samma som "at").
Fungerar precis som vanlig array-indexering
s.at(k) Returnerar den bokstav (char) som finns på position k i strängen s
s.c_str() Returnerar en "char *" motsvarande strängen i s
s.find(x) Letar efter en förekomst av x i strängen s. Returnerar positionen för första bokstaven
s.length() Returnerar längden på s (int)
s.substr(k,n) Returnerar ett nytt string-objekt som är en delsträng av s, med början i position k och längden n
cout << s Skriver ut s till skärmen
cin >> s Läser in tecken från tangentbordet, slutar vid vitt tecken
(mellanslag, nyrad och tab kallas för whitespace)
getline(cin, s) Läser in en hel rad till s från cin.
Observera att getline är en vanlig funktion och inte en medlemsfunktion

Rutan ovanför visar bara upp en liten del av vad som kan göras med string-objekten och är därför långt ifrån en komplett sammanställning.

#include <string>
#include <iostream>
using namespace std;

void main()
{
	string str;
	str = "En STL-sträng";
	cout << str;
}
Exempel 1.Enkel hantering av STL-strängar.

Detta exempel skriver inte helt oväntat ut strängen "En STL-sträng". Vi utökar denna till att skriva ut ett sammansatt meddelande.

#include <string>
#include <iostream>
using namespace std;

void main()
{
	string str("En STL-sträng. ");
	str.append("En till.");
	cout << str;
}
Exempel 2.Nästan lika enkel hantering av STL-strängar.

string-klassen sammanfogar strängarna till en enda sträng. Medlemsfunktionen append har även en synonym. Följande rader är således ekvivalenta

str.append("En till.");
och
str += "En till.";
#include <string>
#include <iostream>
using namespace std;

void func(string);

void main()
{
	string str("En STL-sträng. ");
	func(str);
}

void func(string param1)
{
	cout << param1;
}
Exempel 3.Skicka strängar som parametrar

Det är lätt att skicka strängar som parametrar till en funktion. Strängklassen tar automatiskt hand om eventuell kopiering av strängar m.m.

B. vector

Behållaren vector är en motsvarighet till en array i C. Fördelen med vector är att den kan växa dynamiskt. Det innebär att ingen bestämd storlek behöver sättas och att vektorn inte kan bli full. Den hanterar automatiskt minnesallokering för de dataelement som läggs in i vektorn.

Här nedan följer en kort sammanställning av några av de vanligast använda medlemsfunktionerna i vector.

I dessa exempel så är v ett vektor-objekt, x ett element (motsvarande int i vector<int>, eller float i vector<float>) string-objekt, k är ett heltal (int)
v[k] Returnerar det element som finns på plats k i vektorn v (samma som medlemsfunktionen "at")
v.at(k) Returnerar det element som finns på plats k i vektorn v
v.begin() Returnerar en iterator till det första elementet i vektorn.
Detta beskrivs noggrannare längre fram i kursen
v.clear() Tömmer vektor v på alla element
v.push_back(x) Lägger till ett element sist i vektorn
v.reserve(k) Reserverar ett antal platser i vektorn,
vilket gör att man kan använda vektorn som en vanlig array med "[]" indexering
v.size() Returnerar antalet element i vektorn

För att illustrera när en vector ger uppenbara fördelar framför arrayer med fasta storlekar skall vi läsa in en fil med ett okänt antal datavärden och lagra dessa i minnet.

#include <vector>		// Denna fil behövs för att kunna använda vector-klassen
#include <iostream>		// Deklarationer för streams (cin, cout m.m.)
#include <fstream>		// Deklarationer för filhantering

// detta gör att vi kan använda STL-klasserna
using namespace std;

void main()
{
	// öppna en fil från c:\
	ifstream data("c:\\values.dat");

	// skapa en vektor som skall innehålla double-värden.
	vector<double> vektor;

	// fortsätt så länge 'data' inte har nått slutet på dataströmmen
	while(!data.eof())
	{
		// variabler kan deklareras där de behövs i C++
		double value;

		// läs in en double från 'data' till 'value'
		data >> value;

		// lägg till det inlästa talet 'value' på sista plats i vektorn
		vektor.push_back(value);
	}
}
Exempel 4.Inläsning av en fil med okänt antal datavärden till en vector.

Om vi nu i efterhand vill ändra på programmet så att det läser in sina datavärden från tangentbordet istället för från en fil så behövs endast en liten justering. Byt ut raden

ifstream data("c:\\values.dat");
mot
istream & data = cin;
Observera skillnaden mellan ifstream och istream! Tryck Ctrl-Z för att avsluta inmatningen från tangentbordet (Ctrl-Z innebär samma sak som 'end-of-file' vilket får while-satsen att avsluta). cin är ett globalt objekt för inläsning från tangentbordet.

Programmet har nu gjort en inläsning av alla tal som fanns i filen values.dat eller som matats in från tangenbordet utan att vi har behövt bekymra oss om hur många som lästs in. För att kontrollera att alla tal verkligen finns i vektorn, kan vi skriva ett program som skriver ned alla tal i vektorn på en fil.

#include <vector>
using namespace std;

void main()
{
	ifstream data("c:\\values.dat");
	vector<double> vektor;

	while(!data.eof())
	{
		double value;
		data >> value;

		vektor.push_back(value);
	}

	ofstream ut("c:\\values2.dat");
	for(int i=0; i<vektor.size; i++)
	{
		ut << vektor.at(i);
	}
}
Exempel 5.Inläsning av en fil med okänt antal datavärden till en vektor, samt nedskrivning av dessa till en ny fil.

Om vi här vill ändra utskriften av värdena till att skriva ut dem på skärmen istället för på en fil så kan vi även här åstadkomma detta med en väldigt enkel förändring av programmet. But ut raden

ofstream ut("c:\\values2.dat");
mot
ostream & ut = cout;
Observera även här skillnaden mellan ofstream och ostream!

Mer information om STL och vektorer hittar ni exempelvis i STL-referensen i Visual C++.

CD5250
Nyheter
Kursinformation
Föreläsningar
Labbar
Projektuppgift
Redovisningar
STL-intro
Size-klassen
Visual C++
Kursplan
Schema
Aktuellt
Projektuppgift
Föreläsning 7
Laboration 6
Underrubriker
string
vector
Ansvarig lärare: Martin Skogevall - martin.skogevall@mdh.se
Senast uppdaterad: Wed May 16 21:18:16 GMT+02:00 2001