weiter geht’s

15. August 2011 - 17:11 Uhr

hier geht’s jetzt weiter…

54 Kommentare » | Uncategorized

Podiumsdiskussion

19. Januar 2011 - 11:42 Uhr

Morgen Abend findet die dritte Podiumsdiskussion zur Lehre an der Göttinger Physik statt.

Studenten und Professoren diskutieren über Studiengebühren, Stellenwert der Lehre und neue Übungskonzepte.

Donnerstag, 17 Uhr, im Hörsaal 1.

Auf folgende – teils kontroverse Themen – können wir uns freuen:

Studiengebühren:

  • Übersicht (Zahlen und so)
  • Ideen und Vorschläge sammeln
  • halten Professoren manche Anträge „aus Angst“ zurück – und wenn ja, welche
  • Beispielanträge vorstellen und Studentenmeinungen einholen
  • Stellenwert der Lehre:

  • Evaluationen
  • Absprache zwischen Dozenten
  • Vergleich mit anderen Unis (bzgl. Notenvergabe, Leistungskriterien, Übungen)
  • Anreize für Didaktikfortbildungen
  • Repetitorien verbessern
  • Lehrqualifikationssemester analog zu Forschungsfrei-Semester einrichten
  • Preis für gute HiWis
  • Übungskonzepte:

  • Problem Fachkenntnis oder Didaktik?
  • HiWi-Mangel: Lieber größere Übungen mit besseren HiWis oder kleinere mit den HiWis, die sich irgendwie finden lassen?
  • HiWi-Besprechung regelt fachliches
  • bessere Bezahlung für gute HiWis?
  • Also, bis morgen. Ab 18ct führe ich Protokoll.

    Kommentare deaktiviert für Podiumsdiskussion | Uncategorized

    CCC Anfang März

    19. Januar 2011 - 07:30 Uhr

    Anfang März ist wieder der CCC in Göttingen. Nein, nicht dieser schlechte abgekupfter Chaos Computer Congress, sondern das Original!

    Der Computer Crash Course der Physik-Fachschaft zeigt den Ersties in deren ersten „Ferien“, wie man so einen Linux-Rechner vernünftig bedient. Bash, LaTeX, Gnuplot – alles, was man für’s Grundpraktikum braucht, ist dabei.

    Nach derzeitigem Plan bin ich gleich mit drei Vorträgen an Bord: Der Vortrag-Vortrag, und zusammen mit Martin am Freitag dann vim und Reguläre Ausdrücke.

    Vortrag-Vortrag:
    Wie halte ich einen Vortrag? Wie schnell rede ich, wo kucke ich hin, klicke ich bloß Folien durch, schreibe ich vielleicht mal was an, wiederhole ich mal was, beantworte ich die Frage, sage ich, dass man ruhig welche stellen könne, wie bereite ich mich vor – und vor allem: kann man mit LaTeX auch Folien machen?

    vim (vi improved):
    Will man programmieren oder TeXen, braucht man einen Editor. Um Textdateien zu ändern. Da gibt es eine ganze Menge, manche sind sehr speziell, andere eher allgemein. Aber einer ist vor allem eines: Ausgeklügelt und ziemlich schnell, wenn man an bestimmte Stellen springen möchte. Das ist der vim, der „impruufte“ vi (sprich: „wim“, „wi-ai“).

    Reguläre Ausdrücke:
    Reguläre Sprachen stammen aus der theoretischen Informatik, speziell der Automatentheorie. Dort fragt man sich:
    „Welche (interessanten) formalen Grammatiken / Sprachen können wir definieren, und wie kompliziert sind sie zu beschreiben / zu entscheiden?“

    Reguläre Sprachen sind dabei die einfachsten, können durch deterministische endliche Automaten erkannt werden – und Reguläre Ausdrücke sind „Patterns“, die in dieser Grammatik verfasst werden. Diese Muster können wir dann in Texten suchen, etwa nach dem Motto: „Gib mir alle Stellen, die aus einer Zahl, einem Komma, zwei Zahlen, einem Leerzeichen und einem Euro-Zeichen bestehen“ (== Preise).

    Mit spezialisierten Programmiersprachen wie AWK oder Perl kann man sehr einfach nach solchen Mustern suchen und darauf operieren (zum Beispiel Währungen umrechnen, Messdaten kombinieren, einfaches numerisches Integrieren oä).

    Der CCC startet am Dienstag, 1. März, und endet am Freitag, 4. März. Mehr beim FSR Physik.

    Kommentare deaktiviert für CCC Anfang März | Allgemein, Linux, Studieren in Göttingen

    Buchrezension – Jürgen Becker: So was lebt und Goethe musste sterben

    4. Januar 2011 - 20:28 Uhr

    Jürgen Becker, Dietmar Jacobs, Martin Stankowski: So was lebt und Goethe musste sterben — Der dritte Bildungsweg

    Kiepenheuer & Witsch, 2009 (2. Auflage)
    ISBN: 978-3-462-04166-8

    Der Inhalt.
    „Zuhause ist wegfahren am schönsten“, heißt das erste Kapitel des neuen Buches von Jürgen Becker (4711, Mitternachtsspitzen, Stunksitzung etc. pp.). Die Autoren nehmen den Leser mit auf eine Reise quer durch den Westen Deutschlands. An 17 Orten stellen sie die Sehenswürdigkeiten vor, die sonst wohl nie jemand suchen würde. Etwa die Klapp-Kirche St. Anna zu Augsburg: Je nach Konfession (kniend oder stehend) werden die Bänke umgeklappt. „Die Glaubensrichtung ist einstellbar“, „Mutter sitzt katholisch, Sohn evangelisch“, so zwei Bildzeilen.

    Schön auch das Kapitel „Römer go home – über die Germanen“. Hier erfahren wir im Schnelldurchlauf noch einmal alles, was wir in der Schule gleich vergessen haben:

    Die Germanen waren zersplittert in Bundesländer, wie wir das heute auch noch kennen: Schleswig-Holstein hat nichts mit Sachsen zu tun, und wenn man in Bayern die AOK-Rückenschule abgeschlossen hat, gilt das in Bremen als Abitur.

    Auch die Speere der Germanen tauchen in unserer Zeit wieder auf, beim Nordic Walking. Zur Varus-Schlacht finden wir diese Zeilen:

    Arminius war also eigentlich kein Held, sondern ein Typ, der die Seiten wechselte und null Prozent Steuern wollte. So eine Art Guido Westerwelle der Antike.

    Aufbau der Kapitel.
    Satire umrahmt Ausflug. Siebzehn Ziele, die man so nie besuchen würde. Dazu satirische Texte über verschiedene Themen (Religion, Geschichte, …)

    Zur Sprache.
    Herrlich, rheinisch, lustig.

    Kommentare deaktiviert für Buchrezension – Jürgen Becker: So was lebt und Goethe musste sterben | Allgemein, Buchrezension

    :TOhtml

    30. Dezember 2010 - 20:13 Uhr

    „Wie hast Du denn den Quellcode so schön formatiert?“, hätte man gut fragen können. Hat zwar keiner gemacht, aber hier trotzdem die Antwort:

    $ source-highlight -n -i waffel.c -o waffel.html -s c.lang

    Dieses nette Progrämmchen macht bunt und fett, was Quellcode ist. Mit -n gibt’s dann auch gleich die Zeilennummern vorne vor.

    Das tolle: man kann nicht nur HTML-Dateien erstellen, sondern auch LaTeX und einige mehr.

    Und vor wenigen Minuten fand ich noch folgendes:

    :TOhtml

    im vim, dem besten Editor auf der Welt. Damit ist es möglich, die aktuelle Ansicht im vim (inklusive Zeilennummern, Syntax-Farbe und Folding) als HTML-Datei zu speichern. Die ganze Datei, oder der markierte Teil (think visual).

    Mehr dazu gibt es bei techspeak.

    Kommentare deaktiviert für :TOhtml | Allgemein, Linux

    UDP vs. TCP

    30. Dezember 2010 - 08:42 Uhr

    Die Netzwerkschnittstelle von unserem Waffelstrichlistenprogramm, <tt>waffel.c</tt>, basiert auf UDP. Warum aber nicht TCP?

    Von der Funktion her sind beide Protokolle gleich: Im ISO-OSI-Modell entsprechen sie der Ebene Nummer 4 (Transport-Layer, zwischen 3: Network Layer und 5: Session Layer).

    Sehen wir uns mal die Vorteile von TCP, dem Transmission Control Protocol, an:

    • Drei-Wege-Handschlag zum Aufbau einer Verbindung
    • Datenpakete werden in korrekter Reihenfolge zusammengesetzt
    • fehlende Pakete werden neu angefordert
    • bei Verstopfungen wird die Paketrate automatisch gedrosselt

    All diese Vorteile bietet UDP, das User Datagram Protocol nicht; warum haben wir uns trotzdem dafür entschieden? Schließlich is es ja…

    • unzuverlässig,
    • ungeordnet,
    • fehleranfällig.

    Aber: es ist wesentlich einfacher zu handhaben und schneller. Gerade für kurze Nachrichten (einige hundert Bytes), die sowieso nicht auf einzelne Pakete aufgeteilt werden. Das Fehlen von einem Handschlag und der Überprüfung, ob die Pakete wirklich angekommen sind, ist eine große Zeitersparnis, wenn die Nachrichten sehr kurz sind. Da verloren gegangene Pakete nicht neu angefordert werden, wird UDP gerne für Realtime-Anwendungen (Videokonferenz, VoIP etc) genutzt.

    Vergleichbar mit einem Klavierspieler, der an Weihnachten begleitet und vom Blatt spielt: Trifft mal ein Finger nicht die richtige Taste – einfach weiterspielen, sonst kommen die Sänger ja aus dem Rhythmus…

    Kommentare deaktiviert für UDP vs. TCP | Allgemein, Linux

    set term dumb

    29. Dezember 2010 - 17:22 Uhr

    Und so sieht ein Konsolen-Plot in Gnuplot aus:

    set term dumb

    Besonders hervorzuheben ist die Waffel-Verkaufspause wegen des Feueralarms (nein, wir waren es nicht).

    Kommentare deaktiviert für set term dumb | Allgemein, Linux

    void* udplisten(void*);

    29. Dezember 2010 - 13:36 Uhr

    Die Waffel-Strichliste bietet auch eine Netzwerkschnittstelle; darüber lassen sich live wichtige Informationen abrufen:

    • Wie viele Waffeln wurden bereits verkauft?
    • Welches Lied wird gerade gespielt?
    • Wie hoch ist die (geschätzte) Spendensumme?
    • Wann wurde die letzte Waffel verkauft?

    Das ganze läuft über UDP, das User Datagram Protocol. Die Funktion udp_listener wird in einem eigenen Thread gestartet. Aber zunächst die Signatur:

    
    027: void* udplisten(void*);
    

    Dieser Prototyp ist im Wesentlichen dadurch bestimmt, dass wir einen Funktionszeiger für die Posix-Funktion pthread_create benötigen, siehe gleich.

    In der main-Funktion braucht es noch zwei Variablen:

    
    046:     pthread_t udplistener;
    047:     int udplistener_rv;
    

    Und hier geht’s ab: Wir erstellen einen neuen Thread, sodass recvfrom() (Zeile 332) nicht den normalen Benutzerbetrieb stört.

    
    069:     udplistener_rv = pthread_create(&udplistener, NULL, udplisten, NULL);
    

    So, genug der Vorrede, jetzt die Funktion. Wir beginnen mit Deklarationen und sowas…

    
    292: void* udplisten(void* nueksch)
    293: {
    294:     int sock;
    295:     struct sockaddr_in echoserver;
    296:     struct sockaddr_in echoclient;
    297:     char buffer[BUFFSIZE];
    298:     unsigned int clientlen, serverlen;
    299:     int received = 0;
    300:     char* answer;
    301: 
    302:     answer = (char*) malloc(sizeof(char) * BUFFSIZE);
    303:     if (answer == NULL)
    304:     {
    305:         fprintf(stderr, "malloc failed @ line %d\n", __LINE__);
    306:         exit(-1);
    307:     }
    

    Nun legen wir einen UDP-Socket an:

    
    309:     /* Create the UDP socket */
    310:     if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
    311:     {
    312:         fprintf(stderr, "Failed to create socket\n");
    313:     }
    

    Da, wo ich diesen Schnipsel herkopiert hab, wird nun die sockaddr_in-Struktur initialisiert; im Wesentlichen vereinbaren wir einen IPv4-Socket und setzen den Port auf PORT==1042

    
    314:     /* Construct the server sockaddr_in structure */
    315:     memset(&echoserver, 0, sizeof(echoserver));       /* Clear struct */
    316:     echoserver.sin_family = AF_INET;                  /* Internet/IP */
    317:     echoserver.sin_addr.s_addr = htonl(INADDR_ANY);   /* Any IP address */
    318:     echoserver.sin_port = htons(PORT);                /* server port */
    

    Mit bind() aktivieren wir nun unseren Server-Socket:

    
    320:     /* Bind the socket */
    321:     serverlen = sizeof(echoserver);
    322:     if (bind(sock, (struct sockaddr *) &echoserver, serverlen) < 0)
    323:     {
    324:         fprintf(stderr, "Failed to bind server socket\n");
    325:     }
    

    Endlosschleife: warte auf eine Anfrage und bearbeite sie…

    
    327:     /* Run until cancelled */
    328:     while (1)
    329:     {
    330:         /* Receive a message from the client */
    331:         clientlen = sizeof(echoclient);
    332:         if ((received = recvfrom(sock, buffer, BUFFSIZE, 0,
    333:                         (struct sockaddr *) &echoclient,
    334:                         &clientlen)) < 0)
    335:         {
    336:             fprintf(stderr, "Failed to receive message\n");
    337:         }
    

    Damit die Anfrage auch schön NULL-terminiert ist:

    
    338:         buffer[received] = '';
    

    Die Anfragen bestehen aus einem string, der folgenden Text enthält:

    • qWaffelCount
    • qSpendenSumme
    • qLastWaffel
    • qSong

    Die Anfrage steht in buffer und wird mittels strcmp überprüft; dann wird mit sprintf die Antwort zusammengeschustert:

    
    340:         sprintf(answer, "---");
    341:         if (strcmp(buffer, "qWaffelCount") == 0)
    342:             sprintf(answer, "Bisher verkaufte Waffeln: %d\n", qWaffelCount());
    343:         if (strcmp(buffer, "qSpendenSumme") == 0)
    344:             sprintf(answer, "Aktuelle Spendensumme: %.2f Euro\n", 0.42*qWaffelCount());
    345:         if (strcmp(buffer, "qLastWaffel") == 0)
    346:             sprintf(answer, "Letzte Waffel: %s", asctime(qLastWaffel()));
    

    Das aktuelle Musikstück kennt mocp, zu dem wir eine Pipe aufbauen:

    
    347:         if (strcmp(buffer, "qSong") == 0)
    348:         {
    349:             FILE* fpipe;
    350:             char* command="mocp -i | grep ^Title";
    351:             char line[256];
    352: 
    353:             if ( !(fpipe = (FILE*)popen(command, "r")) )
    354:             {
    355:                 perror("Problems with pipe");
    356:                 exit(1);
    357:             }
    358: 
    359:             while ( fgets( line, sizeof line, fpipe))
    360:             {
    361:                 sprintf(answer, "Aktuelles Lied: %s", line);
    362:             }
    363:             pclose(fpipe);
    364:         }
    

    Bevor es funktionierte, gab es hier eine Ausgabe:

    
    366:         /*
    367:         fprintf(stderr, "Client connected: %s\n", inet_ntoa(echoclient.sin_addr));
    368:         fprintf(stderr, "Q: %s\n", buffer);
    369:         fprintf(stderr, "A: %s\n", answer);
    370:         */
    

    Mit sendto schicken wir die Antwort zurück, dann geht die Schleife wieder von vorn los.

    
    372:         /* Send the message back to client */
    373:         sendto(sock, answer, strlen(answer), 0, (struct sockaddr *) &echoclient, sizeof(echoclient));
    374:     }
    375: 
    376:     return NULL;
    377: }
    

    Kommentare deaktiviert für void* udplisten(void*); | Allgemein, Linux

    int show_plot();

    22. Dezember 2010 - 18:42 Uhr

    Nicht sonderlich spektakulär: von C aus gnuplot aufrufen…

    
    00429: int show_plot()
    00430: {
    00431:     return system("gnuplot < gnu.plot");
    00432: }
    

    Das Plotfile hingegen bietet da schon mehr Einsichten:

    
    00001: set term dumb 125 45
    00002: set xlabel 'Uhrzeit'
    00003: set ylabel 'Anzahl'
    00004: set xdata time
    00005: set timefmt "%s"
    00006: set format x "%H:%M:%S"
    00007: plot [] [0:11] 'waffel.input' u ($2+3600):($1 > 0 ? $1 : 1/0) w points ps 5 pt 3 t '15.12.10'
    

    Das Terminal dumb ist gar nicht doof, sondern die Konsole. Dort wird auf 125 mal 45 Zeichen (fast) jede verkaufte Waffel durch ein W dargestellt; genauer: die Anzahl der auf einmal verkauften Waffeln als Funktion der Zeit. Um Fehleingaben und negative Korrekturwaffeln zu unterdrücken, ist die y-Achse auf 0 bis 10 eingeschränkt.

    Die +3600 Sekunden sind übrigens Winterzeit gegen Greenwich.

    Kommentare deaktiviert für int show_plot(); | Allgemein, Linux

    int waffelloop(FILE*)

    21. Dezember 2010 - 15:24 Uhr

    Heute möchten wir uns die Waffel-Schleife von waffel2010 ansehen.

    Zunächst noch einmal die Signatur:

    
    00022: int waffelloop(FILE*);
    

    waffelloop erhält also einen FILE-Pointer und gibt einen int zurück. Als FILE-Pointer übergeben wir zunächst eine geöffnete Datei:

    
    00063:         waffelloop(infile);
    

    In dieser ist die bisherige Geschichte gespeichert, damit wir das Programm unterbrechen und später neu starten können. Anschließend gibt die main-Funktion ein bisschen Text aus und startet die waffelloop mit einem Zeiger auf stdin: Nun werden die Eingaben von der Tastatur (alternativ aus einer Pipe) gelesen.

    
    00071:     err = waffelloop(stdin);
    

    Gehen wir doch einmal die Implementation der waffelloop durch. Zunächst deklarieren wir Variablen und allokieren Speicher für einen Eingabe-Puffer:

    
    00133: int waffelloop(FILE* infile)
    00134: {
    00135:     char* buffer;
    00136:     const int buffer_size = 32;
    00137:     FILE* outfile = NULL;
    00138: 
    00139:     buffer = (char*) malloc(buffer_size * sizeof(char));
    00140:     if (buffer == NULL)
    00141:         return __LINE__;
    

    Wenn die Eingabe nicht aus der der waffel.input stammt (als FILE* also stdin übergeben wurde), öffnen wir diese Datei zum Anhängen, um die Eingaben zu speichern. Kann sie nicht geöffnet werden, geben die Zeilennummer __LINE__ (gcc-Makro) als Fehler zurück:

    
    00143:     if (infile == stdin)
    00144:     {
    00145:         outfile = fopen("waffel.input", "a");
    00146:         if (outfile == NULL)
    00147:             return __LINE__;
    00148:     }
    

    Nun beginnt die Endlos-Schleife while(1). Wir deklarieren einen Zähler int waffel_count=0 und einen Zeitstempel time_t when=0; ist die Eingabe stdin, geben wir einen Prompt auf stdout aus. Anschließend lesen wir eine Zeile in den Puffer.

    
    00150:     while (1)
    00151:     {
    00152:         int waffel_count = 0;
    00153:         time_t when=0;
    00154: 
    00155:         if (infile == stdin)
    00156:             printf("Waffel $ ");
    00157:         fflush(stdout);
    00158:         if (fgets(buffer, buffer_size, infile) == NULL)
    00159:             break;
    

    Am Dateiende schlägt fgets fehl, wir verlassen die Schleife mit einem break.

    Nun ein fieser Hack: Hat der Nutzer nur Enter gedrückt, schreiben wir 1\n in den Puffer:

    
    00161:         if (buffer[0] == '\n')
    00162:         {
    00163:             buffer[0] = '1';
    00164:             buffer[1] = '\n';
    00165:         }
    

    Fallunterscheidung zur Behandlung der Eingabe: lesen wir aus der waffel.input, bekommen wir die Zahl der verkauften Waffeln und den Zeitstempel.

    
    00166:         if (infile != stdin)
    00167:         {
    00168:             int when_int;
    00169:             sscanf(buffer, "%d %d", &waffel_count, &when_int);
    00170:             when = when_int;
    00171:         }
    

    Im anderen Fall müssen wir die Benutzer-Eingabe verarbeiten. Im einfachsten Fall steht in buffer eine Zahl, die wir mittels sscanf in die Variable waffel_count schreiben können; den Zeitstempel bekommen wir von time(0):

    
    00172:         else
    00173:         {
    00174:             sscanf(buffer, "%d", &waffel_count);
    00175:             when = time(0);
    00176:             fprintf(outfile, "%3d %d\n", waffel_count, (int)when);
    00177:             fflush(outfile);
    00178:         }
    

    Hat sscanf jedoch eine 0 gelesen, vergleichen wir das erste Zeichen, buffer[0], mit den erlaubten Befehlen, und springen in die entsprechenden Funktionen (oder verlassen die while(1)-Schleife):

    
    00180:         if (waffel_count == 0)
    00181:         {
    00182:             if (buffer[0] == 'x' || buffer[0] == 'X')
    00183:                 break;
    00184:             if (buffer[0] == 'a' || buffer[0] == 'A')
    00185:                 start_alsamixer();
    00186:             if (buffer[0] == 'h' || buffer[0] == 'H')
    00187:                 print_help();
    00188:             if (buffer[0] == '?')
    00189:                 print_help();
    00190:             if (buffer[0] == 's' || buffer[0] == 'S')
    00191:                 output_uptime();
    00192:             if (buffer[0] == 'l' || buffer[0] == 'L')
    00193:                 output_last_waffel();
    00194:             if (buffer[0] == 'n' || buffer[0] == 'N')
    00195:                 blubber = system("mocp --next");
    00196:             if (buffer[0] == 'p' || buffer[0] == 'P')
    00197:                 show_plot();
    00198:             if (buffer[0] == 't' || buffer[0] == 'T')
    00199:                 print_datetime();
    00200:         }
    

    Ansonsten wurde eine Zahl gelesen, der Waffel-Zähler entsprechend geändert und der Eintrag in die Datei waffel.input geschrieben:

    
    00201:         else
    00202:         {
    00203:             save_to_history(waffel_count, when);
    00204:             if (infile == stdin)
    00205:             {
    00206:                 if (waffel_count > 0)
    00207:                     alert(waffel_count);
    00208:                 printf("\n");
    00209:             }
    00210:         }
    

    Nach dem Schleifenende schließen wir outfile und geben zurück.

    
    00211:     }
    00212: 
    00213:     if (infile == stdin)
    00214:         fclose(outfile);
    00215:     
    00216:     return 0;
    00217: }
    

    Anmerkungen:

    • Für nächstes Jahr wird das Programm auf die readline-Bibliothek vorbereitet; dann kann man nämlich die Eingabe löschen.
    • Eine falsche Waffel-Zahl kann durch Eingabe einer negativen Zahl korrigiert werden.

    Kommentare deaktiviert für int waffelloop(FILE*) | Allgemein, Linux

    « Ältere Einträge     

    Zur Werkzeugleiste springen