1/23 Informationsverarbeitung im Bauwesen Einführung in das Programmieren mit C++ Markus Uhlmann Institut für Hydromechanik Karlsruher Institut für Technologie www.ifh.kit.edu WS 2010/2011 Vorlesung 6
2/23 6. VORLESUNG Datenfelder Advice: Take care not to write beyond the bounds of an array. B. Stroustrup
3/23 Fragen, die in dieser Vorlesung diskutiert werden Wie kann man Sequenzen von Daten darstellen? Wie können einzelne Datenelemente angesprochen und verarbeitet werden? Wie behandelt man mehrdimensionale Felddaten?
4/23 Notwendigkeit von Datenfeldern & Funktionen Wiederholte Daten gleichen Typs lineare Algebra (Gleichungssysteme) Zeitreihen (z.b. Messdaten) Bilddaten,... Anforderungen Ansprechen einzelner Elemente (Indizierung) Bestimmung der Anzahl der Elemente,... effiziente Operationen über ganze Felder
5/23 Definition Datenfeld & Funktionen Feld (array): Sequenz von Speicheradressen, welche jeweils den gleichen Datentyp aufnehmen können. einzelne Speicheradresse des Feldes wird als Element bezeichnet Elemente sind im Speicher konsekutiv abgelegt (ohne Lücken )
6/23 Definition von Datenfeldern in C++ Syntax (Definition): <Typ> <feldname> [ <feldlaenge> ]; & Funktionen Bsp: int vec[4]; //Feld mit 4 Elementen Definition: wie einzelne Variable, Feldlänge in eckigen Klammern Indizierung: Elemente zählen von 0 bis Länge - 1! Bsp: 1 int main(){ 2 int vec[4]; 3 vec[0]=-2; 4 vec[1]= 4; 5 vec[2]=-5; 6 vec[3]= 7; 7 return 0;} (Quelltext) Element Speicheradresse Wert (Bsp.) vec[0] 0xbffff7e4-2 vec[1] 0xbffff7e8 4 vec[2] 0xbffff7ec -5 vec[3] 0xbffff7f0 7
7/23 & Funktionen Definieren und Benutzen von Beliebige Datentypen int ifeld[6]; float ffeld[6]; Bei Zugriff muss ganzzahliger Index verwendet werden int a=3, b=4; float fvec[100]; fvec[a+b]=9.5; // fvec[7]=9.5 Feldelemente sind r-werte : können zugewiesen werden float g=fvec[8] * 2;
8/23 Initialisierung von Feldern & Funktionen Möglichkeiten der Initialisierung 1. Definition mit Initialisierungsliste int vec[4]={-2, 4, -5, 7}; int vec[4]={-2, 4};//OK: fehlende Elemente= 0 int vec[4]={}; //OK: alle Elemente = 0 int vec[2]={1,2,3};//*falsch*, zu viele Elemente 2. Initialisierung durch explizite Anweisungen (z.b. Schleife) 1 int vec[4]; 2 for (int i=0; i<=3; i++){ 3 vec[i]=i*2; 4 }
9/23 & Funktionen : Summieren der Elemente eines Vektors 1 #include <iostream> 2 #include <cmath> 3 4 const int vecleng = 5; //Konstante: Vektorlaenge 5 6 int main() 7 { 8 float feld[vecleng]; //Vektor "feld" mit "vecleng" Elementen 9 float sum=0.0; //Summe der Werte der Elemente von "feld" 10 int i; //Zaehler 11 for(i=0; i<vecleng; i++) (Quelltext) 12 { 13 feld[i]=pow(i,2);//zuweisen der Werte des Feldes 14 } 15 for(i=0; i<vecleng; i++)//was passiert bei <= statt <? 16 { 17 sum = sum +feld[i];//aufsummieren 18 } 19 std::cout << "Summe: " << sum << std::endl; 20 return 0; 21 }
10/23 Überschreiten der Feldlänge & Funktionen Index ausserhalb der Dimension des Feldes unberechtigter Speicherzugriff, unvorhersehbare Folgen int a; int vec[4]; a=vec[3]; //OK a=vec[4]; //*FALSCH* vec[4]=10; //*FALSCH* Überschreiten der Länge wird vom Compiler nicht erkannt führt zu Fehlern oder unerklärlichem Verhalten bei Programmlauf häufiger Fehler: fencepost (Zaunelemente=Pfosten-1) Möglichkeit der Fehlererkennung durch den Befehl assert
zu assert & Funktionen 1 #include <iostream> 2 #include <cmath> 3 #include <cassert> 4 const int vecleng = 5; //Konstante: Vektorlaenge 5 int main() 6 { 7 float feld[vecleng]; //Vektor "feld" mit "vecleng" Elementen 8 float sum=0.0; //Summe der Werte der Elemente von "feld" 9 int i; //Zaehler 10 for(i=0; i<vecleng; i++) 11 { 12 assert(i<vecleng); (Quelltext) 13 assert(i>=0); 14 feld[i]=pow(i,2);//zuweisen der Werte des Feldes 15 } 16 for(i=0; i<=vecleng; i++)//*fehler*: <= statt < 17 { 18 assert(i<vecleng); 19 assert(i>=0); 20 sum = sum +feld[i];//aufsummieren 21 } 22 std::cout << "Summe: " << sum << std::endl; 23 return 0;} 11/23
12/23 Fehlervermeidung mit assert & Funktionen assert kann z.b. Grenzüberschreitungen aufdecken helfen aber: assert führt zu geringer Effizienz des Programmes sollte nur in der Entwicklungsphase eingesetzt werden
13/23 und Funktionen & Funktionen Funktionen sind wichtige Werkzeuge zur Strukturierung Aber: liefern nur einen Rückgabewert Parameterübergabe i.a. durch call-by-value Wie kann man Feldwerte in Funktionen modifizieren? Felder werden nicht als Wert übergeben (call-by-reference) Übergabe von Feldparametern erfolgt als Referenz Werte an ursprünglicher Speicheradresse veränderbar (mehr zu Referenzen und Zeigern in Vorlesung 10)
14/23 & Funktionen Übergabe von Feldparametern an Funktionen Funktionsdefinition: <funktionstyp> <funktionsname> (...,<feldtyp> <feldname>[ ],... ) { <Anweisungen> return <Audruck>; } Aufruf: <funktionsname> (...,<feldname>,...) bei Definition wird Parameter durch [] als Feld identifiziert Funktionsaufruf durch Name der Feldvariable (ohne [])
zu Feldern & Funktionen & Funktionen 1 #include <iostream> 2 #include <cmath> Bsp: 3 const int vecleng = 5; //Konstante: Vektorlaenge 4 void square_vec(float vec[], int leng) 5 { //Funktion zum Quadrieren eines Vektors der Laenge len eines Vektors. 6 for(int i=0; i<leng; i++) 7 {vec[i]=pow(vec[i],2);} Ausgabe: 8 return ;} Wert der Elemente des 9 int main() Vektors: 10 { 0: 0 11 float feld[vecleng]; //Vektor "feld" mit "vecleng" 1: 2 Elementen 12 int i; //Zaehler 2: 4 13 std::cout << "Wert der Elemente des Vektors: " 3: 6 << std::endl; 14 for(i=0; i<vecleng; i++) 4: 8 15 { Quadrat der Elemente des 16 feld[i]=2*i;//zuweisen der Werte des Feldes Vektors: 17 std::cout << i << ": " << feld[i] << std::endl; 0: 0 18 } 1: 4 19 square_vec(feld,vecleng); 2: 16 20 std::cout << "Quadrat der Elemente des Vektors: " 3: 36 << std::endl; 21 for(i=0; i<vecleng; i++) 4: 64 22 {std::cout << i << ": " << feld[i] << std::endl;} 23 return 0;} (Quelltext) Berechnung des Quadrates der Werte von Elementen 15/23
& Funktionen Übergabe ganzer Felder vs. einzelner Elemente Felder: call-by-reference, Feldelemente: call-by-value Übergabe von ganzen Feldern erfolgt als Referenz Übergabe von einzelnen Elementen erfolgt als Wert Bsp: 1... 2 void square_element(float element) 3 { //diese Funktion hat keine Wirkung 4 element=pow(element,2); //*FALSCH* 5 return ;} 6 int main() 7 { 8 float feld[vecleng]; //Vektor "feld" 9... 10 square_element(feld[2]); //*FALSCH* 11...} legaler Code, aber wirkungslos (Quelltext) 16/23
17/23 & Funktionen Konstanter Feldparameter in Funktionen Vermeidung ungewollten Überschreibens Funktionsparameter können als konstant definiert werden dadurch ist eine Veränderung innerhalb der Funktion illegal Bsp: void square_vec(const float vec[], int leng) { for(int i=0; i<leng; i++) {vec[i]=pow(vec[i],2);} //*FALSCH* return ; } Compiler erkennt Fehler: versuchte Änderung von Konstante
18/23 Felder mit mehreren Dimensionen & Funktionen Bisher: eindimensionales Feld (Vektor) 1D Felder besitzen eine Länge (Anzahl Elemente), einen Index z.b. Zeitreihe von Temperaturdaten an einer Messstelle Mehrdimensionales Feld eine Länge und einen Index pro Dimension z.b. 2D: Temperaturdaten über Zeit, versch. Messstellen Indizierung über wiederholte Klammern: feld2d[i][j]
19/23 : zweidimensionales Feld 1 #include <iostream> 2 #include <cmath> 3 & Funktionen 4 const int feldleng1 = 2; //Konstante: 1. Felddimension (Zeile) 5 const int feldleng2 = 3; //Konstante: 2. Felddimension (Spalte) 6 7 int main() 8 { 9 float feld[feldleng1][feldleng2]; //2D Feld mit feldleng1 x feldleng2 10 int i,j; //Zaehler 11 for(i=0; i<feldleng1; i++) (Quelltext) 12 { 13 for(j=0; j<feldleng2; j++) 14 { 15 feld[i][j]=i+j*2;//zuweisen der Werte des Feldes 16 std::cout << "i=" << i << " j=" << j << 17 " : "<< feld[i][j] << std::endl; 18 } 19 } 20 return 0; 21 }
20/23 & Funktionen Initialisierung von mehrdimensionalen Feldern Definition mit Initialisierungsliste jede Zeile wird in geschweifte Klammern gesetzt, Zeilen getrennt durch Kommas int vec[2][3]={{-2, 4, 3},{-5, 7, 1}}; falls Trennung der Zeilen ausgelassen, zeilenweises Initialisieren: int vec[2][3]={-2, 4, 3, -5, 7, 1}; //aequivalent fehlende Elemente werden mit Nullen intialisiert: int vec[2][3]={-2, 4, 3, -5, 7}; //implizit: vec[1][2]=0
21/23 Speichersequenz von Felddaten & Funktionen Welche Elemente sind Nachbarn im Speicher? in C++ (und C) werden Felddaten entlang der letzten Dimension an benachbarten Speicherplätzen abgelegt Vergleich: umgekehrt in FORTRAN und Visual Basic Warum ist es wichtig Nachbarschaft zu kennen? Reihenfolge von verschachtelten Schleifen ist wichtig für die Effizienz in C++/C sollte möglichst die innerste Schleife über die letzte Dimension laufen schnellerer Code bei großen Längen (Quelltext)
22/23 & Funktionen & Funktionen Übergabe von mehrdimensionalen Feldern mehrfache eckige Klammern in Funktionsdefinition Länge der einzelnen Dimensionen wird angegeben Angabe der ersten Dimension nicht notwendig Bsp: void funktion(int vec[][n2][n3],int n1); //Funktionsprototyp... int ivec[2][3][4]; //Felddefinition... funktion(ivec,2); //Funktionsaufruf Compiler kann Indizierung in Speichersequenz umwandeln Dimensionen müssen Compiler bekannt sein (Quelltext)
23/23 Partikelsimulation programm: Partikelsimulation Erweiterung des Programmes aus Vorlesung 5 Bewegung von multiplen Partikeln Vektoren Behandlung von Partikelkollisionen Quelltext: Linux, Windows
1/3 Anhang Zusammenfassung Literatur Zusammenfassung Datenfelder liefern konsekutiven Speicher für Daten gleichen Typs Definition wie (skalare) Variablen, mit Längenangabe mehrere Dimensionen möglich Indizierung über eckige Klammern Verwendung in Funktionen, Übergabe per Referenz Überschreiten der Grenzen möglich, häufiger Fehler
2/3 Anhang Zusammenfassung Literatur Anhang
3/3 Anhang Zusammenfassung Literatur Weiterführende Literatur S. Prata, C++ Primer Plus, Sams, 2005 S. Oalline, Practical C++ Programming, O Reilly, 2003 J. Liberty and B. Jones, Teach yourself C++ in 21 days, Sams publishing, 2005 R. Lischner, C++ in a Nutshell, O Reilly, 2003 Handbücher erhältlich am Rechenzentrum: (Weblink) RRZN, Die Programmiersprache C, 17. Auflage, 2008 RRZN, C++ für C Programmierer, 13. Auflage, 2005 Online Dokumentation zum C++ Standard (Weblink) (freie) Microsoft Software für Studenten am KIT: (Weblink)