Da sich Gestern jemand über zu seltene Postings beschwert hat (Herzlichen Glückwunsch nochmal, Andreas
), und da ich gerade mal wieder an einem kleinen Python-Projekt bastele: ein aktuelles Fundstück. Wenn man sich — wie ich — nichts merken kann, und zudem — wie ich — dauernd zwischen verschiedenen Programmiersprachen hin- und herspringt findet man so eine Sammlung mit Codeschnipseln sehr praktisch, stelle ich gerade fest. Hinweise auf bessere Schnipselsammlungen nehme ich dankend entgegen!
Tag-Archiv für » Programmieren «
Das erinnert mich daran warum ich die Sprache C nach Möglichkeit nur auf Mikrocontrollern benutze:
rschaten% cat array.c
#include <stdio .h>
int main(int argc, char **args) {
char *string = "abc";
printf("%c %c %cn", string[0], string[1], string[2]);
printf("%c %c %cn", 0[string], 1[string], 2[string]);
return 0;
}
rschaten% gcc -o array array.c
rschaten% ./array
a b c
a b c
rschaten%
Das habe ich aus dem Unix Haters Handbook, ich hätte nicht gedacht dass das wirklich funktioniert…
Wie schon erwähnt muss ich mich bei der Arbeit mit Windows rumschlagen. Um Sehnenscheidenentzündungen vorzubeugen verschlägt es mich da bisweilen auch in die Kommandozeile. OK, das ist nicht der einzige Grund. Manchmal will man ja aus einem Skript (leider in diesem Fall kein Perl) heraus einfach mal ein system() aufrufen, und da muss man dann halt DOS-Kommandos absetzen.
Jetzt wollte ich etwas kluges basteln, das testet ob ich eine Datei (schreiben|lesen|löschen) kann. Auf anderen Systemen hätte ich dazu auf etwas in der Form
kommando; echo $?
gesetzt, die Ausgabe könnte ich parsen. Ein Kollege hat für DOS
kommando && echo ok || echo nein
vorgeschlagen, das sollte funktionieren. Prima, Exitcodes kann ich dann offenbar auswerten. Oder?
Um Vielleicht mehr Infos zu kriegen als (tut’s|tut’s nicht) versuche ich folgendes:
kommando & echo %ERRORLEVEL%
Und jetzt bin ich verwirrt (siehe Screenshot):
Das mit && funktioniert scheinbar, die Ausgabe von %ERRORLEVEL% bringt aber nicht sinnvolles? Was wird denn dann von && bzw. || ausgewertet? Und wie zur Hölle kriege ich den wirklichen Exit-Code?!?
Nach etwas mehr Spielerei stelle ich fest, dass in einigen Konstellationen der %ERRORLEVEL% tatsächlich gesetzt wird. Leider immer ein Kommando zu spät, wie man am zweiten Screenshot erkennen kann. Komischerweise funktioniert das aber — wenn man da von ‘funktionieren’ sprechen kann — auch nur bei Programmaufrufen.
echo > . & echo %ERRORLEVEL%
führt zwar jedes Mal zu einer Fehlermeldung, gibt aber trotzdem nur 0 aus…
Ich beschließe einfach erstmal, das nicht zu verstehen. Mein eigentliches Problem kann ich offenbar unter Windows nicht elegant lösen, also muss ich mir da was anderes ausdenken…
Im Moment bin ich wie schon erwähnt dazu gezwungen, beruflich viel auf Windows zu machen. Leider knirscht es dabei an allen Ecken und Enden, wenn man wie gewohnt produktiv sein will. Eine Menge Werkzeuge fehlen einfach, mal eben schnell eine elegante Shell- oder Perl-Zeile abschicken geht nicht. Von ganzen Skripten ganz zu schweigen.
Klar gibt es mit Cygwin oder ActiveState auch die Möglichkeit, einen Werkzeugkasten auf Windows nachzuinstallieren. Aber das ist lästig, und das würde ich auch nicht auf hunderten produktiver Server bei meinem aktuellen Kunden machen wollen. Geschweige denn: dürfen.
Ich habe jetzt eine Lösung gefunden die zwar kein hundertprozentiger Ersatz für eine anständige Umgebung ist, aber die an einigen Stellen schon echt hilfreich war: PAR::Packer.
Auf meinem Arbeitsplatz habe ich ein ActiveState-Perl installiert, darin das genannte Modul. Jetzt kann ich beispielsweise folgendes eingeben:
pp -e "print time();"
Die Maschine kaut eine Weile auf dem Kommando rum und spuckt dann eine a.exe aus, die ab sofort den aktuellen Unix-Timestamp ausspuckt wenn man sie aufruft. Und das auch auf Systemen auf denen keine Perl-Umgebung installiert ist, man braucht also keine zusätzlichen DLLs oder so, nur die jeweilige EXE.
Leider ist es nicht so, dass pp das Kommando wirklich compiliert. Es ist vielmehr so, dass pp ein Archiv zusammenpackt in dem alles drin steckt was zur Ausführung des Befehls nötig ist. Die Ausgabe des entstehenden Executables ist zwar die gleiche, aber oben genanntes a.exe ist 1.844.011 Bytes groß und braucht auf meiner Kiste über eine Sekunde bevor sie wirklich ausgeführt wird. Klar, muss ja erst entpackt werden.
Die gute Nachricht ist, dass lediglich der Start so lange dauert. Das enthaltene Programm läuft — nach dem Entpacken — praktisch genauso schnell wie in einer ‘richtigen’ Perl-Umgebung.
Wer es etwas schicker haben will kann übrigens auch direkt folgendes machen:
pp --output=timestamp.exe -e "print time();"
Und komplexe Skripte werden wie folgt gepackt:
pp --output=weltherrschaft.exe weltherrschaft.pl
Die Größe der entstehenden Datei steigt übrigens nicht derartig an dass für jede Zeile wieder 1,8MB dazu kommen. Ich habe hier ein Skript von 5.308 Bytes übersetzt, das EXE ist 2.493.292 Bytes groß. Immer noch eine Menge, aber für einen schnellen Hack ist das durchaus tauglich.
Ich bin auf ein merkwürdiges Phänomen in C gestoßen, vielleicht kann mir das jemand erklären. Extrem eingedampft sieht das Problem so aus:
int main(int argc, char* arg[]) {
int i = 0;
switch (i) {
case 0:
int j = 7;
break;
}
}
Der Compiler (aufgerufen mit ‘gcc test.c’) sagt dazu “t.c:5: error: expected expression before ‘int’“. Mit geschweiften Klammern funktioniert der case-Block dagegen prima:
case 0: {
int j = 7;
break;
}
Zu meinem grössten Erstaunen klappt auch folgender Block:
case 0:
i = 3;
int j = 7;
break;
Es geht halt nur nicht wenn direkt nach dem case eine Variablendeklaration kommt.
Wenn man schon innerhalb eines case eine Variable deklarieren kann… warum dann nicht ganz am Anfang? Ich meine: ich habe ja Lösungen für das Problem. Mir fehlt halt nur das ‘Problembewusstsein’. Kann mir das jemand vermitteln?

