K&R The C Programming Language: Word Lengths Histogram Aufgabe
-
Dann hast du das Konzept wirklich nicht verstanden. Die gezeigten Codes sind jedenfalls tatsächlich OO pur. OO hat nichts mit Punkten in der Syntax zu tun. Ein anderer Unterschied besteht zwischen dem C und dem C++-Code aber nicht.
Oder anders gesagt, in C++ (doer jeder anderen Sprache, die du als oo bezeichnen würdest) ist
f.write("Bla")
nur Syntaxzucker fürwrite(f, "Bla")
.
-
ne mit punkten nicht, aber damit, dass funktionen bei oop in ein objekt gekapselt werden sollen, damit das alles schön übersichtlich ist und man weiß, dass f.write() eine methode der durch f instanziierten klasse File ist und daher nicht zig dateien durchsucht werden müssen, wenn man da irgendwas dran ändern will.
den vorzug hast du bei write(f,...) nicht.
-
So? Was ist denn anders? Der erste Parameter von fwrite nimmt schließlich einen FILE* entgegen, weil fwrite eine Methode der Klasse FILE ist. Erinnert dich das vielleicht an etwas? *hust*this*hust*
-
Am Ende des Tages wird doch eh alles (völlig Hunz ob C, C++, Python, Haskell, oder Brainfuck) in die Maschinensprache des Computers übersetzt, denn das ist das einzige was er versteht, alles andere ist nur für den Menschen (ausgenommen letzteres). Jedes Programm ist start -> tu was -> stop.
Ein Objekt bestimmt meiner Ansicht nach eine Menge von Daten (Also irgendwelche Bytes im Speicher) und auf diese Daten ist eine Menge möglicher Operationen definiert. Wie das jetzt konkret aussieht, ist doch wurscht.
-
HarteWare schrieb:
...
"Objektorientierung" in C anzuwenden,
...
bei C++ (da komme ich her).Lange vor Stroustrup und dem Managerhype OOP wurde von den Praktikern schon das "Objekt" benutzt, natürlich auch von Ritchie.
In C++ hätte o.g. Beispiel dann als Klasse so ausgesehen:
class Histogram { public: void count_word_lengths(FILE *fp, unsigned numWordsOfLen[], unsigned maxLen); void output_histogram(unsigned arr[], unsigned len); private: static constexpr int MAX_LEN = 100; // hier hat Stroustrup mal wieder gepfuscht, das hätte so schon in C++98 funktionieren müssen void count_length(unsigned numWordsOfLen[], unsigned len, unsigned maxLen); void output_header(unsigned numLengths, const char* title); void output_graph(unsigned arr[], unsigned len); void output_y_axis_segment(unsigned y, unsigned step); void output_graph_segment(unsigned arr[], unsigned len, unsigned currentY); void output_x_axis(unsigned arr[], unsigned len); unsigned find_max(unsigned arr[], unsigned len); void char_line(int ch, unsigned length); };
Wie du siehst, kann man mit C-Modulen und static die Accesslevel implementieren.
Bleibt nur noch die Frage: Wo wäre MAX_LEN (als enum) denn am besten aufgehoben?
Antwort: Im C-Modul:
histogram.c:enum {MAX_LEN=100}; /* das ist keine Objekt- sondern nur eine Typdefinition, d.h. ein Zugriffsschutz via static ist nicht nötig (und nicht möglich) */
-
Bleibt nur noch die Frage: Wo wäre MAX_LEN (als enum) denn am besten aufgehoben?
Antwort: Im C-Modul:Stimmt, das war mir auch nicht 100% klar. Kannst ja Gedanken lesen :o
-
Wobei die enum-Variante im Rahmen einer anonymen enum-Typdefinition im C-Modul prinzipiell noch weitere Vorteile bietet:
- erstmal natürlich: du kommst von außerhalb des C-Moduls niemals an den Wert heran, da kannst du via extern versuchen was du willst; weil MAX_LEN gar kein Objekt ist
- ein Debugger zeigt dir den enum-Wert sehr viel wahrscheinlicher separat an als ein #define
- gegenüber einer const int-Definition hast du hier den Vorteil, dass du auf Fehler immer schon zur Compilezeit hingewiesen wirst, wenn du (verbotenerweise doch) versuchst den Wert zu ändern, und nicht erst vielleicht zur Laufzeit
#include <stdio.h> const int x = 4711; enum {y = 4711}; int main() { #if 0 *(int*)&x = 4712; /* nicht lachen, ich habe schon viel solchen Code gesehen (auch voll selbsternannten Profis), der const auf diese Weise umgehen will */ printf("%d",x); #else y=4712; #endif return 0; }
- const-Variante: du kannst froh sein, wenn du überhaupt zur Laufzeit einen Fehler bekommst (hängt von der Güte des Compilers ab)
const int x = 4711; enum {y = 4711}; int main() { #if 1 *(int*)&x = 4712; printf("%d",x); #else y=4712; #endif return 0; } Runtime error
- enum-Variante: du erhältst immer schon zur Compilezeit einen Fehler (ein unschätzbarer Vorteil bei professioneller Programmierung: man lässt so viel wie möglich durch den Compiler prüfen); der Code reift nicht beim Kunden sondern möglichst beim Entwickler
const int x = 4711; enum {y = 4711}; int main() { #if 0 *(int*)&x = 4712; printf("%d",x); #else y=4712; #endif return 0; } prog.c:11:6: error: lvalue required as left operand of assignment y=4712; ^
-
SeppJ schrieb:
Oder anders gesagt, in C++ (doer jeder anderen Sprache, die du als oo bezeichnen würdest) ist
f.write("Bla")
nur Syntaxzucker fürwrite(f, "Bla")
.Interessant. Wie kommt write() denn an die privates von f heran? Datenkapselung ist ja ein wesentliches Merkmal von OOP.
-
versionsnummer schrieb:
SeppJ schrieb:
Oder anders gesagt, in C++ (doer jeder anderen Sprache, die du als oo bezeichnen würdest) ist
f.write("Bla")
nur Syntaxzucker fürwrite(f, "Bla")
.Interessant. Wie kommt write() denn an die privates von f heran? Datenkapselung ist ja ein wesentliches Merkmal von OOP.
file.h
struct File; size_t write(struct File* file, char const* data, size_t len);
file.c
struct File { // irgendwelche Innereien }; size_t write(struct File* file, char const* data, size_t len) { // greife einfach auf die Innereien von file zu }
Tada! Daten sind in einem Modul* gekapselt. Module sind in C üblicherweise Header/Source Dateien, in C++ sind es Klassen, usw.
*Den Bergiff Modul habe ich eben erfunden; es handelt sich hier nicht um standard C/C++ Terminologie.
-
naiv
-
versionsnummer schrieb:
SeppJ schrieb:
Oder anders gesagt, in C++ (doer jeder anderen Sprache, die du als oo bezeichnen würdest) ist
f.write("Bla")
nur Syntaxzucker fürwrite(f, "Bla")
.Interessant. Wie kommt write() denn an die privates von f heran? Datenkapselung ist ja ein wesentliches Merkmal von OOP.
Indem auch das Objekt (this) separat als Parameter übergeben wird. (was C++ intern bei class macht)
typedef struct { void (*write)(); const char*s; } class; void write(class*this,const char*s){puts(this->s);puts(s);} int main() { class objekt={write,"privat"}; /* "Klassen"-Instanziierung mit gleichzeitiger Initialisierung */ objekt.write(&objekt,"public"); /* OOP */ return 0; }
-
und solche spielereien kommen euch nicht ein bisschen seltsam vor?
mit diesen ganzen "richtigen" objektorientierten programmiersprachen lässt sich das alles viel eleganter umsetzen.natürlich unter der voraussetzung, dass das wirklich den prinzipien der oop entspricht, woran ich irgendwie weiterhin meine zweifel habe.
-
Nur weil du naive Vorstellungen von "eleganter" OOP hast, müssen nicht alle außer dir die letzten Jahrzehnte konzeptlos programmiert haben.
Fakt ist: OOP ist ein Managerhype der 90er (auffälligerweise nahezu zeitgleich mit dem Aufkommen von Java);
das Konzept gibt es schon sehr viel länger, wie hier schon gesagt:File* f = fopen('foo'); fwrite(f, ...); fclose(f);
ist OO pur
Mit diesem Managerhype einhergehend ist der (in C++ und besonders Java) verbreitete Umkehrschluss: ich programmiere Java/C++, also programmiere ich OOP.
Das ist ebensolcher Dünnschiss von denselben Consultens der 90er, die ihre Javadeppen verkaufen wollen, nur weil die ein paar fehlerfreie Zeilen geradeaus schreiben können, und meinen, den Rest der VM oder irgendwelchen Appservern überlassen zu können.
-
@HansKlaus: Auch die WinAPI ist objektorientiert geschrieben - und (zumindestens die Schnittstelle) komplett "C".
-
HansKlaus schrieb:
und solche spielereien kommen euch nicht ein bisschen seltsam vor?
Doch, natürlich. Lass' Dich nicht beschwätzen ... Man muß im Hinterkopf behalten, daß es zwei Auffassungen von OOP gibt, diejenige aus der Simula-Tradition (Java, C++ ...) und diejenige aus der Smalltalk-Tradition. Vieles aus der letzteren (Metaklassen, "alles ist ein Objekt" ...) sucht man in der ersteren vergeblich.
-
@Wutz
naja ich hab halt an der fh eine veranstaltung namens "einführung in die objektorientierte programmierung" gehabt und irgendwie hatte der stoff ungefähr soviel mit java zu tun gehabt, als dass wir da mal ein gebäude modellieren und dieses modell dann in java umsetzen sollten.
da ging es dann eher darum, irgendwelche uml-klassendiagramme zu malen und darin die attribute und methoden zu kapseln, beziehungen herzustellen, zu vererben, zugriffsmodifikatoren zu verwenden und dann noch um diverse entwurfsmuster.kann man ja von halten was man will, aber ein wenig übersichtlicher (und angeblich auch fehlerfreier, dynamischer etc) wird die sache dadurch ja schon und da wir ja fachkräftemangel haben und mehr oder weniger jeden nehmen müssen, sind solche sachen wohl erforderlich.
@Th69
hmmm also das wort "object" kommt tatsächlich sehr häufig in der dokumentation vor, aber mit dem, was ich in o.g. veranstaltung gelernt habe, hat das irgendwie überhaupt nichts zu tun, eher mit dem, was ich über prozedurale programmierung gelernt habe.@versionsnummer
endlich kann das mal jemand nachvollziehen!