Grundsatzfragen, Ungarische Notation



  • Videonauth schrieb:

    /*
     * Project: Basefile
     * File: Basefile for console applicationsa
     */
    
    /*
     * Documentation:
     *
     * 1.1 Naming Convntion
     *
     *	bool			<-->	b
     *	char			<-->	ch
     *	string			<-->	sz
     *	unsigned short		<-->	us
     *	short			<-->	s
     *	unsigned integer	<-->	ui
     *	integer			<-->	i
     *	unsigned long		<-->	ul
     *	long			<-->	l
     *	float			<-->	f
     *	double			<-->	d
     *	long double		<-->	ld
     *	function		<-->	fn
     *	class			<-->	cl
     *	union			<-->	un
     *	struct			<-->	st
     *	enum			<-->	en
     *	pointer			<-->	p
     *	array			<-->	a
     *	member(class)		<-->	mb
     */
    

    Das wird aber hässlich.



  • 100% schrieb:

    Videonauth schrieb:

    /*
     * Project: Basefile
     * File: Basefile for console applicationsa
     */
    .
    .
    .
    .
    

    Das wird aber hässlich.

    Das ist muss ich zugeben wenig konstruktiv!

    Gruss Micha



  • Videonauth schrieb:

    Das ist muss ich zugeben wenig konstruktiv!

    Das muss ich auch zugeben.
    Allerdings: Die "Hungarian Notation" ist im gesamten modernen C++ Umfeld ziemlich ungern gesehen. Man kann es halbherzig versuchen, aber dann bringt es nichts. Und man kann es wirklich bis in jede Ecke durchziehen - dann wird das System aber sehr komplex und Namen unnötig lang und unlesbar. Daher verzichte am besten komplett darauf. (Wie auch der Standard und so ziemlich jedes Buch und Coding Styles das machen.)

    Edit:
    Und zu den Kommentaren mit File, Prototypes etc.: Auch sparen. Wenn das alles so undurchsichtig wird, dass solche Kommentare helfen, dann ist das ein klares Zeichen dafür, dass du mal aufräumen, sprich den Kram in mehrere Dateien/Module aufteilen solltest. (Auch wenn sich nicht gerade alle open source Projekte daran halten. 🤡 )



  • OK, dann werd ich das nochmal überdenken.

    Gruss Micha



  • Wieviel Stellen (merke: nicht Nackkommastellen!) eine Fließkommazahl hat, kannst du so feststellen:

    size_t const max_precision_double = std::numeric_limits<double>::digits10;
    

    Für diese Methode musst du den <limits> -Header einbinden.
    OMC ist max_precision_double 18.

    Bspw. hast du eine Zahl die mit 52. Anfängt - die also zwischen 52 und 53 liegt - so kannst du sie bis auf die 16te Nachkommastelle genau in einem [/c]double[c] speichern.



  • Überleg dir welchen Mehrwert UN überhaupt bringt.
    Man sieht, wenn man die genaue Definition der Bezeichner kennt, sofort welchen Typ eine Variable hat. Das kann man Heute auch mit einer modernen IDE mit einem Maus-Hover auch herausfinden und hat dann ganz sicher den Typen und nicht möglicherweise eine nicht refaktorisierten Namen. Meistens geht aber der Typ einer Variable auch aus dem Kontext hervor.



  • Ah, ungarische Notation mal wieder. Das Thema kommt alle Nase lang mal wieder auf und ist mehr oder weniger heiß umstritten, aber es scheint eine Art Konsens zu geben, dass sie in der von dir beschriebenen Form (mit Typbezeichnern im Namen) unsinnig ist.

    Das grundsätzliche Problem damit ist, dass dir erstens der Typ im Namen nicht so richtig viel bringt und man sich zweitens erfahrungsgemäß nicht die Mühe macht, den Bezeichner überall zu ändern, wenn man man den Typen ändert. Irgendwann hast du doch

    double nPreis;
    

    irgendwo stehen.

    Etwas anderes ist es beim sog. "Applications Hungarian", bei der nicht der konkrete Datentyp, sondern ihr Zweck beschrieben wird. Ein praktisches Beispiel wäre die Unterscheidung zwischen unbereinigten und bereinigten Strings, etwa

    std::string usInput = get_stuff_from_network_socket(); // us = unsanitized
    std::string sInput  = sanitize(usInput);
    

    Auf die Art könne man später schneller sehen, dass bei

    do_sql(usInput);
    

    unbereinigter Input an die Datenbank durchgereicht wird, was tunlichst vermieden werden sollte.

    Dem kann man so oder so gegenüberstehen. Es ist natürlich sinnvoll, den Zweck einer Variable in ihrem Namen festzuhalten; ob man das jetzt in Prä- oder Postfixform und in CamelCase, javaCase oder underscore_separated macht, ist eher nebensächlich.

    Besser noch ist es, solche Dinge gleich im Typsystem zu verankern, im konkreten Beispiel etwa zwei Klassen unsanitized_string und sanitized_string zu haben, so dass der Compiler sich ggf. beschweren oder die Bereinigung automatisch bei der Umwandlung passieren kann. Das ist aber schon für Fortgeschrittene.



  • Schade das es hier keine Danke Buttons gibt aber ich muss mich mal bei dir bedanken seldon und natürlich auch bei den anderen Postern. ich denke ich werde es hier herauslassen obwohl ich dieses System eigendlich gewohnt bin. Am ende bleibt im compilierten sowiso nichts mehr davon übrig.

    Gruss Micha



  • Videonauth schrieb:

    Nun meine Frage ob sowas in C++ sinvoll ist

    Nicht wirklich.



  • @ NEXUS

    Dein Link Wäre einen Sticky wert. Das hätte meine Frage erst garnicht aufkommen lassen.

    Gruss Micha



  • Videonauth schrieb:

    /*
     * Globals
     */
    // Pi
    const long double PI = 3.1415926535897932;
    // Euler
    const long double EUL = 2.7182818284590452;
    

    Frage dazu ist eigendlich nur, wie viele nachkommastellen kann mein long double haben? Derzeit hab ich da 16 aber will dann schon die maximal mögliche Genauigkeit ausschöpfen.

    Nachkommastellen werden nicht definiert aber signifikante Dezimalstellen insgesamt als DBL_DIG bzw. LDBL_DIG in <cfloat>.

    const long double PI = 3.1415926535897932;
    

    ist auch suboptimal gelöst, da du die evtl. höhere Signifikanz von long double gegenüber double deines Compilers durch Weglassen des long-double-Typspezifizierers nicht ausnutzt.
    Besser also

    const long double PI = 3.1415926535897932L;
    


  • Wutz schrieb:

    Videonauth schrieb:

    /*
     * Globals
     */
    // Pi
    const long double PI = 3.1415926535897932;
    // Euler
    const long double EUL = 2.7182818284590452;
    

    Frage dazu ist eigendlich nur, wie viele nachkommastellen kann mein long double haben? Derzeit hab ich da 16 aber will dann schon die maximal mögliche Genauigkeit ausschöpfen.

    Nachkommastellen werden nicht definiert aber signifikante Dezimalstellen insgesamt als DBL_DIG bzw. LDBL_DIG in <cfloat>.

    const long double PI = 3.1415926535897932;
    

    ist auch suboptimal gelöst, da du die evtl. höhere Signifikanz von long double gegenüber double deines Compilers durch Weglassen des long-double-Typspezifizierers nicht ausnutzt.
    Besser also

    const long double PI = 3.1415926535897932L;
    

    Soweit ich weiß, erkennt der Compiler automatisch die entsprechenden Typen der Literale, wenn es um Größen geht. Aber Danke!



  • Hacker schrieb:

    Soweit ich weiß, [...]

    Eben. Es ist nicht so wie du weisst.

    Der Compiler erkennt zwar floats und doubles anhand der Länge, aber bei long double hört der Spass auf.

    Bei Fullquotes übrigens auf.



  • Ja, aber in diesem Fall braucht man nur ein double.
    Edit: Ah, stop. Ich dachte, ein double kann 18 Stellen speichern? Bei mir kann er nur 15. Dann reicht es wohl doch nicht, wobei man natürlich bedenken muss, dass man PI genauer als 14 Nachkommastellen theoretisch garnicht braucht.



  • Mit Hacke und Spaten schrieb:

    Der Compiler erkennt zwar floats und doubles anhand der Länge, aber bei long double hört der Spass auf.

    Unsinn.
    Jedes Fließkommaliteral ist zunächst mal double (egal ob es anschließend in irgendeinem Kontext intern vom Compiler gewandelt wird), deshalb gibt es die Typspezifizierer für float (f,F) und long double (l,L).



  • Hacker schrieb:

    wobei man natürlich bedenken muss, dass man PI genauer als 14 Nachkommastellen theoretisch garnicht braucht.

    Unsinn.
    Woher kennst du überhaupt sämtliche vorkommenden Anwendungsfälle, dass du sowas behauptest?
    Ab C99 (C++98 TR1) gibt es viele neue explizite long double Varianten in cmath bzw. ctgmath wie

    long double sinhl(long double);
    zusätzlich zum herkömmlichen
    double sinh(double);
    

    Gar nicht schreibt man gar nicht zusammen.



  • Videonauth schrieb:

    100% schrieb:

    Videonauth schrieb:

    /*
     * Project: Basefile
     * File: Basefile for console applicationsa
     */
    .
    .
    .
    .
    

    Das wird aber hässlich.

    Das ist muss ich zugeben wenig konstruktiv!

    Ein schönes hässliches Beispiel hast du ja mit deinem pachArgv schon gebracht. Da frag ich mich nur, was ist den ein pach? Meint er patch? 😕



  • pachArgv[] meinst du. Das wäre dann ein (p)ointer(a)array(ch)ar namens Argv[].

    Gruss Micha



  • Ist mir auch klar, wenn ich deine Ungarische Notation kenne, aber es ist einfach hässlich, wenn die Ungarische Notation schon bald wieder ein Wort ergibt.



  • Äh...
    Müsste das nicht eh dann "apch" heißen? Ist ja ein Array von Zeigern auf char*? "pach" wäre für mich nämlich nur ein Zeiger auf ein Array von chars. Und wie unterscheidest du das Zerfallen eines Arrays in einen Pointer bei der Übergabe an eine Funktion?
    Gibts dann auch ein "papch"? Oder chap, weils lustig klingt? Kann es sein, dass klingonisch aus der ungarischen Notation entstandenist?
    Mal wieder ernster: Welche Regel befolgst du bei der Zusammensetzung der einzelnen Präfix-Bausteine?


Anmelden zum Antworten