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

// Datenstruktur deklarieren
struct FloatVec {
	float *vecPtr;	// Zeiger auf ein float-Feld
	int maxmem;	// max. verfuegbare Elemente
	int used;	// belegte Elemente
};

// Vektor initialisieren
void fv_init(FloatVec& v, int maxmem=10)
{
	// neues Speicherfeld erzeugen (alle automatisch 0.0)
	v.vecPtr = new float[maxmem];
	// max. verfuegbare Elemente definieren
	v.maxmem = maxmem;
	// benutzte Elemente auf 0 setzen
	v.used = 0;
}

// den Vektorspeicher auf neue Groesse vergroessern
void fv_resize(FloatVec& v, int size)
{
	// nur vergroessern, wenn notwendig
	if( size <= v.maxmem)
		return;
	// neuen Speicher erzeugen
	float *temp = new float[size];
	// altes Feld in neuen Speicher laden
	for(int i=0; i<v.used; i++)
		*(temp+i) = v.vecPtr[i];
	// alten Speicher freigeben
	delete[] v.vecPtr;
	// vecPtr auf neuen Speicher zeigen lassen
	// temp verschwindet nach verlassen der Funktion
	v.vecPtr = temp;
	v.maxmem = size;
}

// einen Wert an den Vektor fuegen
void fv_append(FloatVec& v, float wert)
{
	// pruefen, ob Speicher vergroessert werden muss
	if( v.used == v.maxmem)
		fv_resize(v,v.maxmem+1);
	// Anzahl benutzter Elemente erhöhen
	v.used++;
	// neues Element einfuegen
	v.vecPtr[v.used-1] = wert;
}

// Vektor ausgeben mit gegebener Genauigkeit
void fv_print(const FloatVec& v, int precision=2)
{
	// Anzahl Nachkommastellen festlegen
	cout.precision(precision);
	for(int i=0; i<v.used; i++)
	{
		// max. 3 Zahlen pro Zeile
		if(i%3 == 0)
			cout << endl;
		// Darstellung im 15 Zeichen breiten Spalten
		// und in Gleitpunktdarstellung
		cout << setw(15) << fixed << v.vecPtr[i];
		// Adressen der Elemente im Speicher ausgeben
		cout << "(" << &v.vecPtr[i] << ")";
	}
	cout << endl;
}

// Vektor leeren
void fv_delete(FloatVec& v)
{
	// Speicherfeld freigeben
	delete[] v.vecPtr;
	// Anzahl benutzter Elemente auf 0 setzen
	v.used = 0;
	// max. verfuegbare Elementanzahl auf 0 setzen
	v.maxmem = 0;
}

// Vektorelement zurueckliefern
float fv_get(const FloatVec& v, int pos)
{
	// wenn angegebene Position die Obergrenze einhaelt
	if(pos < v.used)
		return v.vecPtr[pos];
	else{
		cout 	<< "Grenze fuer pos in fv_get() ueberschritten!" 
			<< endl;
		return 0;
	}
}

// Vektorelement loeschen
void fv_remove(FloatVec& v, int pos)
{
	// pruefen, ob Element an Position existiert
	if(pos < v.used){
		// Elemente ab pos+1 nach links shiften
		for(int i=pos; i<v.used-1; i++)
			v.vecPtr[i] = v.vecPtr[i+1];
		// nachfolgende Elemente nicht mehr beachten
		v.used--;
	}
	else{
		cout 	<< "Grenze fuer pos in fv_remove ueberschritten!"
			<< endl;
	}
}

// Vektorelement an bestimmter Position einfuegen
void fv_insert(FloatVec& v, int pos, float wert)
{
	// pos kann nur bis v.used-1 gehen,
	// ansonsten ist fv_append() zu nutzen
	if(pos < v.used){
		// pruefen, ob noch Platz im Vektor,
		// ansonsten vergrössern
		if(v.used+1 > v.maxmem)
			fv_resize(v,v.maxmem+1);
		// Elemente ab pos nach rechts shiften
		for(int i=v.used-1; i>pos; i--)
			v.vecPtr[i] = v.vecPtr[i-1];
		// neues Element an pos eintragen
		v.vecPtr[pos] = wert;
		// Anzahl benutzter Elemente erhoehen
		v.used++;
	}
	else{
		cout 	<< "Grenze fuer pos in fv_insert ueberschritten!"
			<< endl;
	}
}

int main()
{
	// Objekt erstellen
	FloatVec fv;
	// Objekt initialisieren mit Reserve von 20 Plaetzen
	fv_init(fv,5);
	// Vektor mit 0.1 bis 1.7 fuellen
	for(float i=0.1; i<2.0; i+=0.4)
		fv_append(fv,i);
	// Vektor ausgeben
	fv_print(fv,5);
	// Vektor um einen Wert erweitern
	cout << "\nHaenge Wert 123.45 an..." << endl;
	fv_append(fv,123.45);
	// Vektor ausgeben
	fv_print(fv,2);
	
	// ein Element ausgeben
	cout << "\nElement an Position 3: " << fv_get(fv,3) << endl;
	// ein Element loeschen

	fv_remove(fv,3);
	cout << "\nEntferne Element an Position 3..." << endl;
	// Vektor ausgeben
	fv_print(fv,2);

	// ein Element einfuegen
	cout << "\nFuege 45.678 an Position 3 ein..." << endl;
	fv_insert(fv,3,45.678);
	// Vektor ausgeben
	fv_print(fv,2);

	// Vektor loeschen
	fv_delete(fv);
}

