Interpreter und Compiler Programmierung I Von Python nach C++ Wintersemester 2004/2005 University Bonn Dr. Gabriel Zachmann 2 Arten der Programmausführung Compiler := Tool (Programm) das Source-Code übersetzt in Maschinen-Code (object code); dieser kann dann auf der Zielmaschine ausgeführt werden. Interpreter := Tool das Source-Code ausführt, konzeptionell Zeile für Zeile. Virtuelle Maschine := Hybrid Jede Hochsprache kann durch eine der 3 Arten ausgeführt werden C++ wird üblicherweise compiliert (Tool = 'g++') Python wird interpretiert (daher "Skriptsprache"; Tool = 'python') Wie entsteht ein compiliertes Programm Edit-Compile-Debug-Zyklus Sie ClassName.cpp ClassName.h ASCII Editor C++ source ClassName.o Analyze, check consistency, generate code Compiler Libraries Link further classes Linker Platform-dependent! execute, test, debug ProgName.exe Executable Processor Programmieren geschieht in einem Zyklus Source Program Compile Library routines Edit Link Other object files Think Load Execute Compilieren mit g++ (von Hand) Hello World tahiti: zach% g++ -ffor-scope Wall W -Wold-style-cast -Woverloaded-virtual -Wfloat-equal -Wshadow myprogram.cpp o myprogram Alias definieren: alias gpp 'g++ -Wshadow' Verwendung: gpp myprogram.cpp o myprogram Komfortableres Alias: alias gpp 'g++ -Wshadow \!#:1 o \!#:1:r' gpp myprogram.cpp 1 Zeile! Preprocessor directives Programm startet hier; eine Fkt main() muß immer vorhanden sein. // Program: Display greetings // Author(s): Ima Programmer // Date: 1/24/2001 # Program: Display greetings #include # Author(s): <stdlib.h> Ima Programmer #include # Date: <stdio.h> 1/24/2001 intimport main( sys int argc, char *argv[] ) print puts("hello world!"); Ends execution of main(), which ends program Error code for calling process; 0 = everyting ok Kommentar Macht bestimmte "System calls" bekannt Funktionsaufruf 1
Style Guide Schlechtes Beispiel Kommentare! Leerzeilen zwischen sinnvollen Abschnitten // Program: Display greetings // Author(s): Ima Programmer // Date: 1/24/2001 int main( int argc, char *argv[] ) puts("hello world!"); Vertikale Ausrichtung! Einrückung = 4(!) Spaces! Leerzeichen innerhalb einer Zeile! int main(int argc,char*argv[]) puts("hello world!"); Benötigt zwar weniger Bytes auf der Platte, aber Kann keiner mehr lesen, besonders dann, wenn der File groß wird (oft 100-10000 Zeilen pro File) Nicht mehr wartbar! (wer hat schon Lust, solchen Code von jemand anders zu lesen?) Für mehr schlechte Beispiele siehe The International Obfuscated C Code Contest (http://www.de.ioccc.org/ ) Kleine syntaktische Unterschiede Der ternäre Operator (Bedingungsoperator) Kommentare: int x = 10; // Bedeutung der Variable /*. */ Anweisungen mit Semikolon abschließen: Zusätzliche Operatoren: Boolean Operators! unary not && logical and logical or x = i + j; Self-increment Equivalent to and decrement k = ++ j; j = j+1; k = j; k = j ++; k = j; j = j + 1; k = -- j; j = j - 1; k = j; k = j --; k = j; j = j - 1;? : Eigentlich Kontrollflußkonstrukt, verkappt als Operator cond? true-expr : false-expr Wert des Ausdrucks = Wert von true-expr, falls Wert von cond 0 Wert von false-expr, falls Wert von cond = 0 Keywords in C++ Beispiele: puts( x? "true" : "false" ); double max = (a>b)? a : b; printf("bestellung: %d %s\n", i, i == 1? "Baum" : "Bäume" ); Teilweise gleich, insgesamt sehr viel mehr keyword asm operator throw auto enum private true bool explicit protected try break extern public typedef case false register typeid catch float reinterpret_cast typename char for return union class friend short unsigned const goto signed using const_cast if sizeof virtual continue inline static void default int static_cast volatile delete long struct wchar_t do mutable switch while double namespace template dynamic_cast new this 2
Eingebaute (built-in) Typen Wertebereiche Nur Typen, die direkt in der CPU/FPU verarbeitet werden können: int long int float double long double unsigned int char bool single precision integer double precision integer single precision real double precision real extended precision real unsigned integer single character (a letter) logical variables Keine höheren Typen (strings, complex, list, ) String-Literale gibt es! Plattform-abhängig! Symbolische Konstanten für diese Bereiche: Bekommt man durch: #include <limits> Beispiele: #include <limits> using namespace std; int a = numeric_limits<int>::max(); char c = numeric_limits<char>::min(); float eps = numeric_limits<float>::epsilon(); Ausgabe auf stdout Ausgabe auf stderr Einzelnes Zeichen: Zeichenkette: Eine Zeile: Formatiert: putchar('x'); char c; putchar(c); puts("text"); puts( zeiger-auf-string ); Formatiert: fputs( "text", stderr ); fputs( zeiger-auf-string, stderr ); fprintf( stderr, "format-string", arg1, arg2, ); printf( "format-string", arg1, arg2, ); Befinden sich in der sog. libc (C standard library, glibc); wird immer automatisch dazugelinkt Lesen von stdin Einzelnes Zeichen Ganze Zeile Formatiert char c; c = getchar(); gets( zeiger-auf-string ); scanf( "format-string", arg1, arg2, ); Formatstring (fast) wie bei printf Achtung: am Schluß niemals \n lesen wollen! Beispiele zu scanf: printf("geben Sie den Vektor ein: "); float v1, v2, v3; scanf( "%f %f %f", &v1, &v2, &v3 ); Zahlen durch Space getrennt eingeben Space im Formatstring matcht beliebig viele Whitespaces! Werte lesen bis Input leer: float f; int success = scanf("%f", &f ); while ( success == 1 && success!= EOF ) // do something success = scanf("%f", &f ); Man-Page: scanf liefert EOF falls kein Input mehr da 3
Kontrollstrukturen if Block in C++: durch Einrückung hat in C++ keine Bedeutung Trotzdem unbedingt beibehalten! Beliebte Falle: a = 1; b = a*a; if ( i == 0 ) if ( a < 0 )... // will be executed only... // if a < 0!! if ( boolean-expr ) statement1; statement2; Statt statement kann Block stehen if ( punkte >= 90 ) note = 'A'; if ( punkte >= 85 ) note = 'B'; if ( punkte >= 70 ) note = 'C'; if ( punkte >= 50 ) note = 'D'; note = 'F'; while for (abgeleitet aus while) while ( condition ) statement ; i init = ; 0; while ( i < n ) ( test ) action ; ; i expr ++ ; Init und test werden immer mind. 1x ausgeführt for ( init ; test ; expr ) action ; Expr und action werden nicht notw. ausgeführt! // int b int a = 1; while ( a < b ) a *= 2; // float q; unsigned int n; float s = 0.0; // s = geom. Reihe 1 + q + q^2 + q^3 + + q^n float qq = 1.0; for ( unsigned int i = 0; i < n; i ++ ) s += qq; qq *= q; Schleifenvariable hier deklarieren! Scope von Deklarationen innerhalb des for-init: Nur For-Klammer und Rumpf der For-Schleife (action)! Unbedingt nutzen! Hat mir schon einige Stunden Bug-Suche erspart! Unterstützt das Prinzip der Daten-Lokalität bzw. des "information hiding" Wann for und wann while? For wenn Schleife über Integer-Bereich mit festen Grenzen While wenn Anzahl Durchläufe nicht klar (max. Anz. begrenzen!) for ( uint i = 0; ) // ab hier ist i wieder unbekannt! Scope von i 4
do while Gegenüberstellung do statement ; while ( condition ) char reply; do printf("decision (y/n): "); reply = getchar(); if ( reply == EOF ) exit(0); while ( reply!= 'y' && reply!= 'n' reply!= 'Y' && reply!= 'N' ); statement(s) condition false true Verwende die der Sprache eigenen Idiome C++ i ++ ; for ( i=0; i < n; i ++ ) if ( a &&!b ) Python i += 1 for i in range(n) if a and not b : 5