Was machen Programmier-Anfänger mit ihren Fragen?

Smalltalk
RobertDebiannutzer
Beiträge: 385
Registriert: 16.06.2017 09:52:36

Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von RobertDebiannutzer » 13.12.2018 09:09:57

Einleitung:
Ich schreibe gerade an einem file manager, der vom "spirit" her so ähnlich werden soll wie die Programme des "suckless"-Projekts.
Nun müssen bei einem file manager ja die Dateien sortiert angezeigt werden, also nutze ich qsort() und eine compare-Funktion. Dabei soll meine compare-Funktion
a) case insensitive sein (weiß nicht, wie das auf Deutsch heißt)
b) Zahlen berücksichtigen, so wie strverscmp() das kann (= "version sort", also "file10" soll z.B. größer sein als "file2")
c) utf-8 so gut es geht berücksichtigen können.


Habe also eine Funktion geschrieben, die das imho kann.
Nun bin ich ja Anfänger und wollte mal wissen, wie Profis meine Funktion bewerten würden. So geht es doch sicherlich auch x-Tausenden außer mir! Also gehe ich zu stackoverflow, weil ich denke, dass meine Frage dort eher am Platze sei als hier im Forum. Dort werde ich dann darauf hingwiesen, dass ich doch bitte zu codereview.stackexchange.com gehen soll und meine Frage dort richtig sei. Gehe ich also dorthin [1]. Zunächst finde ich mit Hilfe einer Anregung noch einen bug. Doch dann kamen Kommentare und eine Antwort, die mir nicht wirklich weiterhalfen. Meine Nachfragen wurde nicht beantwortet, sondern mein Thema wurde auf "[on hold]" gesetzt, also geschlossen, weil es angeblich "off topic" sei bzw. mein Code nicht funktionieren würde "to the best of the author's knowledge". Dabei funktioniert mein Code stets "to the best of the author's knowledge"! Natürlich kann es sein, dass er dann doch nicht funktioniert, weil ich halt noch Anfänger bin, aber deshalb frage ich ja nach! Und dann habe ich natürlich kein Problem damit, wenn mir jemand sagt: "Du, Deine Funktion ist echt schlecht.", aber das muss dann derjenige/diejenige mir doch auch erklären, sonst komme weder ich weiter, noch profitiert die Community davon.

Versteht vielleicht von euch jemand, was in dem verlinkten Thema von mir das Problem war bzw. mag mir das erklären? Das wäre sehr nett! Ich könnte natürlich versuchen in der "meta"-Abteilung der dortigen Community nachzufragen, doch ich befürchte, dass mir das wieder nicht wirklich weiterhelfen wird...

[1] https://codereview.stackexchange.com/qu ... th-strcoll

EDIT: Noch vergessen: Der von dem einen User vorgeschlagene unit-test hat den return value 0, beendet sich also erfolgreich.

Benutzeravatar
Gharika
Beiträge: 209
Registriert: 28.09.2004 16:51:51
Lizenz eigener Beiträge: GNU Free Documentation License

Re: Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von Gharika » 13.12.2018 09:53:44

Hallo,

also das Folgende ist meine persönliche Meinung, was nicht unbedingt richtig ist!

Die Platform, die du gewählt hast behandelt folgende Fälle:
security, maintainability, performance, and scalability
https://codereview.stackexchange.com/help/on-topic

Nichts davon ist dein Problem, deswegen wird es wohl als off-topic gesehen. Du willst eine Lösung zu einem technischen Problem... wohl die falsche Platform dafür.

Nun zu deinem eigentlichen Problem. Die "gelernten" Programmierer, versuchen meist nicht das Rad neu zu erfinden, sondern vorhandene Lösungen zu nutzen, die gut erbrobt und "bewiesen" sind. Wenn du es aber machst, um etwas zu lernen oder gar neues zu erfinden, ist dein Ansatz völlig in Ordnung.

Ich wäre wie folgt vorgegangen:
1. Einen vorhandenen "natural sort" Algorithmus verwenden (file9 > file10 Problem), gibt so einige davon, welcher für dich passt, musst du selbst rausfinden (z.B. https://github.com/sourcefrog/natsort)
2. Deine Ordnung ist eine "Eigene", definiere sie, z.B. "äÄaAbB...0123456789..." und prüfe das, statt den ASCII/UTF8 code. Tipp: ä und Ä können nicht gleich sein, auch die müssen eine Ordnung haben, sonst hast du zufällige Ergebnisse. äÄ und Ää wäre dann beides richtig und kann somit beides auftreten, das willst du sicher nicht.

Ich hoffe das hilft wenigstens etwas weiter...
Beleidigungen sind die Argumente derer, die unrecht haben.

-- Jean Jacques Rousseau

Benutzeravatar
Meillo
Moderator
Beiträge: 8813
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von Meillo » 13.12.2018 10:02:31

Ich finde schade, dass keine klare Begruendung kommt, *warum* der ``Code not implemented or not working as intended'' sei. Liegt es daran, dass andere kein strverscmp() haben? Oder liegt es daran, dass es scheinbar mit anderen Encodings (Latin1?) nicht funktioniert? Oder liegt es daran, dass falsch sortiert wird (Ää vs. Aa)?

Ich kenne die Community nicht, bekomme aber den Eindruck, dass der Fokus dort das reine Optimieren oder Absichern von Code ist, der schon vollumfaenglich funktioniert. Deine Frage geht aber in eine andere Richtung, habe ich den Eindruck: Du suchst einen Lernprozess beim Programmieren. Dafuer ist diese Community vielleicht einfach die falsche. Andererseits hast du ja eine hochwertige Analyse und verschiedene hilfreiche Kommentare zum Code zurueck bekommen. Insofern war das ja schon erfolgreich.
Use ed once in a while!

Benutzeravatar
Meillo
Moderator
Beiträge: 8813
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von Meillo » 13.12.2018 10:19:13

Gute Antwort, Gharika.

Gharika hat geschrieben: ↑ zum Beitrag ↑
13.12.2018 09:53:44
Tipp: ä und Ä können nicht gleich sein, auch die müssen eine Ordnung haben, sonst hast du zufällige Ergebnisse. äÄ und Ää wäre dann beides richtig und kann somit beides auftreten, das willst du sicher nicht.
Er hat kein Sort sondern ein Compare programmiert. Bei dem koennen schon zwei verschiedene Zeichen gleich sein, beispielsweise ``Ä'' und ``A'' oder ``é'' und ``e''. Das ist eine Frage der Collation. In Mysql kann man fuer eine Spalte beispielsweise ``COLLATE utf8_unicode_ci'' festlegen, was zur Folge hat, dass ``A'' gleich ``a'' ist. Verwendet man ``COLLATE utf8_bin'', dann ist ``A'' kleiner ``a''. Im ersten Fall koennen in einer sortierten Liste grosse und kleine A gemischt vorkommen, im zweiten Fall nicht. Sein Compare definiert selbst eine Collation-Sequence, die allerdings an manchen Stellen nicht optimal zu sein scheint (weil z.B. das Verhaeltnis von ``A'' zu ``a'' anders ist als das von ``Ä'' zu ``ä'').


Btw: Den Beitrag von Toby Speight finde ich richtig gut. Er zeigt dir wie du weiter kommst. Vielleicht brauchst du Hilfe beim Verstehen der Aussagen, aber die Aussagen sind gut (bist auf die Empfehlung fuer C++ :-P ).
Use ed once in a while!

RobertDebiannutzer
Beiträge: 385
Registriert: 16.06.2017 09:52:36

Re: Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von RobertDebiannutzer » 13.12.2018 10:36:27

Danke für eure Antworten.

Zu meiner Funktion:
Das Problem ist, dass ich ascii-Zeichen selber vergleichen kann, mich aber bei non-ascii-Zeichen auf strcoll() verlassen muss. D.h., dass ich nur meinen Teil beeinflussen kann, nicht strcoll(). Möglicherweise könnte ich das aber umgehen, wenn ich die Library-Funktion tolower() statt meines Eigenbaus verwenden würde, egal ob ascii, oder nicht. Dann könnte ich tolower() vor strcoll() einsetzen. Das geht aber nur, wenn tolower() (oder vielleicht towlower()) mit Multibyte-UTF-8 umgehen kann.
Dann wäre nur noch das Problem nicht-arabischer Zahlen, auf deren Vergleich ich keinen Einfluss mehr hätte. Außer die Library-Funktion isdigit() kann das. Dann könnte ich meine Funktion etwas umschreiben und hätte auch das gelöst.
Im Grunde genommen könnte ich mir dann auch meinen eigenen ascii-Vergleich sparen und nur strcoll verwenden. Das würde von der Performance her wohl wenig ausmachen, da ja strcoll nur gerufen würde, wenn zwei Zeichen nach tolower() unterschiedlich sind.

Zu der Antwort von "Toby Speight":
Vielleicht habe ich - insbesondere den ersten Teil - falsch verstanden und er meinte das, was ich gerade über isdigit() und tolower() schrieb.
Der unit-test soll so wie ich das verstehe, testen, ob a) die Funktion korrekt auf Gleichheit testet und b) es keine Rolle spielt, in welcher Reihenfolge die Argumente übergeben werden.
Das läuft ja auch erfolgreich mit seinem Beispiel. Aber was ist, wenn jetzt z.B. einmal bei test_lt "-1" herauskommt und bei test_eq "1"? Dann wäre der Rückgabewert des Testes ja auch 0 = Erfolg, obwohl zwei Fehler passiert sind. Da fände ich "printf-Debugging" sicherer?

Benutzeravatar
Meillo
Moderator
Beiträge: 8813
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von Meillo » 13.12.2018 10:46:00

RobertDebiannutzer hat geschrieben: ↑ zum Beitrag ↑
13.12.2018 10:36:27
Das Problem ist, dass ich ascii-Zeichen selber vergleichen kann, mich aber bei non-ascii-Zeichen auf strcoll() verlassen muss.
Warum willst du ASCII-Zeichen ueberhaupt selber vergleichen?
D.h., dass ich nur meinen Teil beeinflussen kann, nicht strcoll(). Möglicherweise könnte ich das aber umgehen, wenn ich die Library-Funktion tolower() statt meines Eigenbaus verwenden würde, egal ob ascii, oder nicht.
Man sollte immer vorhandene Bibliotheksfunktionen verwenden, wenn sie verfuegbar sind. (Geh davon aus, dass sie gut optimiert sind. Falls du Zweifel haben solltest, und es ueberhaupt zu langsam ist, dann messe mit einem Profiler wo das Bottleneck tatsaechlich ist.)
Dann könnte ich tolower() vor strcoll() einsetzen.
Dann wäre nur noch das Problem nicht-arabischer Zahlen,
Was meinst du damit? Roemische Zahlen? :-P
auf deren Vergleich ich keinen Einfluss mehr hätte. Außer die Library-Funktion isdigit() kann das. Dann könnte ich meine Funktion etwas umschreiben und hätte auch das gelöst.
Verwende isdigit(3), was das nicht kann wirst du wohl nicht brauchen.
Im Grunde genommen könnte ich mir dann auch meinen eigenen ascii-Vergleich sparen und nur strcoll verwenden.
Gute Idee. ;-)
Das würde von der Performance her wohl wenig ausmachen, da ja strcoll nur gerufen würde, wenn zwei Zeichen nach tolower() unterschiedlich sind.

Zu der Antwort von "Toby Speight":
Vielleicht habe ich - insbesondere den ersten Teil - falsch verstanden und er meinte das, was ich gerade über isdigit() und tolower() schrieb.
Damit solltest du jedenfalls mal anfangen.
Der unit-test soll so wie ich das verstehe, testen, ob a) die Funktion korrekt auf Gleichheit testet und b) es keine Rolle spielt, in welcher Reihenfolge die Argumente übergeben werden.
Das läuft ja auch erfolgreich mit seinem Beispiel. Aber was ist, wenn jetzt z.B. einmal bei test_lt "-1" herauskommt und bei test_eq "1"? Dann wäre der Rückgabewert des Testes ja auch 0 = Erfolg, obwohl zwei Fehler passiert sind. Da fände ich "printf-Debugging" sicherer?
Dann schau dir test_lt() nochmal genauer an. Das kann kein -1 liefern. ;-) (Der Trick ist, dass in C Boolean und Integer austauschbar sind.)
Use ed once in a while!

uname
Beiträge: 12072
Registriert: 03.06.2008 09:33:02

Re: Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von uname » 13.12.2018 10:59:00

Ich programmiere nicht so viel. Aber du solltest auch wenn du eine Standard-Funktion verwendest, diese über eine eigene Funktion kapseln, damit du sie einfacher austauschen kannst.

eggy
Beiträge: 3331
Registriert: 10.05.2008 11:23:50

Re: Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von eggy » 13.12.2018 11:34:17

Du könntest die Funktion weiter in kleine Subroutinen aufteilen. Zum Beispiel "bool checkIfStringsAreEqual(...)" Das würde Lesbarkeit und Testbarkeit erhöhen.

Schreibe Unittests für alle Teilfunktionen. Insbesondere auch Tests, bei denen Du erwartest, dass das Ergebnis Murks ist. In solchen Fällen sollte Dein Programm dann auch entsprechend Rückmeldung geben.

Wenn man Eingabedaten in einem bestimmten Schema/Sprache erwartet, dann sollte man das deutlich machen.
Solche Tests kann man (auch wenn es Geschwindigkeit kostet) am Anfang der Funktion abarbeiten. Will man diese Kosten einsparen, weil man es "kostenlos" an anderen Stellen mitgeliefert bekommt, wäre ein deutlicher Kommentar am Anfang der Funktion hilfreich.

Nimm aussagekräftigere Bezeichner.
"Code wird öffer gelesen als geschrieben". ISASCII ist grade noch verständlich, bei TL kann man schon nicht mehr sagen worum es geht. Grade wenn später Leute in größeren Team beurteilen sollen, ob Dein Code tut was er soll, ist es wichtig, dass es keine Zweifel daran gibt, was von ihm erwartet wird.
Allein für TL fallen mir ohne lange nachzudenken drei plausible Erklärungen ein:
ToLower (alle Zeichen in Kleinbuchstaben umwandeln)
ToL (alle Zeichen in jeweils 1 L umwandeln) bzw ToL (alle Zeichen in insgesammt ein L umwandeln)
ToLast (nur das letzte Zeichen nutzen, alles andere wegwerfen)
Ohne Kommentare kann beim Codereview niemand sagen, ob meine Funktion wirklich das tut was von ihr erwartet wird.

Wenn man sich Programmieren im Alleingang beibringst, gibt es eine Klippe, die oftmals gerne übersehen wird:
Semantische Fehler sind -grade von andern- sehr viel schwerer zu finden.
Deine Kollegen können nicht wissen, was für Dich absolut logisch ist. Wenn man Funktionen entwickelt, hat man eine gewisse Vorstellung, unter welchen Umständen wann welche Eingabedaten zu erwarten sind. Diese Vorstellung muss aber nicht stimmen. Du magst wissen "ich kann die Funktion nur bei ASCII anwenden", Du weißt, dass Du dafür gesorgt hast, dass die Funktion niemals mit was anderem ASCII Daten aufgerufen werden wird. Und Dir ist klar, dass Du ne neue Funktion schreiben musst, sobald UTF-8 nötig ist. Aber andere Leute in Deinem Team, die Deinen Code an anderer Stelle wiederverwenden, wissen das nicht. Sie können das nicht wissen. Alles, was für Dich in Deiner Vorstellung selbstverständlich ist, solltest Du aufschreiben, besser noch: am Anfang Deiner Funktion testen.
Während der Entwicklung hilft es die jeweiligen Stellen mit assert zu kennzeichnen, einfach damit das später nicht untergeht. Für Produktionscode sollten es dann aber richtige Fehlerbehandlungsroutinen sein.

Benutzeravatar
Meillo
Moderator
Beiträge: 8813
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von Meillo » 13.12.2018 11:35:34

uname hat geschrieben: ↑ zum Beitrag ↑
13.12.2018 10:59:00
Ich programmiere nicht so viel. Aber du solltest auch wenn du eine Standard-Funktion verwendest, diese über eine eigene Funktion kapseln, damit du sie einfacher austauschen kannst.
Wenn du geschrieben haettest ``eine Funktion von dritter Stelle'' (z.B. Github-Projekte), dann haette ich dir zugestimmt. Im Falle von tatsaechlichen Standard-Funktionen (wie tolower(3) oder isdigit(3)) halte ich das fuer unangebracht. Sonst muesste man ja die ganze Standardbibliothek kapseln. ;-)

Aber vielleicht verstehe ich dich ja nur nicht richtig. Hast du ein Beispiel, was du meinst?
Use ed once in a while!

uname
Beiträge: 12072
Registriert: 03.06.2008 09:33:02

Re: Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von uname » 13.12.2018 12:28:49

Meillo hat geschrieben:Aber vielleicht verstehe ich dich ja nur nicht richtig. Hast du ein Beispiel, was du meinst?
Naja. Im angegebenen Beispiel sollen z. B. Dateien sortiert angezeigt werden.

Als erstes würde ich in einer eigenen Funktion die Aufbereitung / Sortierung durchführen, die als Eingabe die nichtsortierten Daten erwartet und als Ausgabe die sortierten Daten bereitstellt. Innerhalb dieser eigenen Funktion ist es wahrscheinlich ausreichend direkt tolower() und isdigit() zu verwenden, da die Funktionen recht trivial sind.
Benötigt man aber komplexere Funktionen (z. B. Umwandlungen in irgendeine Form), so würde ich diese vielleicht auch auslagern.

Wichtig wäre mir aber vor allen, dass innerhalb des Hauptprogramms bzw. der Haupt-Funktionen der Ablauf übersichtlich bleibt.
Im Haupt-Programm bzw. Haupt-Funktion würde dann nur der Aufruf zur Aufbereitung / Sortierung aufgeführt, die Darstellung der Werte über eine weitere Funktion usw.

Wie gesagt ich programmiere nicht so oft.
Spätestens wenn durch gekapselte Funktionen und Mehrfachaufruf der Code kürzer wird, würde ich es nutzen wollen.
Der Code sollte lesbar bleiben. Das kann durch selbst definierte Funktionen bzw. Methoden sehr gut optimiert werden.
Hier mal ein Beispiel, welches mir schon zu unübersichtlich ist: viewtopic.php?f=34&t=171615&start=15#p1192049 (zudem stark gekürzt)

https://de.wikipedia.org/wiki/Spaghetticode
https://de.wikipedia.org/wiki/Prozedura ... rammierung (z. B. Programmiersprache C)
https://de.wikipedia.org/wiki/Objektori ... rammierung (z. B. Programmiersprache C++ und Java)

RobertDebiannutzer
Beiträge: 385
Registriert: 16.06.2017 09:52:36

Re: Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von RobertDebiannutzer » 13.12.2018 12:46:39

Vielen Dank für euren Input!

Ich werde mich noch einmal an meine Funktion ransetzen.
Die aufrufende Funktion in meinem file manager ist myreaddir(), Zeile 37: NoPaste-Eintrag40530 (vielleicht noch etwas zu unübersichtlich, aber ist ja auch noch in Entwicklung).
Wobei meine Funktion wegen der Übersetzung der Argumente von void-Pointern nach char-Pointern noch in eine Mini-Wrapper-Funktion kommt (so wie in der Manpage von qsort vorgeschlagen).
Die main()-Funktion dagegen ist schön übersichtlich: NoPaste-Eintrag40531

Benutzeravatar
Meillo
Moderator
Beiträge: 8813
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von Meillo » 13.12.2018 12:55:11

uname hat geschrieben: ↑ zum Beitrag ↑
13.12.2018 12:28:49
Meillo hat geschrieben:Aber vielleicht verstehe ich dich ja nur nicht richtig. Hast du ein Beispiel, was du meinst?
Naja. Im angegebenen Beispiel sollen z. B. Dateien sortiert angezeigt werden.
Eigentlich geht es um eine Compare-Funktion, die man dann bei qsort(3) verwenden kann.

Input sind zwei Stings; Output ist -1, 0 oder 1, je nachdem ob String eins kleiner, gleich oder groesser als String zwei ist.

Der Rest des Codes ist nur Rahmenwerk zum Testen.

Als erstes würde ich in einer eigenen Funktion die Aufbereitung / Sortierung durchführen, die als Eingabe die nichtsortierten Daten erwartet und als Ausgabe die sortierten Daten bereitstellt. Innerhalb dieser eigenen Funktion ist es wahrscheinlich ausreichend direkt tolower() und isdigit() zu verwenden, da die Funktionen recht trivial sind.
Benötigt man aber komplexere Funktionen (z. B. Umwandlungen in irgendeine Form), so würde ich diese vielleicht auch auslagern.

Wichtig wäre mir aber vor allen, dass innerhalb des Hauptprogramms bzw. der Haupt-Funktionen der Ablauf übersichtlich bleibt.
Im Haupt-Programm bzw. Haupt-Funktion würde dann nur der Aufruf zur Aufbereitung / Sortierung aufgeführt, die Darstellung der Werte über eine weitere Funktion usw.
Jetzt verstehe ich, wie du das meinst. Ja, in der Weise, stimme ich dir zu.

In dem Zusammenhang will ich gerne den Vorschlag von Toby Speight aufgreifen:
https://codereview.stackexchange.com/a/209542 hat geschrieben: Consider finding the first digit in each string. Then compare the substrings to that point using the standard function, then compare numbers, then return to substrings, etc until a mismatch or end-of-string.
Das liefert nicht nur ein anderes Vorgehen, sondern auch gleich eine Unterteilung der Funktion in Hilfsfunktionen. So koennte man den Code lesbarer machen.



Ganz grundsaetzlich solltest du, Robert, dich aber auch noch fragen, ob du eine derartige Sortierfunktion fuer deinen Filemanager ueberhaupt brauchst. Natuerlich ist diese Funktion ein nettes Beschaeftigungsobjekt. Du kannst in diesem Prozess eine Menge lernen, darum solltest du weiter daran arbeiten. Dein Filemanager wird aber nicht darauf angewiesen sein. Wenn es ueblich waere, eine solche Sortierfunktion zu verwenden, dann muesste ja jeder Filemanager sie implementieren. Dann gaebe es die bestimmt schon fertig. Da das nicht der Fall zu sein scheint, werden deine Nutzer sie vermutlich nicht unbedingt brauchen. Der ``richtige'' Ansatz waere auch eher, sich auf LC_COLLATE zu stuetzen, weil genau das die gewuenschte Collation-Order im System vorgibt. Nutzer koennen deinen Filemanager mit dem jeweiligen von ihnen gewuenschten Wert fuer LC_COLLATE aufrufen, der auch vom Wert fuer das Restsystem abweichen kann. Insofern waere es (wenn man dem ``richtigen'' Weg folgen will) eher angebracht, zu schauen, ob du deine gewuenschte Sortierreihenfolge nicht als Collation-Order fuer das Locale-System definieren kannst. Dann koennte man die im System installieren und anschliessend auswaehlen. (Ich weiss allerdings nicht, wie gross die Maechtigkeit dieses Systems ist, ob man da also Ziffern zu Zahlen zusammenfassen und numerisch vergleichen kann.) Das alles aber nur als Nebenbemerkung.
Use ed once in a while!

uname
Beiträge: 12072
Registriert: 03.06.2008 09:33:02

Re: Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von uname » 13.12.2018 12:56:43

Auszug Paste NoPaste-Eintrag40530

Code: Alles auswählen

qsort(&cdir[0], num+1, sizeof(char *), mycompare);
Wie sieht denn deine Funktion mycompare(const void * a, const void * b) überhaupt aus? Du hast doch bestimmt auch da einen kleinen Entwurf, oder?

Benutzeravatar
Lord_Carlos
Beiträge: 5578
Registriert: 30.04.2006 17:58:52
Lizenz eigener Beiträge: GNU Free Documentation License
Wohnort: Dänemark

Re: Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von Lord_Carlos » 13.12.2018 13:23:57

eggy hat geschrieben: ↑ zum Beitrag ↑
13.12.2018 11:34:17
Du könntest die Funktion weiter in kleine Subroutinen aufteilen. Zum Beispiel "bool checkIfStringsAreEqual(...)" Das würde Lesbarkeit und Testbarkeit erhöhen.
Dies ^
Versuch deine Methoden zwischen 10 und 15 Zeilen zu halten. Nicht als harte Regeln, aber als Richtlinie.

Code: Alles auswählen

╔═╗┬ ┬┌─┐┌┬┐┌─┐┌┬┐╔╦╗
╚═╗└┬┘└─┐ │ ├┤ │││ ║║
╚═╝ ┴ └─┘ ┴ └─┘┴ ┴═╩╝ rockt das Forum!

RobertDebiannutzer
Beiträge: 385
Registriert: 16.06.2017 09:52:36

Re: Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von RobertDebiannutzer » 13.12.2018 13:26:15

@uname:
Im Moment mache ich die Umwandlung von (const void *) nach (const char *) einfach in meiner compare-Funktion, die ich dazu am Anfang leicht anpasse, wenn ich sie in den Code meines file managers einfüge (also Argumente anpassen nach const void *p1 und *p2 und dann einfach s1 und s2 mit den konvertierten Pointern p1 und p2 belegen, alles andere bleibt dann gleich). Da ihr aber zurecht sagt, dass man Sachen lieber in mehrere Funktionen aufteilt, werde ich stattdessen eine Wrapper-Funktion wie in der Manpage von qsort dazwischenschalten.
Also wenn die Wrapper-Funktion z.B. mycompare_wrapper heißt:

Code: Alles auswählen

static int
mycompare_wrapper(const void *p1, const void *p2)
{
	return mycompare(* (char * const *) p1, * (char * const *) p2);
}
@meillo:
Den Vorschlag von Toby Speight hatte ich ganz am Anfang probiert und fand ihn nicht so gut. Ich glaube, ich fand ihn zu langsam, denn bei vielen "Buchstabe,Zahl, Buchstabe, Zahl..." Kombinationen, wo sich eine Differenz vielleicht erst spät ergibt, wird unnötig oft gehandelt. Da fand ich es besser, einfach über gleiche Zeichen zu loopen, bis man eine Differenz findet und dann erst zu handeln. Aber ich kann den Vorschlag ja trotzdem später nochmal probieren.
Vielen Dank für Deinen Vorschlag mit LC_COLLATE. Das sollte ich wirklich parallel auch mal prüfen.

@Lord_Carlos: Verstehe ich das richtig, dass Du meinst, dass man es so einrichten sollte, dass alle Funktionen nur zwischen 10 und 15 Zeilen lang sind?

eggy
Beiträge: 3331
Registriert: 10.05.2008 11:23:50

Re: Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von eggy » 13.12.2018 14:10:20

RobertDebiannutzer hat geschrieben: ↑ zum Beitrag ↑
13.12.2018 13:26:15
Verstehe ich das richtig, dass Du meinst, dass man es so einrichten sollte, dass alle Funktionen nur zwischen 10 und 15 Zeilen lang sind?
Ich denke, dass man da keine Zahl nennen kann. Außerdem: keine Regel ohne Ausnahme.

Es wird oft empfohlen, dass man Funktionen nicht größer schreiben sollte, als das was man noch gut "mit einem Blick" erfassen kann.
Früher war die Metrik dafür mal "eine (Bildschirm-)Seite". Da heute manche Leute aber ne halbe Kinoleinwand vor sich aufgebaut haben, nicht mehr in allen Fällen anwendbar. Außerdem kommt es sehr auf die benutzte Sprache an, manchmal ist ne Methode in der einen Sprache nen Dreizeiler, während in anderen dreizig Zeilen allein für die Initialisierung der Variablen nötig sind.

Versuche Code, wenn möglich, in kleinste "Sinneinheiten" aufzuteilen. Immer wenn Du nen Block mit if/while/etc vor Dir hast, der komplizierter als "ist die Zahl ungrade" ist, frag Dich: welchen Nachteil habe ich, wenn ich das hier in ne Funktion auslagere? Wenn Dir nicht sofort nen guter Grund einfällt: ab in ne eigene Funktion.

Spoiler: Die nächsten paar Monate wirst Du wirklich schrecklichen Code schreiben. Jeder Krümel Code wird in ner eigenen Funktion landen. Deine Header werden Kilometer lang. Keine Sorge. Das ist ok. Für jetzt. Zuerst nervt es dich. Ignorier das. Dann hast Du Dich dran gewöhnt. Dich wird es einige Zeit lang nicht stören. Dann nervt es Dich wieder. Das ist der richtige Zeitpunkt, anzufangen wieder etwas größere Funktionen zu schreiben. Jetzt solltest Du in der Lage sein, zu beurteilen, an welchen Stellen "Mikromodule" sinnvoll waren und an welchen Stellen es übertrieben war.

Benutzeravatar
Meillo
Moderator
Beiträge: 8813
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von Meillo » 13.12.2018 15:01:05

Am sinnvollsten finde ich es, viel guten Code zu lesen und darueber ein Gefuehl dafuer zu bekommen, wie man Code sinnvoll strukturiert und unterteilt. Natuerlich gibt es unterschiedliche Meinungen darueber, was guter Code ist. Da wird man sich nie komplett einig werden. Nur verschiedene groessere Ziele werden vermutlich gemeinsam angestrebt werden. Mit welchen Mitteln man das aber erreicht, da gibt es schon wieder Kulturunterschiede.

Ich empfehle, sich mit der Frage, was guter Code ist, zu beschaeftigen. Sich die Meinungen der verschiedenen Communities anzuhoeren und mit der eigenen Erfahrung und den eigenen Vorstellungen zu pruefen. Code zu diskutieren. So kann man sich ueber Jahre und Jahrzehnte gutem Code annaehern. Man wird meist Komprimisse machen muessen, weil sich manche Ziele widersprechen. Aber man sollte dies realisieren und begruenden koennen, warum man sich gerade so oder so entschieden hat.

Konkret: Implementiere dein mycompare() nun in anderer Weise und vergleiche anschliessend die beiden Varianten. Welche ist besser. Dann fertige nochmal eine neue Variante an ... Mache mal die Funktionen so klein wie moeglich und mal ziemlich gross. Lese vor allem fremden Code, der ganz kleine Funktionen hat und lese fremden Code, der grosse Funktionen hat. Lese verschiedene Implementierungen des gleichen Programms, z.B. GNU ed vs. Heirloom ed, oder verschiedene cut(1)-Implementierungen, wie ich es hier gemacht habe: http://marmaro.de/docs/freiesmagazin/cut/ . Wenn du Suckless magst, dann vergleiche deren 9base mit den GNU Coreutils und den entsprechenden BSD-Programmen. Oder vergleiche dwm mit larswm (der die engste Vorlage fuer dwm war), desweiteren kannst du dir dazu noch ion und ratpoison anschauen. Freie Software bietet diese Moeglichkeit, nutze sie! :-)
Use ed once in a while!

Benutzeravatar
MSfree
Beiträge: 10741
Registriert: 25.09.2007 19:59:30

Re: Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von MSfree » 13.12.2018 15:21:57

Meillo hat geschrieben: ↑ zum Beitrag ↑
13.12.2018 15:01:05
Am sinnvollsten finde ich es, viel guten Code zu lesen
Sowas? https://www.ioccc.org/

*SCNR*

Benutzeravatar
Meillo
Moderator
Beiträge: 8813
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von Meillo » 13.12.2018 15:39:14

MSfree hat geschrieben: ↑ zum Beitrag ↑
13.12.2018 15:21:57
Meillo hat geschrieben: ↑ zum Beitrag ↑
13.12.2018 15:01:05
Am sinnvollsten finde ich es, viel guten Code zu lesen
Sowas? https://www.ioccc.org/
Meillo hat geschrieben: ↑ zum Beitrag ↑
13.12.2018 15:01:05
Natuerlich gibt es unterschiedliche Meinungen darueber, was guter Code ist.
;-)
Use ed once in a while!

ViNic

Re: Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von ViNic » 14.12.2018 08:22:56

Meillo hat geschrieben: ↑ zum Beitrag ↑
13.12.2018 15:01:05
Natuerlich gibt es unterschiedliche Meinungen darueber, was guter Code ist. Da wird man sich nie komplett einig werden. Nur verschiedene groessere Ziele werden vermutlich gemeinsam angestrebt werden.
Entwicklerteams und Projekte haben oft auch Coderichtlinien, woran sich alle halten sollten. Ist auch eine Art von gutem Code.

Benutzeravatar
MSfree
Beiträge: 10741
Registriert: 25.09.2007 19:59:30

Re: Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von MSfree » 14.12.2018 08:40:58

ViNic hat geschrieben: ↑ zum Beitrag ↑
14.12.2018 08:22:56
Entwicklerteams und Projekte haben oft auch Coderichtlinien,...
Wir haben Uncrustify im Pre-Commit-Hook von Subversion (GIT-Migration steht noch aus). Code, der nicht den Anforderungen entspricht, darf gar nicht erst comittet werden.

ViNic

Re: Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von ViNic » 14.12.2018 09:51:14

MSfree hat geschrieben: ↑ zum Beitrag ↑
14.12.2018 08:40:58
ViNic hat geschrieben: ↑ zum Beitrag ↑
14.12.2018 08:22:56
Entwicklerteams und Projekte haben oft auch Coderichtlinien,...
Wir haben Uncrustify im Pre-Commit-Hook von Subversion (GIT-Migration steht noch aus). Code, der nicht den Anforderungen entspricht, darf gar nicht erst comittet werden.
Ich weiß nicht ob es stimmt, aber GitLab soll auch eine Qualitätsprüfung von Code machen. Habe es mir aber nur erzählen lassen. In wieweit das stimmt, kann ich jetzt nicht sagen, da ich GitLab nicht nutze und kenne. Aber vielleicht auch ein Tipp.

Edit: Ein nachträglich prüfender Blick auf GitLab (https://about.gitlab.com/) zeigt, das es eine Qualitätskontrolle wohl doch macht.
Zuletzt geändert von ViNic am 14.12.2018 09:55:44, insgesamt 1-mal geändert.

RobertDebiannutzer
Beiträge: 385
Registriert: 16.06.2017 09:52:36

Re: Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von RobertDebiannutzer » 14.12.2018 09:54:00

Jetzt bin ich fast fertig mit der neuen Version meiner Funktion, da fällt mir auf, warum der von "Toby Speight" vorgeschlagene, von @meillo unterstützte und von mir ja auch ursprünglich eingeschlagene Weg wohl doch besser als mein aktueller ist...
Der Hase liegt dort im Pfeffer, wo über die Continuation Bytes eines Multibyte-Encodings zurückgeloopt wird. Mit UTF-8 läuft das, aber was ist mit anderen Multibyte-Encodings? Ursprünglich hatte ich nur an ASCII und UTF-8 gedacht, aber es ist vielleicht kein Fehler, es doch etwas mehr zu generalisieren. Denn auch bei mir (also Debian 9) sehe ich in /etc/locale.gen doch auch ein paar Encodings, die nicht single-byte oder UTF-8 zu sein scheinen.
Und vor dem Hintergrund ist der "alternative approach" natürlich die einzige Möglichkeit. Also bis zu Zahlen loopen, danach mit strcoll() alles bis dahin vergleichen, wenn gleich, dann Zahlen vergleichen (und dabei Folgezahlen berücksichtigen), wenn gleich, dann von vorne. Kommt keine Zahl vor, ist es ja eh einfach.
Schade, hat Spaß gemacht mit ASCII und UTF-8 zu arbeiten und sich dabei auch mit der Hexadezimal-Darstellung zu beschäftigen... :( Und schneller war es auch. Aber natürlich geht Funktionalität vor, sonst bringt mir ja auch die Geschwindigkeit nichts.
Apropos Geschwindigkeit:

@eggy: Bezüglich Deines Spoilers - ich glaube nicht, dass mir das passieren wird. Denn da ich mit shell-Scripten angefangen habe, habe ich immer noch die Tendenz, zu viel auf die Performance zu achten, auch wenn die Situation bei C ja eigentlich ganz anders ist. Insofern denke ich nicht, dass ich in das von Dir beschriebene Extrem umschwanken werde. Eher werde ich mich hoffentlich langsam der "Normalform" annähern... Aber vielleicht kommt es ja doch anders, ich werde es ja sehen. :)

@meillo:
Sehr interessant, Dein Artikel über cut! Wusste gar nicht, was das alles kann. Ich habe das bisher immer mit den Optionen "-d" und "-f" genutzt - wenn überhaupt, denn meistens habe ich versucht, das aus Performance-Gründen wegzulassen und die Aktion, die cut durchgeführt hätte, woanders reinzuschmuggeln (z.B. in einen Aufruf von sed, den ich sowieso hatte, oder in eine shell-Funktionalität wie "${variable#delimiter}" - je nachdem). Ich weiß auch nicht, was ich immer mit der Performance habe...

ViNic

Re: Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von ViNic » 14.12.2018 10:06:42

RobertDebiannutzer hat geschrieben: ↑ zum Beitrag ↑
14.12.2018 09:54:00
Jetzt bin ich fast fertig mit der neuen Version meiner Funktion, da fällt mir auf, warum der von "Toby Speight" vorgeschlagene, von @meillo unterstützte und von mir ja auch ursprünglich eingeschlagene Weg wohl doch besser als mein aktueller ist...
Willkommen in der Welt der Programmierung. Das ist normal. Bedenke das du erst angefangen hast und es real viele Jahre dauern wird, bis du darin auch wirklich gut wirst. Besonders am Anfang wirst du viele Fehler machen. Aber wenn du dabei bleibst und dich darum bemühst besser zu werden, wirst du auch besser. Außerdem wirst du dann auch mal über deinen alten Code oft staunen und sich vielleicht fragen, was hast du dir damals dabei gedacht :mrgreen:

Ich habe heute mein erstes Projekt, ein WebCRM, durch Zufall wieder gefunden. Ich will es jetzt gar nicht aufmachen und sehen was da drin steht :lol:

Benutzeravatar
novalix
Beiträge: 1909
Registriert: 05.10.2005 12:32:57
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: elberfeld

Re: Was machen Programmier-Anfänger mit ihren Fragen?

Beitrag von novalix » 14.12.2018 13:54:08

Die Einstufung Deiner Frage als "nicht einschlägig" auf der Codereview-Plattform finde ich ein wenig voreilig.
Aber manchmal ist das so, wenn man versucht in komplexen Feldern (ab)grenzende Fäden zu spannen (working code und so). Dabei ist es häufig genug so, dass die Fragen, die von Neulingen aufgeworfen werden, den Eingeweihten dazu auffordern, die damit zusammenhängenden Probleme verständlich - und damit sauber - zu (re)formulieren.
Das kann natürlich zuweilen lästig sein, oder gar die unangenehme Ahnung auslösen, dass das eigene Verständnis löchrig ist. Das ist meiner bescheidenen Meinung nach so wie so der Normalzustand; kein Grund für Scham.[1]
RobertDebiannutzer hat geschrieben: ↑ zum Beitrag ↑
14.12.2018 09:54:00

Schade, hat Spaß gemacht mit ASCII und UTF-8 zu arbeiten und sich dabei auch mit der Hexadezimal-Darstellung zu beschäftigen... :( Und schneller war es auch. Aber natürlich geht Funktionalität vor, sonst bringt mir ja auch die Geschwindigkeit nichts.
Ohne Scheiß, der Spaß ist viel, viel wichtiger als oftmals angenommen.
Der eingeschlagene Weg führt nicht zu dem Gehöft, das man zu erreichen gedenkt? Sei 's drum.
Man hat einen Teil des Feldes erkundet, an den Blumen geschnuppert, die dort wachsen und die Sicht von diesem Standpunkt aus ergänzt die Vorstellung der Gegend. Manchmal justiert man sogar seinen Kompass neu.

Nach Donald E. Knuth sind 97% der Optimierungen "premature". Wir sollten sie vergessen. Aber die restlichen, wichtigen drei Prozent sollten wir uns keinesfalls durch die Lappen gehen lassen.[2]

[1]Ich schließe da von mir auf andere. Das ist selbstverständlich nicht beweisbar, aber eben auch "normal".

[2]https://en.wikiquote.org/wiki/Donald_Kn ... Art_(1974)
Das Wem, Wieviel, Wann, Wozu und Wie zu bestimmen ist aber nicht jedermannns Sache und ist nicht leicht.
Darum ist das Richtige selten, lobenswert und schön.

Antworten